Читаем Real-Time Interrupt-driven Concurrency полностью

// уменьшить (восстановить) динамический приоритет до `1`

unsafe { basepri::write(224) }

// ПРИМЕЧАНИЕ: BASEPRI содержит значение `224` в этот момент

// обработчик UART0 восстановит значение `0` перед завершением

}

}

<p id="Инвариант_basepri"><strong><a l:href="#Инвариант_basepri">Инвариант BASEPRI</a></strong></p>

Инвариант, который фреймворк RTIC должен сохранять в том, что значение BASEPRI в начале обработчика прерывания должно быть таким же, как и при выходе из него. BASEPRI может изменяться в процессе выполнения обработчика прерывания, но но выполнения обработчика прерывания в начале и конце не должно вызвать наблюдаемого изменения BASEPRI.

Этот инвариант нужен, чтобы избежать уеличения динамического приоритета до значений, при которых обработчик не сможет быть вытеснен. Лучше всего это видно на следующем примере:

#![allow(unused)]

fn main() {

#[rtic::app(device = ..)]

mod app {

struct Resources {

#[init(0)]

x: u64,

}

#[init]

fn init() {

// `foo` запустится сразу после завершения `init`

rtic::pend(Interrupt::UART0);

}

#[task(binds = UART0, priority = 1)]

fn foo() {

// BASEPRI равен `0` в этот момент; динамический приоритет равен `1`

// `bar` вытеснит `foo` в этот момент

rtic::pend(Interrupt::UART1);

// BASEPRI равен `192` в этот момент (из-за бага); динамический приоритет равен `2`

// эта функция возвращается в `idle`

}

#[task(binds = UART1, priority = 2, resources = [x])]

fn bar() {

// BASEPRI равен `0` (динамический приоритет = 2)

x.lock(|x| {

// BASEPRI увеличен до `160` (динамический приоритет = 3)

// ..

});

// BASEPRI восстановлен до `192` (динамический приоритет = 2)

}

#[idle]

fn idle() -> ! {

// BASEPRI равен `192` (из-за бага); динамический приоритет = 2

// это не оказывает эффекта, из-за значени BASEPRI

// задача `foo` не будет выполнена снова никогда

rtic::pend(Interrupt::UART0);

loop {

// ..

}

}

#[task(binds = UART2, priority = 3, resources = [x])]

fn baz() {

// ..

}

}

}

ВАЖНО: давайте например мы забудем восстановить BASEPRI в UART1 -- из-за какого нибудь бага в генераторе кода RTIC.

#![allow(unused)]

fn main() {

// код, сгенерированный RTIC

mod app {

// ..

#[no_mangle]

unsafe fn UART1() {

// статический приоритет этого прерывания (определен пользователем)

const PRIORITY: u8 = 2;

// сделать снимок BASEPRI

let initial = basepri::read();

let priority = Cell::new(PRIORITY);

bar(bar::Context {

resources: bar::Resources::new(&priority),

// ..

});

// БАГ: ЗАБЫЛИ восстановить BASEPRI на значение из снимка

basepri::write(initial);

}

}

}

В результате, idle запустится на динамическом приоритете 2 и на самом деле система больше никогда не перейдет на динамический приоритет ниже 2. Это не компромис для безопасности памяти программы, а влияет на диспетчеризацию задач: в этом конкретном случае задачи с приоритетом 1 никогда не получат шанс на запуск.

<p id="Анализ_приоритетов"><strong><a l:href="#Анализ_приоритетов">Анализ приоритетов</a></strong></p>

Поиск максимального приоритета ресурса (ceiling) - поиск динамического приоритета, который любая задача должна иметь, чтобы безопасно работать с памятью ресурсов. Анализ приоритетов - относительно прост, но критичен для безопасности памяти RTIC программ.

Перейти на страницу:

Похожие книги

Компьютерные сети. 6-е изд.
Компьютерные сети. 6-е изд.

Перед вами шестое издание самой авторитетной книги по современным сетевым технологиям, написанное признанным экспертом Эндрю Таненбаумом в соавторстве со специалистом компании Google Дэвидом Уэзероллом и профессором Чикагского университета Ником Фимстером. Первая версия этого классического труда появилась на свет в далеком 1980 году, и с тех пор каждое издание книги неизменно становилось бестселлером. В книге последовательно изложены основные концепции, определяющие современное состояние компьютерных сетей и тенденции их развития. Авторы подробно объясняют устройство и принципы работы аппаратного и программного обеспечения, рассматривают все аспекты и уровни организации сетей — от физического до прикладного. Изложение теоретических принципов дополняется яркими, показательными примерами функционирования интернета и компьютерных сетей различного типа. Большое внимание уделяется сетевой безопасности. Шестое издание полностью переработано с учетом изменений, произошедших в сфере сетевых технологий за последние годы, и, в частности, освещает такие технологии, как DOCSIS, 4G и 5G, беспроводные сети стандарта 802.11ax, 100-гигабитные сети Ethernet, интернет вещей, современные транспортные протоколы CUBIC TCP, QUIC и BBR, программно-конфигурируемые сети и многое другое.

Дэвид Уэзеролл , Ник Фимстер , Эндрю Таненбаум

Учебные пособия, самоучители