VDK потік очікування (Idle Thread), dsp, programming

Idle thread це спочатку визначений системою VDK потік очікування, який автоматично створюється в наборі ідентифікаторів потоків з ідентифікатором ThreadID, рівним 0, і пріоритетом, який нижчий від найнижчого пріоритетного потоку з усіх потоків користувача. Таким чином, коли у черзі готовності (ready queue) немає жодного потоку користувача (всі потоки перебувають у стані сну на заданий час, або заблоковані на семафорах), буде працювати потік Idle. Єдине, що робить Idle thread, це збирання сміття, тобто звільнення ресурсів потоків, які були знищені. Іншими словами, потік очікування обробляє знищення потоків, які були передані у виклик DestroyThread() зі значенням FALSE у параметрі inDestroyNow. Після виконання цієї роботи потік очікування просто зациклюється, не виконуючи жодної роботи і не переводячи процесор у стан очікування або режим зниженого енергоспоживання, тому що тоді зупиниться таймер ядра і всі сервіси VDK, що працюють з реальним часом (див. нижче "Таймер").

Залежно від платформи можна налаштувати певні параметри Idle thread, такі як розмір стека і купу, з якої задовольняються запити до виділень пам'яті (включаючи стек для Idle). Для отримання додаткових подробиць див. онлайн Help. Тут можуть бути залежні від процесора вимоги до властивостей потоку Idle (див. додаток A "Processor-Specific Notes" [1] або переклад цієї документації [4]).

Процесорний час, який програма витрачає у всіх потоках крім Idle thread, показано графіком на закладці Target Load інформаційного вікна State History середовища розробки VisualDSP++ (відкривається через меню View - VDK Windows - History). Докладніше про вікно історії див. розділ "VDK State HistoryWindow" онлайн-help.

При складанні проекту VDK у Вас є опція додати додаткову налагоджувальну інформацію та код, що виконується шляхом вибору у властивостях проекту варіанта Full Instrumentation (закладка Kernel, розділ дерева System -> Instrumentation Level). Інструментальна збірка відрізняється від не інструментальної тим, що в інструментальній збірці доданий зайвий код, що збирає статистику по потоках, що виконуються (thread statistic logging). Цей додатковий запис у лог трохи віднімає ресурси процесора на виклики спеціального API, але допомагає у налагодженні, щоб можна було відстежити активність компонентів системи.

[Вікно VDK State History ]

VDK записує в лог певні користувачем події та зміни стану системи з використанням кільцевого буфера. Подія реєструється у буфері історії (history buffer) за допомогою виклику LogHistoryEvent(). Виклик LogHistoryEvent() записує в лог 4 значення даних: ThreadID викликаного потоку, тик в момент виклику, перерахування і значення, специфічне для цього перерахування. Перерахунки менше ніж 0 зарезервовані для використання всередині VDK. Для додаткової інформації за типом перерахування історії (history enumeration) див. Визначення HistoryEnum.

потік

Надається API для отримання майже всіх даних, які відображаються у вікні VDK Status, так що ця інформація стає доступною у програмі VDK. Докладніше це API описано у розділі 5, "VDK API Reference", також див. [2, 3].

Є можливість або замінити підпрограми VDK history logging, або додати функцію, що визначається користувачем, в існуючий механізм history logging (див. [2]).

[Вікно Target Load ]

Інструментальні збірки VDK дозволяють розробнику аналізувати завантаження процесора впротягом минулого періоду часу. Обчислене навантаження відображається графічно у вікні Target Load. Хоча це обчислення не є точним, графік допомагає оцінити рівень використання ресурсів процесора. Зверніть увагу, що інформація на графіку оновлюється в момент зупинки програми VDK у налагоджувачі. Для більш точного обчислення див. приклад LoadMeasurement, який знаходиться в каталозі інсталяції VisualDSP++.

programming

Графік Target Load показує відсоток часу, який цільовий процесор (target) проводить у обчислення на потоці очікування (Idle thread). Навантаження 0% означає, що програма VDK постійно проводить у потоці очікування. Навантаження 100% означає, що код потоку очікування практично не виконується. Дані навантаження обробляються вікном усереднення, що переміщається. Навантаження у відсотках обчислюється для кожного тику, і всі тики усереднюються. Для обчислення процентного навантаження (Load) на кожному тику використовується така формула:

