реклама на сайте
подробности

 
 
> Про реентерабельность, малоизвестная фича GCC
_Pasha
сообщение Feb 15 2009, 23:51
Сообщение #1


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Только не говорите, что знали и часто пользуетесь! smile.gif

В общем, тем, кому позарез нада получить сабж, оказалось все очень просто

Код
void somefunc (volatile int param)

  volatile int local1;
  volatile char local2;
//body
local1 |= param;
return;
}


Как объявили все volatile - компилятор все, включая входные параметры, кладет в стек-фрейм.

И логика проста: без соответствующих оптимизаций функции генерятся реентерабельными. Volatile как-раз и отключает эту оптимизацию локальных переменных.

В общем, в мануале ГЦЦ настолько туманно это описано, что побудило поделиться радостной новостью.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Rst7
сообщение Feb 16 2009, 08:26
Сообщение #2


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
Вот условия реентерабельности:


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


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 16 2009, 23:30
Сообщение #3


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Rst7 @ Feb 16 2009, 12:26) *
Тут _Pasha имеет в виду не классическое понятие реетерабельности как работу функции в многопоточном приложении, а как некий костыль, позволяющий организовать многопоточность с минимумом затрат памяти.

Продолжим нашу шизофрению. Как выяснилось, при размещении в стеке переменных достаточный размер переключаемого контекста AVR будет 6 байт! Это даже меньше, чем я на асме делал, протупил - получалось 8 байт.

Код
typedef struct

{

 uint16_t pc,sp,framePTR;

} small_ctx_t;


Т.е. для организации точки входа сопрограммы используется косвенный goto, указатель стека текущей сопрограммы и указатель на локальные данные, который можно получить __builtin_frame_ptr(0). Ввиду того, что жесткого реалтайма не будет, на сохранение регистров в сопрограммах можно вообще не обращать внимание, в смысле - запретить. В общем, 6 байт - это намного меньше, чем в setjmp()
Go to the top of the page
 
+Quote Post
ReAl
сообщение Feb 17 2009, 07:50
Сообщение #4


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(_Pasha @ Feb 17 2009, 01:30) *
Код
typedef struct
{
 uint16_t pc,sp,framePTR;
} small_ctx_t;

Т.е. для организации точки входа сопрограммы используется косвенный goto, указатель стека текущей сопрограммы и указатель на локальные данные, который можно получить __builtin_frame_ptr(0).
Что-то в этом есть. В отличие от указателем на структуру с данным процесса-сопрограммы, это даёт возможность переключаться не только в "корневой" функции, но и в любом месте по глубине вызовов. Но это уже приведёт к потере части преимущества по стеку (да, все регистры уже не сохраняются, но для каждого сопроцесса нужно всё равно резервировать свой стек достаточной глубины).
Правда, по сравнению с вытесняющмим системами, остаётся преимущество по времени синхронного переключения. А вот с асинхронным (из прерывания) - всё равно надо весь контекст сохранять, так как промежуточные вычисления на регистрах делаются, архитектура-то не стековая.

Хотя для этого органичнее стековая архитектура. О которой ругаются в теме про архитектуру контроллера.
На AVR такая модель не ложится, это на PDP-11 ещё можно было эмулировать - делать add 4(R3),8(R3) и только R3 да SP и сохранять (или вообще только SP для четырёх сопроцессов с базами в R0..R3, но они не смогли бы разделять между собой подпрограммы из-за разных баз), хотя, вероятно, выигрыш на переключении растерялся бы на проигрыше в эффектичности самих вычислений.

Что-то я недоспал и всё не соображу. И уже бегу.
Но интересно.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 17 2009, 08:27
Сообщение #5


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(ReAl @ Feb 17 2009, 10:50) *
возможность переключаться не только в "корневой" функции, но и в любом месте по глубине вызовов.
Если вызываемые процедуры построены также. На счет стека - се ля ви - сколько процессов, столько и стеков.sad.gif
Go to the top of the page
 
