Rst7 5 1 февраля, 2023 Опубликовано 1 февраля, 2023 · Жалоба Случайно тут в голову идея пришла, в крайнем IAR'е вроде хорошо работает. В отличии от классики (сделанной через Duff's device) можно использовать switch в том числе. #define P_START() do{ \ static void *___jumper___; \ if (___jumper___) \ { \ __asm volatile("BX\t%0\nyield::"::"r"(___jumper___):"r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12","r14","cc","memory"); \ __asm volatile("STR\tLR,[%0]"::"r"(&___jumper___):"r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12","r14","cc","memory"); \ return; \ } \ } while(0) #define P_YIELD() __asm volatile("BLX\tyield"::: \ "r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12","r14","cc","memory") int foo(int); void Test(void) { P_START(); for(;;) { static int counter; for(counter=0; counter<8; counter++) { foo(counter); P_YIELD(); } } } #pragma optimize=no_inline void main(void) { for(;;) { Test(); } } Наверное, подобное можно и в GCC, если, конечно, там аллокатор регистров с ума не сойдет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 160 1 февраля, 2023 Опубликовано 1 февраля, 2023 · Жалоба 1. Почему не setjmp()/longjmp()? 2. Есть ли еще профит от протопотоков, когда любая кооперативная ОС (или любая другая с поддержкой сопрограмм/кооперативного/смешанного режимов вытеснения) все это делает несколько красивее? 3. ИМХО, протопоточный стиль навязывает определенную сноровку в проектировании логики. Например, расстановка все этих P_YIELD()... рябящих в глазах. 4. Опять же, ИМХО, табличные автоматы состояний тоже нагляднее протопотоков, разве нет? 5. А зачем все это? Пример, вроде, понятен, только мне не получается представить что-то кроме него, увы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 1 февраля, 2023 Опубликовано 1 февраля, 2023 · Жалоба 1. Ну потому что setjmp/longjmp - совсем другое пальто. Это уже куда ближе к настоящей многопоточности, с собственными стеками потоков и так далее. Другая весовая категория. 2. Конечно есть. Это хорошая замена тем же конечным автоматам, чья читабельность очень быстро становится равной нулю с увеличением количества состояний. 3. Да ничего страшного же. Он же в основном в таком виде, типа while(!condition) P_YIELD(); Некоторая сноровка нужна в том, чтобы не забывать, что локальная переменная (не static) не переживет этого вызова, в остальном ничего сложного. 4. см. п 2 5. Так это ж самый главный вопрос. Это ж интересно только тем, кто понимает, где и как применять такие протопотоки. А обсуждать, где их применять - мне не очень интересно, есть масса обсуждений в интернетах. Объективно код тут получается примерно такой же, как и protothreads для GCC с вычисляемым goto. Просто я GCC не считаю достойным компилятором (он давно стал компилятором для x86), а в IAR'е вычисляемых goto нет, но зато можно вышеописанным способом сделать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 160 1 февраля, 2023 Опубликовано 1 февраля, 2023 · Жалоба 7 минут назад, Rst7 сказал: а в IAR'е вычисляемых goto нет, но зато можно вышеописанным способом сделать. Вычисляемый goto это который по __LINE__? Странно, я думал это банально во всех компиляторах поддерживается. Константа же времени компиляции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 1 февраля, 2023 Опубликовано 1 февраля, 2023 · Жалоба Just now, Arlleex said: Вычисляемый goto это который по __LINE__? Ну там для генерации меток используется __LINE__, да. Но вот void *jumper; ... goto *jumper это сугубо GCC'шные дела. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
uriy 5 2 февраля, 2023 Опубликовано 2 февраля, 2023 · Жалоба Я тоже пользуюсь протопотоками. Но только в маленьких процессорах. Мне кажется код получается более читабельный там где нужны автоматы. С локальными переменными да бывает забываешь про static. А PT_YIELD я похоже никогда не применял. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 42 2 февраля, 2023 Опубликовано 2 февраля, 2023 (изменено) · Жалоба 1 час назад, uriy сказал: А PT_YIELD я похоже никогда не применял И как тогда переключались потоки? Получается замкнутый цикл без выхода... Изменено 2 февраля, 2023 пользователем mantech Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 212 2 февраля, 2023 Опубликовано 2 февраля, 2023 · Жалоба 12 минут назад, mantech сказал: И как тогда переключались потоки? Получается замкнутый цикл без выхода... Скорее всего использовались PT_WAIT_UNTIL или PT_WAIT_WHILE, внутри которых скрыт PT_YIELD. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
uriy 5 3 февраля, 2023 Опубликовано 3 февраля, 2023 · Жалоба Quote Скорее всего использовались PT_WAIT_UNTIL или PT_WAIT_WHILE Да именно так Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться