Jump to content

    
Sign in to follow this  
AHTOXA

Выпущена scmRTOS 4.0.

Recommended Posts

ваш вариант TNKernel : 2.83uS для LPC1768, @100МГц,

scmRTOS: 2.55uS STM32F103 @72MHz (приведённое к 100МГц - 1.83uS).

Более чем в полтора раза однако :)

Та не™ :biggrin:

Сравнивать надо на одинаковых процах, одинаковый прикладной код, одинаковым методом (скопом импульс на одной и той же ножке наблюдаем, например), с одинаковыми опциями компилятора, и исполнением из одного и того же места (из флеша, да :), и с одинаковыми waitstates). В упомянутой теме апдейт давний написан - включаешь у компилятора оптимизацию по скорости - и уже имеем 2.50uS на 1768@100МГц для TNKernel. BTW, я там еще оптимизаций добавил, надо бы потестить - а то что-то давно я ерундой не страдал :biggrin:

 

 

Share this post


Link to post
Share on other sites
У меня нет ни IAR-а ни LCP17xx :)

BTW, а не было ли среди ваших оптимизаций TNKernel-а отключения round-robin? :biggrin:

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

Я постараюсь при возможности попробовать scmRTOS 4.0 на той же платформе. Думаю что результаты будут очень близкими. Потому как при грамотной структуре данных реализация round-robin не так уж и страшна.

Share this post


Link to post
Share on other sites
Думаю что результаты будут очень близкими. Потому как при грамотной структуре данных реализация round-robin не так уж и страшна.

Предсказываю процентов 40 выигрыша scmRTOS. Потому что это всё равно что-то (реализация round-robin, пусть даже при грамотной структуре данных) против ничего (две инструкции для выбора младшей единицы в слове-карте процессов).

 

Share this post


Link to post
Share on other sites
Предсказываю процентов 40 выигрыша scmRTOS. Потому что это всё равно что-то (реализация round-robin, пусть даже при грамотной структуре данных) против ничего (две инструкции для выбора младшей единицы в слове-карте процессов).

Это все из серии "Пастернака не читал - но осуждаю" :biggrin:. TNKernel точно так же ищет младший бит в битовой маске приоритетов - для кортекса юзается та же банальная инструкция CLZ (а для ARM7TDMI остроумный алгоритм из 5-6 инструкций)

 

//________________________________________________________________
//
//  Функция быстрого поиска номера младшего установленного бита
//
//  Входные параметры:
//      value	- исходное 32-битовое слово
//  Возвращает:
//      номер самого младшего единичного бита + 1;
//      (для бита 0 - возвращается 1, для бита 31 - 32)
//		если исходное значение было нулевое, то возвращается 0
// 
INLINE_FORCED
DWORD   
ffs_asm(DWORD value)
{
 value = value & (0 - value);
 value = 32 - __CLZ(value);
 return value;
}

А round-robin там списком реализован, поэтому TCB новой планируемой задачи при переключении максимум дополнительно извлечения указателя потребует (и то я не уверен в этом, TNKernel элемент списка встраивает прямо в объект, поэтому просто возможна банальная коррекция указателя инструкцией ADD/SUB #const вместо извлечения нового указателя).

То есть - SCMRTOS ищет самый приоритетный бит и берет из массива указатель на TCB по индексу этого бита. А TNKernel по индексу бита извлекает из того же массива указатель на список round-robin, и потом из этого указателя делает указатель на TCB. Вот и вся разница, делов-то. Если где и будет некоторый расход ресурсов - так это в таймере, который будет тикать и листать список round-robin - переходить на следующий TCB. Но собственно к переключению контекста оно никак не относится. Так что какие там 40 процентов :laughing:

Share this post


Link to post
Share on other sites
Оперативы ровно столько же - ведь меняется только схема приоритетов, а количество процессов и их стеки остаются теми же самыми.

Я про вариант, когда низкоприоритетные задачи просто выполняются по очереди - одна отработала, другой управление передаётся в рамках одного и того же процесса. На практике я просто делаю это через очередь заданий, которую обрабатывает низкоприоритетный процесс.

 

 

А round-robin там списком реализован, поэтому TCB новой планируемой задачи при переключении максимум дополнительно извлечения указателя потребует (и то я не уверен в этом, TNKernel элемент списка встраивает прямо в объект, поэтому просто возможна банальная коррекция указателя инструкцией ADD/SUB #const вместо извлечения нового указателя).

То есть - SCMRTOS ищет самый приоритетный бит и берет из массива указатель на TCB по индексу этого бита. А TNKernel по индексу бита извлекает из того же массива указатель на список round-robin, и потом из этого указателя делает указатель на TCB. Вот и вся разница, делов-то. Если где и будет некоторый расход ресурсов - так это в таймере, который будет тикать и листать список round-robin - переходить на следующий TCB. Но собственно к переключению контекста оно никак не относится. Так что какие там 40 процентов :laughing:

А идентификация задачи как производится? В scmRTOS таким идентификатором является как раз значение приоритета. И каждый сервис при переводе процесса в спячку или пробуждении оперирует с этим значением, которое всегда доступно и однозначно определяет процесс.

Share this post


Link to post
Share on other sites
Это все из серии "Пастернака не читал - но осуждаю" :biggrin:.

Я не читал, но отнюдь не осуждаю:)

Так что какие там 40 процентов :laughing:

Посмотрим-посмотрим:)

 

 

 