+Quote Post
ReAl
сообщение Feb 17 2009, 16:40
Сообщение #6


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(_Pasha @ Feb 17 2009, 10:27) *
Если вызываемые процедуры построены также. На счет стека - се ля ви - сколько процессов, столько и стеков.sad.gif
Вот этого и не понимаю - "за что боролись".
Стеки каждому свои.
На стеке место нужно под всю глубину вызовов.
Место под регистры на стеках не нужны только если все переключения задач синхронные.
Если могут быть асинхронные переключения (из прерываний), то на стеках нужно место под полное сохранение контекста, с регистрами, так как прерывание может произойти в промежуточных операциях до записи результата в переменную на стеке.

Итого при наличии асинхронных переключений экономии памяти на стеках нет вообще.
При наличии только синхронных переключений эконоимия есть, но на не такая ощутимая. А время реакции наверное таки хуже, чем у вытесняющей ОС.
Так что получается что-то среднее между
  • вызовом функции шага каждого процесса do_XXX_step(), делающей небольшой кусок работы и сохраняющей рещультат в статичесокй структуре состояния процесса
    либо
    сопрограммными переключениями на верхнем уровне процесса, когда стек тоже в некотором смысле "очищен"
  • вытесняющей ОС

Причем у "среднего" память расходуется почти как у второго, а всё остальное - практически как у первого.

Или я чего-то не понимаю по сонности своей в последние пару недель?

---------------------------

Где-то пробегал линк на систему над автоматами, в которой (если я правилно помню, тогда пробежался по диагонали) всё происходит синхронно, при каждом автомате набор стандартных функций - "обычный" "сделать кусок", и "обработчики прерываний высокого уровня". У планировщика очередь, где стоят указатели на функции для автоматов которые надо выполнить и таймерные переменные (функция запускается кода дотикает). Кажется ещё приоритеты при этих указателях.
В прерываниях делается самое быстрое типа сохранения байта UART в памяти и в очередь помещается указатель на соответствующий "обработчик высокого уровня" с флагом "как только, так сразу".
Ну а планировщик после синхронного возврата из очередной функции пробегается по очереди и решает, по какому указателю вызвать следующую. Которая тоже может поместить в очередь нечто, например, "сигнальную" функцию от другого автомата.
Всё чинно, синхронно, расход стека минимальный, никаких практически блокировок доступа к структурам не нужно, так как всё синхронно.
Всё это сделано горстью макросов и выглядит довольно красиво и читабельно.

Не уверен, что я правильно напел Битлз по телефону, но если кто-то таке встречал - дайте линк. А то у меня потерялся.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ReAl
сообщение Mar 15 2009, 12:52
Сообщение #7


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(ReAl @ Feb 17 2009, 18:40) *
Не уверен, что я правильно напел Битлз по телефону, но если кто-то таке встречал - дайте линк. А то у меня потерялся.
Шорт побори, это было TinyTimber (Vit aka sensor_ua показал когда-то)
В прерываниях тоже всё работает - выходит, что обработчик прерывания сохраняет всё то, что не обязаны сохранять вызываемые подпрограммы, а планировщик в конце обработчика прерывания сохраняет через setjump остальное и по longjump переходт на другой процесс.
Когда на данный процесс переключатся опять по longjump - оно всплывёт уже непосредственно перед эпилогом обработчика прерывания с восстановленными callee-saved регистрами, эпилог восстановит caller-saved и SREG. Всё пучком.
Только в примере (по ссылке от Vit, эти исходники ненагугливаются по слову TinyTimber) сумма блока описания задачи (с буфером jumpbuf) и стека для задачи занимают где-то столько же, сколько и обычные стеки для AVR в scmRTOS, что вполне естественно.
Т.е. явных преимуществ по памяти нет, оно, как уже отмечалось, было бы при только синхонном переключении и только на верхних уровнях, в "корневых" функциях автоматов (тогда на всех один стек).

