Современная электроника №9/2023
СОВРЕМЕННЫЕ ТЕХНОЛОГИИ 8 WWW.SOEL.RU СОВРЕМЕННАЯ ЭЛЕКТРОНИКА • № 9 / 2023 жительность выполнения секции кода при запрещённых прерываниях долж - на быть строго ограничена констан - той , чтобы разработчик мог рассчитать заранее , сможет ли задача среагиро - вать на событие с заданной макси - мальной задержкой [7]. Уровень SPL_ SYNC используется при изменении данных центральных сервисов ядра , таких как планировщик . Исполнение пользовательских нитей происходит на уровне SPL_LOW, позволяющем прерываться любыми источниками . За консистентность данных поль - зовательских приложений отвеча - ют примитивы синхронизации , пре - доставляемые ядром . В некоторых конфигурациях FX-RTOS возможно использование дополнительных про - межуточных уровней SPL, что услож - няет реализацию , но позволяет гиб - че и быстрее реагировать на события . Помимо управления прерывани - ями , при наличии аппаратной под - держки используются более сложные механизмы , такие как неблокирую - щая синхронизация с атомарными инструкциями и спин - блокировки в симметричных многопроцессорных системах (SMP). Реализация потоков Входом в ядро является ф y нкция fx_kernel_entry , вызывающая fx_thread_ init , где инициализируются контейне - ры системных объектов : список пла - нируемых потоков , список таймеров . Создаётся и добавляется в очередь пла - нировщика поток idle с уникальным , наименьшим приоритетом из возмож - ных . Поток idle необходим для коррект - ного функционирования ОС , чтобы замещать пользовательские потоки при отсутствии активных задач . Перед входом в нормальный режим работы устанавливается пользовательский уровень SPL_LOW . Это означает , что обработка любых прерываний разре - шена , и потоки будут вытесняться дру - гими потоками и прерываниями . На заключительном шаге инициализа - ции вызывается функция fx_app_init() , которую определяет программист для создания начальных пользовательских объектов и задач . Каждая нить имеет персональные секции под код и стек . Указатели на функцию входа и область , выделен - ную под стек , передаются в конструк - тор потока fx_thread_init , который создаёт контекст в памяти , инициа - лизирует структуру fx_thread_t, храня - щую состояние нити . Здесь хранятся параметры планирования ( приоритет , квант ), ссылка для подключения в оче - редь ожидания , структуры для мани - пуляций программным таймером , кон - текст ( рис . 5). Глобальная переменная g_current_ thread хранит указатель на структу - ру fx_thread_t текущего активного потока . Архитектура планировщика Планировщик обладает внутренним состоянием fx_sched_context_t , адресу - емым глобальной переменной global_ domain. Экземпляр хранит ссылку на планировочную структуру активно - го потока , ссылку на очереди гото - вых потоков ( g_domain ) и другие поля ( рис . 6). Атрибут g_domain типа fx_sched_ container_t содержит информацию обо всех потоках , готовых к выполне - нию , и их приоритетах . Массив из оче - редей потоков использует структуру rtl_queue , реализующую абстрактный связный список , способный содер - жать любые объекты [8]. Двухуровне - вая битовая карта приоритетов хра - нит все номера приоритетов (0…1023 в 32- битной системе ) готовых потоков и позволяет за кратчайшее время опре - делить наиболее приоритетную оче - редь ( рис . 7). При добавлении нового потока его приоритет отмечается единичными битами в Map1 и Map2 с индексами : Idx map 1 = Priority / Bitwidth int Процедура планирования ( вызов fx_ sched_container_get ) сводится к опре - делению приоритетнейшей непустой очереди и извлечении первого элемен - та из неё . Необходимо заметить , что фактический приоритет обратно про - порционален его номеру . Наивысший приоритет определяется по самым <fx thread > int task_func() Стек Приоритет Регистры do { } ... } while(1) waiter : fx_sync_waiter_t sched_item : fx_sched_item timestice : uint32_t timer : fx timer_internal_t timer_event : fx_timer_internal_t completion : fx_event_internal_t hw_context : hal_cpu_context.t state_lock : lock_t state fx thread_state_t ... Рис . 5. Параметры потока Рис . 6. Диаграмма классов управляющих структур планировщика global_domain : fx_sched_context_t g_domain : fx_sched_container_t active : fx_sched_item_t <fx_sched_params_t> resched_pending : bool changes_counter : unsigned g_domain : fx_sched_container_t *active : fx_sched_item_t peiority_queues[] : rtl_queue_t map1 : usigned map2[] : unsigned prio : unsigned linkrtl_queuq_linkage_t : rtl_queue_linkage_t suspend_count : unsigned sched_params : fx_sched_params_t
RkJQdWJsaXNoZXIy MTQ4NjUy