Share this post


Link to post
Share on other sites
Я про вариант, когда низкоприоритетные задачи просто выполняются по очереди - одна отработала, другой управление передаётся в рамках одного и того же процесса. На практике я просто делаю это через очередь заданий, которую обрабатывает низкоприоритетный процесс.

Угу, именно это я называю "кооператив". Если система одновременно не поддерживает несколько процессов одинакового приоритета, то остается только такой выход. Хороший кооператив - это тоже достаточно непросто, вон мой HTTP-сервер в основном потоке кооперативный, и то потребовалось внутри три очереди создавать, а как дошло дело до скриптов CGI тут чистый кооператив сдох, пришлось выносить скриптовую часть в чистую вытесняйку.

 

А идентификация задачи как производится?

По значению указателя на TCB (task control block, аналог экземпляра TBaseProcess, если не ошибаюсь). И с объектом TCB сразу можно работать - не надо преобразовывать id (приоритет) в указатель. Понятно что это извлечение из массива, но - надо сделать ldr адреса массива (ага, из очен-но быстрой флеши), потом сам ldr из массива (ну тот уже в RAM).

 

И каждый сервис при переводе процесса в спячку или пробуждении оперирует с этим значением, которое всегда доступно и однозначно определяет процесс.

Ну так оперируем сразу с TCB. При глубокой отладке опционально возможно включение проверки, что указатель на TCB действителен, и содержится в списке действительных на данный момент в системе задач (сканирутся список, при отладке это допустимо).

 

P.S. Ага, я посмотрел листиг - таки round-robin потребовал при переключении одной дополнительной инструкции subs для коррекции указателя списка в указатель на TCB. Одна инструкция - это как, подъемная цена за round-robin среди процессов одного приоритета? И количество процессов не будет ограничено.

 

Update: я как-то упустил из вида что scmRTOS на 8/16-битных платформах тоже работает (мой порт TNKernel исключительно предусматривался для 32-х разпядных - как минимум предполагает что операции загрузки/сохранения указателей атомарны). На 8-битной платформе идентификация процесса по уровню приоритета вероятно даст выигрыш по размеру и быстродействия кода. Но для 16/32-битных платформ это уже становится явных архитектурным ограничением.

Share this post


Link to post
Share on other sites
По значению указателя на TCB (task control block, аналог экземпляра TBaseProcess, если не ошибаюсь). И с объектом TCB сразу можно работать - не надо преобразовывать id (приоритет) в указатель. Понятно что это извлечение из массива, но - надо сделать ldr адреса массива (ага, из очен-но быстрой флеши), потом сам ldr из массива (ну тот уже в RAM).

Про какое ldr речь? Что-то нету у нас в AVR никакой ldr. :) Шутка. Но идея та же.

 

Ну так оперируем сразу с TCB. При глубокой отладке опционально возможно включение проверки, что указатель на TCB действителен, и содержится в списке действительных на данный момент в системе задач (сканирутся список, при отладке это допустимо).

Это хорошо на 32-битном проце, одна инструкция. На мелочи манипуляции с указателями вместо битов уже не так красиво выглядят. Кроме того, Битовая маска, являющаяся идентификатором процесса, одновременно является и средством для манипуляции картами процессов в каждом сервисе. С указателем на процесс так не получится. Там потребуются отдельные телодвижения, чтобы обслуживать все эти вещи. Поскольку битовая маска не может быть уникальной для процесса/задачи, то для фиксации ожидающего процесса, например, нужно будет завести для этого отдельную переменную в TCB. А как, скажем, достичь такой функциональности: Event Flag, когда его сигналят, переводит все процессы, которые встали на ожидание флага, в готовые к выполнению - своего рода широковещательный "подъём" спящих, но не broadcast, а multicast - т.е. не просто всех поднять, а выборочно, только тех, кто "записался" на ожидание? В случае битовых карт процессов с уникальными приоритетами это делается одной командой по маске.