Если я правильно понял при беглом просмотре - преимущество просматривается в, фактически, диамическом создании/удалени задач, массивы описателей потоков и стеков - это массивы запущенных и выолняющегося плюс отложенных "методов", а не "процессов". Т.е. "спящий процесс" - это объект, у которого не запущен ни один "метод", т.е. никакой его код не работает, только сохраняется состояние автомата в его переменных, до которых ОС нет дела. А когда, например, "драйвер"-обработчик прерывания UART отошлёт весь пакет, тогда он из прерывания заланирует отработку соответствущего "метода" соответствующего "объекта" путём постановки "сообщения" в очередь. И он (метод) через сообщение привяжется к свободному блоку задачи/стеку, обработается через run() этого свободного "слота выполнения" (сразу или когда таковой освободится).

Очередь сообщений TinyTimber тоже где-то эквиваленна по памяти набору событий/мьютексов, будет или нет преимущство зя счёт динамического распределения - тяжело сказать. И беда может обнаружиться только во время выполнения, а в случае scmRTOS просто при компиляции не хватит памяти для всех заявленных объектов ОС.

Как-нибудь надо будет ещё покурить эту тему...


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- _Pasha   Про реентерабельность   Feb 15 2009, 23:51
- - Rst7   Вы меня, конечно, извините, но это - "ацкий б...   Feb 16 2009, 00:13
- - Сергей Борщ   Цитата(_Pasha @ Feb 16 2009, 01:51) Как о...   Feb 16 2009, 00:37
|- - _Pasha   Цитата(Сергей Борщ @ Feb 16 2009, 03:37) ...   Feb 16 2009, 07:10
|- - aesok   Цитата(_Pasha @ Feb 16 2009, 10:10) Обесп...   Feb 16 2009, 07:51
|- - demiurg_spb   Цитата(aesok @ Feb 16 2009, 10:51) В Атме...   Feb 16 2009, 09:10
|- - ReAl   Цитата(aesok @ Feb 16 2009, 09:51) В Атме...   Feb 16 2009, 09:56
|- - Сергей Борщ   Цитата(Rst7 @ Feb 16 2009, 10:26) Тут _Pa...   Feb 16 2009, 08:51
- - _Pasha   Цитата(Rst7 @ Feb 16 2009, 03:13) Куда бе...   Feb 16 2009, 08:46
- - Rst7   Че то я уже не пойму. Судя по предыдущей теме, ник...   Feb 16 2009, 09:08
- - Rst7   Лучше бы - не ядро править, а в компиляторы вменяе...   Feb 16 2009, 10:12
|- - ReAl   Цитата(Rst7 @ Feb 16 2009, 12:12) Лучше б...   Feb 16 2009, 20:42
- - Rst7   Нет, с плюсами конечно, неплохо получается. Но хот...   Feb 16 2009, 21:52
|- - ReAl   Цитата(Rst7 @ Feb 16 2009, 23:52) Нет, с ...   Feb 16 2009, 22:11
- - _Pasha   В общем, пока ясно одно: нельзя смешивать синхронн...   Feb 17 2009, 17:05
- - _Pasha   Еще одна ТАСКАЛКА (от слова task) получилась. Не...   Sep 13 2009, 07:01
|- - ReAl   Цитата(_Pasha @ Sep 13 2009, 10:01) Еще о...   Sep 13 2009, 09:21
|- - _Pasha   Цитата(ReAl @ Sep 13 2009, 12:21) Да, sys...   Sep 13 2009, 11:55
|- - ReAl   Цитата(_Pasha @ Sep 13 2009, 14:55) Имхо,...   Sep 13 2009, 17:02
|- - _Pasha   Цитата(ReAl @ Sep 13 2009, 20:02) Ну и чт...   Sep 13 2009, 20:19
|- - ReAl   Цитата(_Pasha @ Sep 13 2009, 23:19) Допус...   Sep 14 2009, 08:58
- - _Pasha   Понял, спасибо. Но не сразу Если локальных параме...   Sep 15 2009, 05:17
- - _Pasha   Кстати, о protothread parallel.h CODE #ifndef PAR...   Sep 15 2009, 06:42
- - _Pasha   Решил скрестить прототредоподобную кооперативку и ...   Dec 25 2009, 08:47


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 31st July 2025 - 20:09
Рейтинг@Mail.ru


Страница сгенерированна за 0.01423 секунд с 7
ELECTRONIX ©2004-2016