diff options
Diffstat (limited to 'book/ru/src/internals/ceilings.md')
| -rw-r--r-- | book/ru/src/internals/ceilings.md | 93 |
1 files changed, 91 insertions, 2 deletions
diff --git a/book/ru/src/internals/ceilings.md b/book/ru/src/internals/ceilings.md index 2c645a4..df9901a 100644 --- a/book/ru/src/internals/ceilings.md +++ b/book/ru/src/internals/ceilings.md @@ -1,3 +1,92 @@ -# Ceiling analysis +# Анализ приоритетов -**TODO** +*Поиск максимального приоритета* ресурса (*ceiling*) - поиск динамического +приоритета, который любая задача должна иметь, чтобы безопасно работать с +памятью ресурсов. Анализ приоритетов - относительно прост, +но критичен для безопасности памяти RTIC программ. + +Для расчета максимального приоритета ресурса мы должны сначала составить +список задач, имеющих доступ к ресурсу -- так как фреймворк RTIC +форсирует контроль доступа к ресурсам на этапе компиляции, он +также имеет доступ к этой информации на этапе компиляции. +Максимальный приоритет ресурса - просто наивысший логический приоритет +среди этих задач. + +`init` и `idle` не настоящие задачи, но у них есть доступ к ресурсам, +поэтому они должны учитываться при анализе приоритетов. +`idle` учитывается как задача, имеющая логический приоритет `0`, +в то время как `init` полностью исключается из анализа -- +причина этому в том, что `init` никогда не использует (не нуждается) критические +секции для доступа к статическим переменным. + +В предыдущем разделе мы показывали, что разделяемые ресусы +могут быть представлены уникальными ссылками (`&mut-`) или скрываться за +прокси в зависимости от того, имеет ли задача к ним доступ. +Какой из вариантов представляется задаче зависит от приоритета задачи и +максимального приоритета ресурса. +Если приоритет задачи такой же, как максимальный приоритет ресурса, тогда +задача получает уникальную ссылку (`&mut-`) на память ресурса, +в противном случае задача получает прокси -- это также касается `idle`. +`init` особеннвй: он всегда получает уникальные ссылки (`&mut-`) на ресурсы. + +Пример для иллюстрации анализа приоритетов: + +``` rust +#[rtic::app(device = ..)] +mod app { + struct Resources { + // доступен из `foo` (prio = 1) и `bar` (prio = 2) + // -> CEILING = 2 + #[init(0)] + x: u64, + + // доступен из `idle` (prio = 0) + // -> CEILING = 0 + #[init(0)] + y: u64, + } + + #[init(resources = [x])] + fn init(c: init::Context) { + // уникальная ссылка, потому что это `init` + let x: &mut u64 = c.resources.x; + + // уникальная ссылка, потому что это `init` + let y: &mut u64 = c.resources.y; + + // .. + } + + // PRIORITY = 0 + #[idle(resources = [y])] + fn idle(c: idle::Context) -> ! { + // уникальная ссылка, потому что + // приоритет (0) == максимальному приоритету ресурса (0) + let y: &'static mut u64 = c.resources.y; + + loop { + // .. + } + } + + #[interrupt(binds = UART0, priority = 1, resources = [x])] + fn foo(c: foo::Context) { + // прокси-ресурс, потому что + // приоритет задач (1) < максимальному приоритету ресурса (2) + let x: resources::x = c.resources.x; + + // .. + } + + #[interrupt(binds = UART1, priority = 2, resources = [x])] + fn bar(c: foo::Context) { + // уникальная ссылка, потому что + // приоритет задачи (2) == максимальному приоритету ресурса (2) + let x: &mut u64 = c.resources.x; + + // .. + } + + // .. +} +``` |