Share this post


Link to post
Share on other sites
Это хорошо на 32-битном проце, одна инструкция. На мелочи манипуляции с указателями вместо битов уже не так красиво выглядят.

Да, это я уже сообразил - одновременно с Вами апдейт своего поста написал.

 

в TCB. А как, скажем, достичь такой функциональности: Event Flag, когда его сигналят, переводит все процессы, которые встали на ожидание флага, в готовые к выполнению - своего рода широковещательный "подъём" спящих, но не broadcast, а multicast - т.е. не просто всех поднять, а выборочно, только тех, кто "записался" на ожидание? В случае битовых карт процессов с уникальными приоритетами это делается одной командой по маске.

Наверное да - тут проще OR сделать на маску активных процессов. Но тут есть нюанс - у меня редко (я даже не могу вспомнить такой случай) бывает что какой-то объект с автосбросом ждет несколько процессов. Такое может быть с мьютексом - но там нужно выбрать и пробудить один самый приоритетный процесс (unicast, Вашими словами). Критическая секция на семафоре - то же самое - пробудить один процесс, первый в очереди.

 

 

Share this post


Link to post
Share on other sites
Посмотрим-посмотрим:)

Да нету там никаких 40 процентов :)

Исходные условия:

- STM32F103RG

- тактовая частота ядра 72МГц

- тактовая частота шины периферии 36МГц

- исполнение из флеша с 2 тактами ожидания

- печатная плата - стартеркит от Терраэлектроники

- компилятор IAR 6.30

- максимальные оптимизации по скорости

 

Тестовый алгоритм такой:

- имеется две задачи - 1 и 2

- приоритет задачи 1 выше (более приоритетная) чем у задачи 2

- задача 1 в бесконечном цикле

{

ждет синхрообъект (семафор для TNKernel и ef для scmRTOS)

после срабатывания синхрообъекта сбрасывает тестовый пин GPIO

}

- задача 2 в бесконечном цикле

{

спит 10 мс

устанавливает тестовый пин GPIO

сигналит синхрообъектом задаче 2

}

 

В итоге осциллографом наблюдаем импульсы положительной полярности длительностью несколько микросекунд с частотой следования 100 Герц.

 

Примечание:

Для SCM выполнена дополнительная оптимизация кода (отличие от релизной версии) предложенная AHTOXA - внесена инструкция

"bl os_context_switch_hook" в файле OS_Target_asm.s

 

Для SCM за основу взял проект 1-EventFlag для порта на STM32F1xx. Tрадиционно помучался со средой (а почему это у вас там есть конфигурация Release которая нихрена не компилируется?), в итоге пришлось проходить все опции ручками - выбирать тагет, включать оптмизации, и прочее. Вкрутил свой код настройки тактовой частоты и флеша. Итоговый результат - длительность тестового импульса 2.72мкс.

 

Потом взял свой проект на TNKernel, тот же самый код инициализации тактового генератора, тот же самый тестовый алгоритм.

Отключил отладку и всякие плюшки типа профайлера времени исполнения задачи - оп-па, импульс 4.04 мкс. Не, такого не бывает, я же железобетонно уверен. Ага - забыли оптимизацию по скорости включить - 3.56 мкс. Ну не может быть. Полез ковыряться, в итоге нарыл у себя глюк в порту - запрос PendSV избыточно вызывался дважды (это я давно перестраховался при разработке порта и потом забыл убрать, так что уже сегодняшний вечер провел с пользой :biggrin: ). Откорректировал, тестим - 2.88мкс. Та не (ТМ), ага - 5.41 компилируется, а надо 6.30 (как было для SCM). Берем 6.30 - итого 2.76мкс :biggrin: . Кстати 6.30 глючный при высоких степенях оптимизации, я его не использую. Еще немного поигрался с оптимизациями - но начали видимо играть начальные выравнивания функций, уже тут эти такты выловить сложно - было от 2.64 до 3.10 мкс, поэтому за пруф результат все-таки принимаю 2.76.

 

Итоговый результат длительностей наблюдаемых импульсов:

scmRTOS - 2.72 мкс

TNKernel - 2.76 мкс

 

Ессно, никаких 40 процентов тут и близко нету, так что "Пастернака надо-таки читать", ага :tongue:

Я не берусь утверждать что тут эта разница именно из-за более сложного диспетчера - уж очень разные ОС и много факторов влияет.

