Руководство по Ada (Ada 2022)
D.3 Блокировка по приоритету потолка
Этот подпункт описывает взаимодействия между планированием задач по приоритету и потолками защищенных объектов. Это взаимодействие основано на концепции приоритета потолка защищенного объекта.
Синтаксис
Форма директивы Locking_Policy следующая:
pragma Locking_Policy(policy_идентификатор);
Правила легальности
policy_идентификатор должен быть либо Ceiling_Locking, либо определенным реализацией идентификатором.
Правила после компиляции
Директива Locking_Policy — это конфигурационная директива.
Динамическая семантика
Политика блокировки определяет детали блокировки защищенных объектов. Все защищенные объекты имеют приоритет. Политика блокировки определяет значение приоритета защищенного объекта и взаимосвязь между этими приоритетами и приоритетами задач. Кроме того, политика определяет состояние задачи при выполнении защищенного действия и то, как на ее активный приоритет влияет блокировка. Политика блокировки задается директивой Locking_Policy. Для реализаций политик блокировки, определенных реализацией, значение приоритета защищенного объекта определяется реализацией. Если ни одна директива Locking_Policy не применяется к каким-либо из программных модулей, составляющих партицию, политика блокировки для этой партиции, а также значение приоритета защищенного объекта, определяются реализацией.
Выражение, указанное для аспекта Priority или Interrupt_Priority (см. D.1), вычисляется при создании соответствующего защищенного объекта и преобразуется в подтип System.Any_Priority или System.Interrupt_Priority соответственно. Значение выражения — начальный приоритет соответствующего защищенного объекта. Если для защищенного объекта не указан аспект Priority или Interrupt_Priority, начальный приоритет задается политикой блокировки.
Существует одна предопределенная политика блокировки, Ceiling_Locking; эта политика определяется следующим образом:
- Каждый защищенный объект имеет приоритет потолка, который определяется аспектом Priority или Interrupt_Priority, как определено в D.1, или присваиванием атрибуту Priority, как описано в D.5.2. Приоритет потолка защищенного объекта (или коротко, потолок) является верхней границей активного приоритета задачи, когда она вызывает защищенные операции этого защищенного объекта.
- Начальный приоритет потолка защищенного объекта равен начальному приоритету этого объекта.
- Если для защищенной подпрограммы защищенного типа указан аспект Interrupt_Handler или Attach_Handler (см. C.3.1), а аспект Priority или Interrupt_Priority не указан, начальный приоритет защищенных объектов этого типа определяется реализацией, но в диапазоне подтипа System.Interrupt_Priority.
- Если ни аспект Priority, ни аспект Interrupt_Priority не указаны для защищенного типа, и ни одна защищенная подпрограмма типа не имеет указанного аспекта Interrupt_Handler или Attach_Handler, то начальный приоритет соответствующего защищенного объекта — System.Priority'Last.
- Во время выполнения задачи защищенного действия она наследует приоритет потолка соответствующего защищенного объекта.
- Когда задача вызывает защищенную операцию, проверяется, что ее активный приоритет не выше потолка соответствующего защищенного объекта; Program_Error возбуждается, если эта проверка завершается неудачно.
Если для приоритета потолка защищенного объекта указана политика диспетчеризации задач EDF_Within_Priorities, применяются следующие дополнительные правила:
- Каждый защищенный объект имеет относительный срок, который определяется аспектом Relative_Deadline, как определено в D.2.6, или присваиванием атрибуту Relative_Deadline, как описано в D.5.2. Относительный срок защищенного объекта представляет собой нижнюю границу относительного срока задачи, когда она вызывает защищенную операцию этого защищенного объекта.
- Если аспект Relative_Deadline не указан для защищенного типа, то начальный относительный срок соответствующего защищенного объекта — Ada.Real_Time.Time_Span_Zero.
- Пока задача выполняет защищенное действие над защищенным объектом P, она наследует относительный срок P. В этом случае пусть DF будет 'сейчас' ('сейчас' получается с помощью вызова Ada.Real_Time.Clock в начале действия) плюс пол потолка P. Если активный срок задачи позже DF, ее активный срок уменьшается до DF; активный срок остается без изменений в противном случае.
- Когда задача вызывает защищенную операцию, проверяется, что разница между ее активным сроком и последним временем выпуска не меньше относительного срока соответствующего защищенного объекта; Program_Error возбуждается, если эта проверка завершается неудачно.
Ограниченные (временные) ошибки
После любого изменения приоритета активный приоритет любой задачи с очередью вызовов на вход защищенного объекта должен быть ниже приоритета потолка защищенного объекта. В этом случае выполняется одно из следующих действий:
- в любой момент до выполнения тела входа, Program_Error возбуждается в вызывающей задаче;
- когда вход открыт, тело входа выполняется с приоритетом потолка защищенного объекта;
- когда вход открыт, тело входа выполняется с приоритетом потолка защищенного объекта, а затем Program_Error возбуждается в вызывающей задаче; или
- когда вход открыт, тело входа выполняется с приоритетом потолка защищенного объекта, который действовал в момент очереди вызова входа.
Разрешения реализации
Реализация может округлять все потолки в определенном поддиапазоне System.Priority или System.Interrupt_Priority до верхнего предела этого поддиапазона равномерно.
Реализации разрешается определять другие политики блокировки, но не требуется поддерживать указание более одной политики блокировки на партицию.
Поскольку реализациям разрешается накладывать ограничения на код, выполняемый с активным приоритетом на уровне прерывания (см. C.3.1 и D.2.1), реализация может реализовать языковую функцию в терминах защищенного объекта с реализацией определенным потолком, но потолок должен быть не меньше Priority'Last.
Рекомендации по реализации
Реализация должна использовать имена, заканчивающиеся на «_Locking», для реализаций политик блокировки, определенных реализацией.
ПРИМЕЧАНИЕ 1 Пока задача выполняется в защищенном действии, она может быть прервана только задачами, активные приоритеты которых выше, чем приоритет потолка защищенного объекта.
ПРИМЕЧАНИЕ 2 Если защищенный объект имеет приоритет потолка в диапазоне Interrupt_Priority, определенные прерывания блокируются во время выполнения защищенных действий этого объекта. В крайнем случае, если потолок — Interrupt_Priority'Last, все блокируемые прерывания блокируются в течение этого времени.
ПРИМЕЧАНИЕ 3 Как описано в C.3.1, всякий раз, когда прерывание обрабатывается одной из защищенных процедур защищенного объекта, проверяется, что его приоритет потолка находится в диапазоне Interrupt_Priority.
ПРИМЕЧАНИЕ 4 При задании потолка защищенного объекта правильное значение — это значение, которое не меньше наивысшего активного приоритета, при котором задачи могут выполняться при вызове защищенных операций этого объекта. При определении этого значения учитываются следующие факторы, которые могут влиять на активный приоритет: эффект Set_Priority, вложенные защищенные операции, вызовы входов, активация задач и другие факторы, определенные реализацией.
ПРИМЕЧАНИЕ 5 Привязка защищенной процедуры, чей потолок ниже аппаратного приоритета прерывания, к прерыванию приводит к ошибочному выполнению программы (см. C.3.1).
ПРИМЕЧАНИЕ 6 В реализации на одном процессоре правила приоритета потолка гарантируют, что нет возможности тупика, связанного только с защищенными подпрограммами (за исключением случая, когда защищенная операция вызывает другую защищенную операцию над тем же защищенным объектом).