Вся правда об ОСРВ. Статья #12. Службы для работы с задачами



    Продолжаем рассматривать службы ОСРВ, предоставляющие дополнительную информацию о задачах и операциях с ними.

    К дополнительным вызовам API, связанным с задачами, относятся вызовы получения ID задачи, проверки объема стека, сброса задачи, получения информации о задаче и определение количества задач в системе. Nucleus RTOS и Nucleus SE обеспечивают 4 основных вызова API для этих операций, о которых я расскажу в этой статье.

    Предыдущие статьи серии:
    Статья #11. Задачи: конфигурация и введение в API
    Статья #10. Планировщик: дополнительные возможности и сохранение контекста
    Статья #9. Планировщик: реализация
    Статья #8. Nucleus SE: внутреннее устройство и развертывание
    Статья #7. Nucleus SE: введение
    Статья #6. Другие сервисы ОСРВ
    Статья #5. Взаимодействие между задачами и синхронизация
    Статья #4. Задачи, переключение контекста и прерывания
    Статья #3. Задачи и планирование
    Статья #2. ОСРВ: Структура и режим реального времени
    Статья #1. ОСРВ: введение.

    Получение ID текущей задачи


    Этот служебный вызов возвращает ID вызываемой задачи. Для Nucleus RTOS это указатель на блок управления текущей задачи. Для Nucleus SE – индекс (0-15) текущей задачи.

    Вызов текущей задачи в Nucleus RTOS
    Прототип служебного вызова:
    NU_TASK *NU_Current_Task_Pointer(VOID);

    Параметры:
    Отсутствуют.

    Возвращаемое значение:
    Указатель на блок управления текущей задачи;
    NU_NULL – нет выполняемой задачи.

    Вызов текущей задачи в Nucleus SE
    Этот API-вызов поддерживает основной функционал API Nucleus RTOS.

    Прототип служебного вызова:
    NUSE_TASK NUSE_Task_Current(void);

    Параметры:
    Отсутствуют.

    Возвращаемое значение:
    Индекс текущей (вызываемой) задачи.

    Выполнение текущей задачи в Nucleus SE
    Реализация вызова API в данном случае довольно проста: возвращается значение глобальной переменной NUSE_Task_Active.

    Проверка доступного объёма стека


    Этот служебный вызов возвращает доступный объём стека (в байтах) для текущей задачи. Это целесообразно только для планировщиков, где каждая задача имеет свой собственный стек; т.е. не подойдет для планировщика Run To Completion (RTC) в Nucleus SE.

    Вызов информации об объеме стека в Nucleus RTOS
    Прототип служебного вызова:
    UNSIGNED NU_Task_Check_Stack(VOID);

    Параметры:
    Отсутствуют.

    Возвращаемое значение:
    Размер доступного объема стека для текущей задачи в байтах.

    Вызов информации о размере стека в Nucleus SE
    Этот вызов API поддерживает основной функционал API Nucleus RTOS. Однако в Nucleus SE требуется формальный (dummy) параметр, чтобы упростить получение значения указателя на используемый стек.

    Прототип служебного вызова:
    U16 NUSE_Task_Check_Stack(U8 dummy);

    Параметры:
    dummy – любое значение, поскольку фактически оно не используется.

    Возвращаемое значение:
    Размер доступного объёма стека для текущей задачи в байтах.

    Реализация
    Для такого вызова код должен быть переносимым:



    Если используется планировщик RTC, возвращаемое значение 0, поскольку невозможно (при использовании переносимого кода) определить доступное для задачи пространство стека.

    В других случаях значение указателя стека определяется нахождением адреса параметра dummy, который будет находиться почти в начале стека. Строго говоря, такой метод зависит от средств разработки/компилятора, но всегда будет рабочим. Возвращаемое значение – это разница между этим значением и первоначальным значением пространства стека, переведенная в байты.

    Сброс задачи


    Вызов API, в данном случае, возвращает задачу в ее первоначальное неиспользуемое состояние. Такая функция API отличается от обычных функций сброса API для других объектов ядра, хотя бы потому что это именно сброс, а не простое установление задачи в ее начальное состояние (для Nucleus SE это либо NUSE_READY, либо запись NUSE_Task_Initial_State[] (см. Структуры данных в следующей статье)); задача переводится в состояние приостановки (NUSE_PURE_SUSPEND) и должна быть возобновлена, для того чтобы снова быть поставленной на планирование. Такая логика похожа на функционал соответствующего вызова API в Nucleus RTOS.

    Вызов сброса задачи в Nucleus RTOS
    Прототип служебного вызова:
    STATUS NU_Reset_Task(NU_TASK *task, UNSIGNED argc, VOID *argv);

    Параметры:
    task – указатель на блок управления задачей;
    argc – элемент данных, который может использоваться для передачи информации в задачу;
    argv – указатель, который может использоваться для передачи информации в задачу.

    Возвращаемое значение:
    NU_SUCCESS – вызов успешно выполнен;
    NU_INVALID_TASK – некорректный указатель на задачу;
    NU_NOT_TERMINATED – описываемая задача не находится в состоянии полной приостановки (terminated) или завершения (finished); только задачи в состоянии приостановки или завершения могут быть сброшены.

    Вызов сброса задачи в Nucleus SE
    Этот API-вызов поддерживает основной функционал API Nucleus RTOS.

    Прототип служебного вызова:
    STATUS NUSE_Task_Reset(NUSE_TASK task);

    Параметры:
    task – индекс (ID) задачи, которую необходимо сбросить.

    Возвращаемое значение:
    NUSE_SUCCESS – вызов успешно выполнен;
    NUSE_INVALID_TASK – некорректный индекс задачи.

    Реализация сброса задачи в Nucleus SE
    Основное назначение API функции NUSE_Task_Reset() после проверки параметра – повторная инициализация всех структур данных задачи:



    Если задача заблокирована при вызове API для ожидания доступа к объекту ядра, первое, что необходимо сделать, настроить счетчик заблокированных задач, соответствующих объекту. Это осуществляется оператором switch.

    Затем структуры данных задачи инициализируются (в основном, нулями, кроме ее контекстного блока) с помощью вызова функции инициализации NUSE_Init_Task(). Её выполнение более детально будет рассмотрено в следующей статье с описанием инициализации системы. Наконец, статус задачи устанавливается в NUSE_PURE_SUSPEND.

    Получение информации о задаче


    Этот служебный вызов позволяет получить частичную информацию о задаче. Реализация Nucleus SE отличается от Nucleus PLUS, в которой возвращается меньше информации, поскольку присваивание объектам имен, вытеснение менее приоритетной задачи и квант времени не поддерживаются, а приоритет не возвращается, будучи избыточной информацией.

    Вызов получения информации о задаче в Nucleus RTOS
    Прототип служебного вызова:
    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 – указатель на переменную для получения минимального количества байт, остававшихся в стеке.

    Возвращаемое значение:
    NU_SUCCESS – вызов успешно выполнен;
    NU_INVALID_TASK – некорректный указатель на задачу.

    Вызов получения информации о задаче в Nucleus SE
    Этот вызов поддерживает основной функционал API Nucleus PLUS.

    Прототип служебного вызова:
    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, ничего не возвращается).

    Возвращаемое значение:
    NUSE_SUCCESS – вызов успешно выполнен;
    NUSE_INVALID_TASK – некорректный индекс задачи;
    NUSE_INVALID_POINTER – параметры указателей (один или более) некорректны.

    Реализация получения информации о задаче в Nucleus SE
    Реализация этого API-вызова довольно проста:



    Функция возвращает статус задачи, учитывая различные возможности конфигураций.

    Получение количества задач


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

    Вызов получения количества задач в Nucleus RTOS
    Прототип служебного вызова:
    UNSIGNED NU_Established_Tasks(VOID);

    Параметры:
    Отсутствуют

    Возвращаемое значение:
    Число установленных (созданных и не удаленных) задач в приложении.

    Вызов получения количества задач в Nucleus SE
    Этот вызов API поддерживает основной функционал API Nucleus PLUS.

    Прототип служебного вызова:
    U8 NUSE_Task_Count(void);

    Параметры:
    Отсутствуют

    Возвращаемое значение:
    Количество сконфигурированных задач в приложении.

    Реализация
    Реализация этого вызова API довольно проста: возвращается значение директивы #define NUSE_TASK_NUMBER.

    В следующей статье будут рассмотрены структуры данных в Nucleus SE, связанные с задачами и некоторыми стандартными вызовами API, не поддерживаемыми Nucleus SE.

    Об авторе: Колин Уоллс уже более тридцати лет работает в сфере электронной промышленности, значительную часть времени уделяя встроенному ПО. Сейчас он — инженер в области встроенного ПО в Mentor Embedded (подразделение Mentor Graphics). Колин Уоллс часто выступает на конференциях и семинарах, автор многочисленных технических статей и двух книг по встроенному ПО. Живет в Великобритании. Профессиональный блог Колина, e-mail: colin_walls@mentor.com.

    О переводе: этот цикл статей показался интересным тем, что, несмотря на местами устаревшие описываемые подходы, автор очень понятным языком знакомит малоподготовленного читателя с особенностями ОС реального времени. Я сам принадлежу к коллективу создателей российской ОСРВ, которую мы предполагаем сделать бесплатной, и надеюсь, что цикл будет полезен начинающим разработчикам.
    Поделиться публикацией

    Комментарии 0

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

    Самое читаемое