Но то что двухуровневый диспетчер с round-robin-ом вещь совсем не аццки сложная и медленная - это экспериментально доказанный факт.

 

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

 

Share this post


Link to post
Share on other sites
Поллингом - использовал чужой драйвер, а допиливать "под себя" было некогда. Хотя по идеи, если время переключения контекста мало, то и в поллинге можно вставить небольшие задержки и выкрутиться. Так или иначе с одинаковыми приоритетами решить подобные задачи проще всего, особенно для не очень искушенных людей в подобных вопросах. :)

ну, наверное, можно запилить в scmTROS сущность, которой скармливается лишь битовая маска процессов которым надо карусель устроить и эта сущность каждые N системных тиков будет на время насильно усыплять очередной процесс из этой маски если он активен, таким образом давая поработать другим хоть и с меньшим приоритетом, таким образом чужие библиотеки которые внутри что-то поллят вполне могут работать по очереди? или так не получится?

накладных расходов на такой псевдо round-robbin вроде никаких.

Share this post


Link to post
Share on other sites
Может, хватит вам уже позориться, а? Неужели трудно понять, что механизмы инкапсуляции C++ ну никак не защищают данные при конкурентном доступе к ним из разных потоков выполнения (в вашем случае - из прерываний)?

Вы слишком спешите с выводами. Нет никаких "конкурентных" потоков у периферии. Если от UARTa идут строки запросов, то они идут в строго определенный интерпретатор этих запрсов. И никто другой туда не сунется. То же самое, инапример, с Ethernet MAC-ом, после выделения, HTTP запросы поступают в строго определенный интерпретатор, и тоже никто к этому WEB серверу не сунется с чем-то другим. О каких таких "конкурентных потоках" вы говорите? Я их не наблюдаю.

 

Наверное вы не поняли, что задачей в моем случае является ISR, которая оформлена в виде защищенного метода в классе с защищенными данными. Никто туда, кроме методов самого класса добраться не может. Какие такие "конкурентные потоки"? Можете представить конкретный пример?

 

 

 

тоже достаточно непросто, вон мой HTTP-сервер в основном потоке кооперативный, и то потребовалось внутри три очереди создавать, а как дошло дело до скриптов CGI тут чистый кооператив сдох, пришлось выносить скриптовую часть в чистую вытесняйку.

Я видимо чего-то упустил, но по-моему CGI основано на использовании .dll в серверах на ПК? При чем тут scmRTOS для малых 8-ми разрядных чипов?

 

 

Share this post


Link to post
Share on other sites
scmRTOS - 2.72 мкс

TNKernel - 2.76 мкс

 

Ессно, никаких 40 процентов тут и близко нету, так что "Пастернака надо-таки читать", ага :tongue:

Давайте всё же уточним, что это не Пастернак, а сильно допиленное чудовище Франкенштейна, причём в данный момент никем, кроме самого Франкенштейна не проверяемое :)

ЗЫ. У меня, кстати, получилось 2.55 мкс (scmRTOS 4.0/GCC).

Share this post


Link to post
Share on other sites
Я видимо чего-то упустил, но по-моему CGI основано на использовании .dll в серверах на ПК? При чем тут scmRTOS для малых 8-ми разрядных чипов?

CGI это несколько более широкая концепция. Имхо, под CGI следует понимать такое - поступает HTTP-запрос, сервер принимает заголовок запроса, определяет имя ресурса. Если это имя является именем скрипта (неважно на каком языке написанном - Ява, Перл, Питон, ПХП, или это вообще может быть приложение на С/С++), то сервер запускает этот скрипт и дальнейший поток данных входящего HTTP-запроса (тело, если оно есть) перенаправляется в stdin порожденного скрипта. А поток stdout, генерируемый скриптом, сервером также перехватывается и отправляется как ответ на HTTP-запрос удаленному хосту. Так вот, веберы (разработчики сайтов) поднакопили некоторый багаж алгоритмов и опыт разработки таких скриптов, принудить их поддерживать явный кооператив сложновато. К тому же обычно из этих скриптов (во встраиваемом сервере это просто процедуры на C/C++ выполняемые в отдельном порожденном потоке) требуется доступ к аппаратуре или внутренним базам данных устройства, например, оно как выдаст "SELECT к внутреннему SQL-серверу" - какой уж тут кооператив.

 

Возвращаясь к scmRTOS, жесткое использование приоритета как идентификатора процесса имеет еще один недостаток - приоритет не может быть динамически изменен. Значит все протоколы управления приоритетами, предназначенные для борьбы с инверсией приоритетов, также не могут быть реализованы даже теоретически :(.

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this