Load = 100% * (1 - (#idle / (#threads +#idle ))))

#idle кількість часу, проведеного в потоці очікування на момент цього тику#threads кількість часу, проведеного в потоках на момент цього тику

Додаткову інформацію про графік Target Load див. онлайн-help.

Примітка: інформація VDK у вікнах State History та Target Load доступна лише для складання в конфігурації Debug, навіть якщо для конфігурації Release на закладці Kernel вибрано Instrumentation Level -> Full Instrumentation.

[Вікно VDK Status ]

Спільно з інформацією історії та завантаження процесора інструментальна збірка збирає статистику за компонентами VDK: коли потік був створений, його останній запуск, кількість запусків потоку, використання стека потоком і т.д.відображаються у вікні статусу (VDK Status), і інформація в ньому оновлюється в момент припинення налагодження.

Для отримання більшості інформації цього вікна надається API, завдяки чому можна отримувати ці дані статистики під час роботи програми, без зупинки налагодження. Докладніше це API описано в розділі 5 "VDK API Reference" (див. також [2, 3]).

Додаткову інформацію про графік VDK Status див. онлайн-help.

Примітка: інформація VDK Status доступна як для складання Debug, так і для складання Release, якщо включена інструментальна підтримка (у властивостях проекту на закладці Kernel вибрано Instrumentation Level - Full Instrumentation).

[Таймер ]

Тики (VDK Ticks) обчислюються за таймером, реалізованим у внутрішньому ядрі процесорів Blackfin. Цей таймер засинхронізований з основною частотою ядра CCLK. Однак, робота цього таймера заборонена, коли процесор Blackfin входить в режим низького енергоспоживання (low power mode). Таким чином, всі служби VDK, пов'язані відліком реального часу (такі як вхід потоку до сну на заданий час, робота періодичних семафорів), не працюють, коли ядро ​​знаходиться в стані IDLE або low power mode. За умовчанням VDK не використовує та не модифікує таймери загального призначення.

На процесорах Blackfin можна зареєструвати переривання за допомогою бібліотечної функції register_handler() або через виклик API системних служб adi_int_CECHook(), тоді не потрібно декларувати переривання на закладці проекту VDK Kernel. Переривання, зареєстровані поза конфігурацією VDK, не повинні використовувати той самий рівень IVG, що і будь-яке переривання, визначене закладкою VDK Kernel.

[Використання переривання стека потоку ]

Через те, що код всіх потоків працює врежимі супервізора, немає автоматичного перемикання між покажчиками користувальницького та системного стека. Таким чином, всі ISR виконуються з використанням стека поточного потоку, під час активності якого відбулося переривання. Це означає, що розмір стека кожного потоку повинен мати достатньо місця як самого потоку, так і для вимог обробників переривань (ISR). Це також стосується і розміру стека потоку очікування (Idle thread), що можна конфігурувати засобами середовища розробки VisualDSP++ (додаткову інформацію див. онлайн-Help). Коли дозволено вкладення переривань один одного, то настає найгірший сценарій виділення місця у пам'яті під стек, оскільки вимоги до стеку від окремих ISR можуть складатися. Коли вкладення переривань заборонено, то задоволення вимог до розміру стеку з боку ISR потрібно враховувати лише вимога від потоку, який найбільше займає пам'яті в стеку.

[Як визначити завантаження процесора? ]

Процесор, який виконує VDK-додаток Blackfin, ніколи не зупиняється і завжди виконує якісь обчислення, які розподілені між потоками системи. Непродуктивні обчислення, які не пов'язані з корисною роботою програми, зосереджені в потоці очікування (Idle Thread). Таким чином, щоб дізнатися, наскільки завантажений процесор корисною роботою, потрібно:

1. Дізнатися, скільки процесорного часу минуло. У тиках або одиницях рахунки таймера ядра, не важливо. Припустимо, що цей час дорівнюєT.2. Дізнатися, скільки часу процесор перебуває у потоці очікування. Припустимо, що цей час дорівнюєTidle.3. Обчислити завантаження процесора корисною роботою за формулою (у відсотках):

LOAD = 100* (1 -Tidle/T)

Все досить просто, залишилося лише отримати значення T та Tidle. Найпростіше це зробити, якщо скористатися статистикою, яку накопичує так зване інструментальне складання проекту VDK. Складання називається інструментальним за термінологією компанії Analog Devices, яка розробила бібліотеки VDK таким чином, що проект VDK можна зібрати в 3 варіантах - Full Instrumentation (варіант повної інструментальної підтримки, який накопичує статистику за системою та потоками), Error Checking (цей варіант забезпечений лише перевіркою помилок) і None (програмісту не надається додаткової налагоджувальної інформації за проектом VDK, що налагоджується).

Інформацію Full Instrumentation можна, якщо зупинити програму у відладчику, і відкрити вікна VDK State History, VDK Target Load, VDK Status (доступно через меню View - VDK Windows). Але як отримати цю інформацію в додатку, runtime, не вдаючись до допомоги відладчика, не порушуючи роботи програми?

На щастя, існує спеціальне API [2, 3], яке дозволяє дістатися цієї інформації з коду програми. Значення часу T у тиках можна отримати викликом функції GetUptime(), а час Tidle у тиках можна отримати викликом функції GetThreadTickData. Приклад:

Зверніть увагу, що у функцію GetThreadTickData передано 0 як ідентифікатор потоку, тому що це значення завжди дорівнює ідентифікатор потоку очікування. Майте на увазі, що виведене завантаження у відсотках не враховує процесорний час, який ядро ​​проводить у обчисленнях драйверів пристроїв, якщо їхній код працює в контексті домену переривань.

А як дізнатися, скільки процесорного часу забирає кожен потік? Теж досить просто, якщо отримати список працюючих потоків і дізнатися про їхні ідентифікатори. Це тежробиться викликами API. Приклад:

Буде виведено список на кшталт наступного (ID потоку, ім'я потоку, % процесорного часу):

Майте на увазі, що ці приклади коду будуть працювати і для конфігурації Debug, і для конфігурації Release, але лише за умови, якщо вибрано варіант бібліотек VDK з повною інструментальною підтримкою (налаштовується у властивостях проекту на закладці Kernel, розділ System -> Instrumentation Level , тут має бути обраний варіант Full Instrumentation).