|
Про реентерабельность, малоизвестная фича GCC |
|
|
|
Feb 15 2009, 23:51
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Только не говорите, что знали и часто пользуетесь!  В общем, тем, кому позарез нада получить сабж, оказалось все очень просто Код void somefunc (volatile int param) { volatile int local1; volatile char local2; //body local1 |= param; return; } Как объявили все volatile - компилятор все, включая входные параметры, кладет в стек-фрейм. И логика проста: без соответствующих оптимизаций функции генерятся реентерабельными. Volatile как-раз и отключает эту оптимизацию локальных переменных. В общем, в мануале ГЦЦ настолько туманно это описано, что побудило поделиться радостной новостью.
|
|
|
|
|
 |
Ответов
|
Sep 13 2009, 07:01
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Еще одна ТАСКАЛКА (от слова task) получилась. [attachment=36203:coos.zip] Несколько слов Код typedef struct Tag_TCB { void (*task)(struct Tag_TCB *tcb); void *param; void *entry; struct Tag_TCB *next; unsigned lock:1;// lock counter unsigned stop:1;// stop flag unsigned exit:1;// request to delete from list unsigned PID:5; // process ID } TCB_t; *param - для создания статических локальных переменных с учетом требований реентерабельности. *entry - для использования переопределяемых точек входа с помощью гнусной фичи labels as valuesВ общем - мне пока понравилась такая мысль: с одной стороны - через вызов system() можно отдавать управление другим задачам во время ожидания событий с другой стороны, чтоб не мучать стек обратными вызовами, можно использовать переопределяемые точки входа и смело выходить из задачи, пока не наступит нужное нам событие. Как Вам такой гибрид, уважаемый ReAl ? PS к тому же system() можно спрятать внутри любой реентерабельной функции, а точки входа - низзя. Теперь в TCB добавить поля для сообщений - и ось на подходе
|
|
|
|
|
Sep 13 2009, 09:21
|

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

|
Цитата(_Pasha @ Sep 13 2009, 10:01)  Еще одна ТАСКАЛКА (от слова task) получилась. Как Вам такой гибрид, уважаемый ReAl ? PS к тому же system() можно спрятать внутри любой реентерабельной функции, а точки входа - низзя. Да, system() некоторые вещи сделает красивее, но при этом если несколько задач из списка позовут system() (да ещё и из функции - а иначе кайфу в вызове system() никакого по сравнению с просто установокй метки и возвратом) - стек как-то глубоко пойдёт, надо помнить о возможности. В этом смысле вместо Код STD_TASK(wait2) { ENTRY(step1) { if(TCNT1 != 0xff00) system(); } } "стандартный" protothread-овский Код PT_WAIT_UNTIL(pt, TCNT1 != 0xff00); по стеку экономнее, так как ставит метку и даёт возврат из функции, а там уже просматривается список потоков. Никто не мешает комбинировать. И управляющую структуру я бы выделил в виде заголовка Код typedef struct Tag_TCB_header { void (*task)(struct Tag_TCB *tcb); void *entry; struct Tag_TCB *next; unsigned lock:1;// lock counter unsigned stop:1;// stop flag unsigned exit:1;// request to delete from list unsigned PID:5; // process ID // тут может ещё сразу таймерную переменную для таймаутов/sleep() } TCB_header_t; а локальные параметры не через указатель, а как продолжением структуры Код typedef struct tag_some_task_tcb { TCB_header_t th; unsigned some_param; unsigned char some_buf[8]; } some_task_tcb_t; при обращении не будет лишнего уровня косвенности. А вообще Vit на protothread-подобных вещах стаю собак сожрал, это с ним обсуждать надо.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Sep 13 2009, 11:55
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(ReAl @ Sep 13 2009, 12:21)  Да, system() некоторые вещи сделает красивее, но... Никто и не заставляет всюду им пользоваться  В тяжелых случаях перед вызовом должна быть проверка стека. Цитата В этом смысле вместо Код STD_TASK(wait2) { ENTRY(step1) { if(TCNT1 != 0xff00) system(); } } "стандартный" protothread-овский Не-не. Если есть ENTRY(), то можно обойтись без system() ЗЫ: Да и что толку от его тотального использования - в залоченном состоянии задача не обработает ни одного нового события. Код STD_TASK(wait2) { ALLOW_ENTRY; ................. ................ ENTRY(step1) { if(TCNT1 != 0xff00) return; /// просто вышли и попали опять в system() :) // а вот если тут был бы цикл с ожиданием - ясное дело, надо system() вызывать ................ ................ } } Отдельное спасибо за то, что напомнили про анонимные метки в PT_WAIT_UNTIL Добавлю. Но именные метки оставить надо, для возможного повторного использования точки входа. Цитата И управляющую структуру я бы выделил в виде заголовка а локальные параметры не через указатель, а как продолжением структуры при обращении не будет лишнего уровня косвенности. Имхо, правильнее просто передавать указатель на локальные переменные из system(), вместо полного TCB. Тогда обращение к полям TCB будет доступно только через осевые сервисы. Ага. И чтобы можно было пользоваться break /continue внутри ENTRY надо сделать Код #define ENTRY(label) tcb->entry = &&label; label: for(;;)
|
|
|
|
|
Sep 13 2009, 17:02
|

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

|
Цитата(_Pasha @ Sep 13 2009, 14:55)  Имхо, правильнее просто передавать указатель на локальные переменные из system(), вместо полного TCB. Тогда обращение к полям TCB будет доступно только через осевые сервисы. Ну и что в этом хорошего? Точнее, что хорошего в том, что эти сервисы вместо коротких inline-вызовов/макросов, обращающихся к полям TCB смещением к тому же указателю, который используеся для локальных переменных потока - вместо этого будут чем-то более толстым и медленным?
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
Сообщений в этой теме
_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 ЦитатаВот условия реентерабельности:
Тут _Pasha и... Feb 16 2009, 08:26 Сергей Борщ Цитата(Rst7 @ Feb 16 2009, 10:26) Тут _Pa... Feb 16 2009, 08:51 _Pasha Цитата(Rst7 @ Feb 16 2009, 12:26) Тут _Pa... Feb 16 2009, 23:30  ReAl Цитата(_Pasha @ Feb 17 2009, 01:30) Кодty... Feb 17 2009, 07:50   _Pasha Цитата(ReAl @ Feb 17 2009, 10:50) возможн... Feb 17 2009, 08:27    ReAl Цитата(_Pasha @ Feb 17 2009, 10:27) Если ... Feb 17 2009, 16:40     ReAl Цитата(ReAl @ Feb 17 2009, 18:40) Не увер... Mar 15 2009, 12:52 _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 Цитата(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
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0
|
|
|