Как правило, при блокировке ядра RTOS просто планировщик не будет работать, поэтому переключения контекста не произойдет. Часто некоторые или все прерывания также отключены. Блокировка используется для критических разделов — разделов кода, которые должны выполняться без прерывания или вытеснения.
Я не эксперт в ChibiOS, но в этом отношении она кажется несколько чрезмерно сложной и не очень подробно документирована. Состояния ядра описаны здесь. Он имеет два режима блокировки, и chSysLock()
вызывает состояние S-Locked, где
"Ядро заблокировано, а обычные источники прерываний отключены. Включены быстрые источники прерываний. В этом состоянии можно вызывать API S-класса и I-класса."
Из документации неясно, означает ли это, что можно использовать только API I/S-класса или что I/S-mode
API можно вызывать только в заблокированном состоянии. Все состояние и его цель не определены ИМО. Однако в некоторых RTOS обычно используются специальные версии функций, которые не вызывают планировщик, это избавляет обычные функции API от накладных расходов, связанных с необходимостью проверки состояния ядра или контекста прерывания, и является незначительной оптимизацией (за счет безопасности в мое мнение). Это подтверждается документацией для chBSemSignalI:
Примечание
Эта функция не перепланируется.
[...]
Класс функции:
Это API I-класса, эта функция может быть вызвана из зоны блокировки системы как потоками, так и обработчиками прерываний.
В вашем примере происходит то, что семафор задан, но планировщик не будет запущен, поэтому любой ожидающий поток не будет немедленно готов. Неясно, вызывает ли chSysUnlock()
запуск планировщика — в документации сказано: «Специальная функция, к этой функции предъявляются особые требования, см. примечания.», но не указано, где эти примечания можно найти.
Я ожидаю, что планировщик запустится, и, на первый взгляд, функция sem_cb()
не имеет большого смысла; однако я также ожидаю, что chSysLock()/chSysUnlock()
будет вложенным, и в этом случае цель функции имеет больше смысла. Это позволяет использовать одну функцию передачи семафора (sem_cb()
) независимо от состояния ядра. То есть безопасно вызывать как в обычном, так и в S-состоянии, но добавляет накладные расходы, которых призваны избежать отдельные API-интерфейсы S-состояния/нормального состояния. Лично я всегда стремился к безопасности (хотя и не обязательно реализовывал ее таким образом), по крайней мере, до тех пор, пока не было показано, что накладные расходы неприемлемы. По сути, он говорит: «_дайте семафор, и если ядро не заблокировано, перепланируйте, в противном случае отложите перепланирование до тех пор, пока ядро не будет разблокировано, то есть после последней вложенной разблокировки».
Однако он не позволяет вызывать sem_cb()
из контекста прерывания, поскольку для этого потребуется chSysLockFromISR()
.
Вышеизложенное делает много предположений из документации и «ожидаемого» поведения RTOS. Если бы мне довелось использовать ChibOS перед лицом такой скудной документации, я бы проверил исходный код, чтобы определить точное поведение.
person
Clifford
schedule
01.04.2018