Продолжаем рассматривать службы ОСРВ, предоставляющие дополнительную информацию о задачах и операциях с ними.
К дополнительным вызовам API, связанным с задачами, относятся вызовы получения ID задачи, проверки объема стека, сброса задачи, получения информации о задаче и определение количества задач в системе. Nucleus RTOS и Nucleus SE обеспечивают 4 основных вызова API для этих операций, о которых я расскажу в этой статье.
Этот служебный вызов возвращает ID вызываемой задачи. Для Nucleus RTOS это указатель на блок управления текущей задачи. Для Nucleus SE – индекс (0-15) текущей задачи.
Реализация вызова API в данном случае довольно проста: возвращается значение глобальной переменной NUSE_Task_Active.
Этот служебный вызов возвращает доступный объём стека (в байтах) для текущей задачи. Это целесообразно только для планировщиков, где каждая задача имеет свой собственный стек; т.е. не подойдет для планировщика Run To Completion (RTC) в Nucleus SE.
Этот вызов API поддерживает основной функционал API Nucleus RTOS. Однако в Nucleus SE требуется формальный (dummy) параметр, чтобы упростить получение значения указателя на используемый стек.
Если используется планировщик RTC, возвращаемое значение 0, поскольку невозможно (при использовании переносимого кода) определить доступное для задачи пространство стека.
В других случаях значение указателя стека определяется нахождением адреса параметра dummy, который будет находиться почти в начале стека. Строго говоря, такой метод зависит от средств разработки/компилятора, но всегда будет рабочим. Возвращаемое значение – это разница между этим значением и первоначальным значением пространства стека, переведенная в байты.
Вызов API, в данном случае, возвращает задачу в ее первоначальное неиспользуемое состояние. Такая функция API отличается от обычных функций сброса API для других объектов ядра, хотя бы потому что это именно сброс, а не простое установление задачи в ее начальное состояние (для Nucleus SE это либо NUSE_READY, либо запись NUSE_Task_Initial_State[] (см. Структуры данных в следующей статье)); задача переводится в состояние приостановки (NUSE_PURE_SUSPEND) и должна быть возобновлена, для того чтобы снова быть поставленной на планирование. Такая логика похожа на функционал соответствующего вызова API в Nucleus RTOS.
NU_SUCCESS – вызов успешно выполнен;
NU_INVALID_TASK – некорректный указатель на задачу;
NU_NOT_TERMINATED – описываемая задача не находится в состоянии полной приостановки (terminated) или завершения (finished); только задачи в состоянии приостановки или завершения могут быть сброшены.
Основное назначение API функции NUSE_Task_Reset() после проверки параметра – повторная инициализация всех структур данных задачи:
Если задача заблокирована при вызове API для ожидания доступа к объекту ядра, первое, что необходимо сделать, настроить счетчик заблокированных задач, соответствующих объекту. Это осуществляется оператором switch.
Затем структуры данных задачи инициализируются (в основном, нулями, кроме ее контекстного блока) с помощью вызова функции инициализации NUSE_Init_Task(). Её выполнение более детально будет рассмотрено в следующей статье с описанием инициализации системы. Наконец, статус задачи устанавливается в NUSE_PURE_SUSPEND.
Этот служебный вызов позволяет получить частичную информацию о задаче. Реализация Nucleus SE отличается от Nucleus PLUS, в которой возвращается меньше информации, поскольку присваивание объектам имен, вытеснение менее приоритетной задачи и квант времени не поддерживаются, а приоритет не возвращается, будучи избыточной информацией.
Прототип служебного вызова:
STATUS NU_Task_Information(NU_TASK *task, CHAR *name, DATA_ELEMENT *task_status, UNSIGNED *scheduled_count, OPTION *priority, OPTION *preempt, UNSIGNED *time_slice, VOID **stack_base, UNSIGNED *stack_size, UNSIGNED *minimum_stack;
task – указатель на задачу, информация о которой запрашивается;
name – указатель на 8-символьную строку для имени задачи; включает область для нулевых символов;
task_status – указатель на переменную, которая получает текущее значение статуса задачи;
scheduled_count – указатель на переменную, которая получает значение счетчика, сколько раз задача была добавлена в планировщик;
priority – указатель на переменную для получения приоритета задачи;
preempt – указатель на переменную для опций вытеснения менее приоритетной задачи; NU_PREEMPT показывает, что задача может быть вытеснена, и NU_NO_PREEMPT показывает, что задача не может быть вытеснена;
time_slice – указатель на переменную для получения значения кванта времени задачи; значение 0 показывает, что квантование времени для данной задачи невозможно;
stack_base – указатель на переменную для получения адреса стека задачи;
stack_size – указатель на переменную для получения размера стека задачи;
minimum_stack – указатель на переменную для получения минимального количества байт, остававшихся в стеке.
STATUS NUSE_Task_Information(NUSE_TASK task, U8 *task_status, U16 *scheduled_count, ADDR *stack_base, U16 *stack_size);
task – индекс задачи, о которой запрашивается информация;
task_status – указатель на переменную U8, которая получает текущее значение статуса задачи (если состояние ожидания задачи недоступно, ничего не возвращается);
scheduled_count – указатель на переменную U16, которая получает значение счетчика количества задач, добавляемых в планировщик (если счетчик планируемых задач отключен, то ничего не возвращается);
stack_base – указатель на переменную ADDR, которая получает адрес стека задачи (если используется планировщик RTC, ничего не возвращается);
stack_size – указатель на переменную U16, которая получает размер стека задачи (если используется планировщик RTC, ничего не возвращается).
Функция возвращает статус задачи, учитывая различные возможности конфигураций.
Этот служебный вызов возвращает информацию о количестве задач, сконфигурированных в приложении. В то время как в Nucleus RTOS это количество может меняться, и возвращаемое значение будет представлять текущее количество задач на данный момент, в Nucleus SE возвращаемое значение устанавливается при сборке и не больше не меняется.
Реализация этого вызова API довольно проста: возвращается значение директивы #define NUSE_TASK_NUMBER.
В следующей статье будут рассмотрены структуры данных в Nucleus SE, связанные с задачами и некоторыми стандартными вызовами API, не поддерживаемыми Nucleus SE.
Об авторе: Колин Уоллс уже более тридцати лет работает в сфере электронной промышленности, значительную часть времени уделяя встроенному ПО. Сейчас он – инженер в области встроенного ПО в Mentor Embedded ( подразделение Mentor Graphics). Колин Уоллс часто выступает на конференциях и семинарах, автор многочисленных технических статей и двух книг по встроенному ПО. Живет в Великобритании. Профессиональный блог Колина: https://blogs.mentor.com/colinwalls/, e-mail: colin_walls@mentor.com