Перейти к содержанию
    

Крайне минималистичный protothreads

Случайно тут в голову идея пришла, в крайнем 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, если, конечно, там аллокатор регистров с ума не сойдет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. Почему не setjmp()/longjmp()?
2. Есть ли еще профит от протопотоков, когда любая кооперативная ОС (или любая другая с поддержкой сопрограмм/кооперативного/смешанного режимов вытеснения) все это делает несколько красивее?:smile:
3. ИМХО, протопоточный стиль навязывает определенную сноровку в проектировании логики. Например, расстановка все этих P_YIELD()... рябящих в глазах.
4. Опять же, ИМХО, табличные автоматы состояний тоже нагляднее протопотоков, разве нет?
5. А зачем все это? Пример, вроде, понятен, только мне не получается представить что-то кроме него, увы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. Ну потому что setjmp/longjmp - совсем другое пальто. Это уже куда ближе к настоящей многопоточности, с собственными стеками потоков и так далее. Другая весовая категория.

2. Конечно есть. Это хорошая замена тем же конечным автоматам, чья читабельность очень быстро становится равной нулю с увеличением количества состояний.

3. Да ничего страшного же. Он же в основном в таком виде, типа while(!condition) P_YIELD(); Некоторая сноровка нужна в том, чтобы не забывать, что локальная переменная (не static) не переживет этого вызова, в остальном ничего сложного.

4. см. п 2

5. Так это ж самый главный вопрос. Это ж интересно только тем, кто понимает, где и как применять такие протопотоки. А обсуждать, где их применять - мне не очень интересно, есть масса обсуждений в интернетах.

 

Объективно код тут получается примерно такой же, как и protothreads для GCC с вычисляемым goto. Просто я GCC не считаю достойным компилятором (он давно стал компилятором для x86), а в IAR'е вычисляемых goto нет, но зато можно вышеописанным способом сделать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 минут назад, Rst7 сказал:

а в IAR'е вычисляемых goto нет, но зато можно вышеописанным способом сделать.

Вычисляемый goto это который по __LINE__?

Странно, я думал это банально во всех компиляторах поддерживается. Константа же времени компиляции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Just now, Arlleex said:

Вычисляемый goto это который по __LINE__?

Ну там для генерации меток используется __LINE__, да. Но вот

	void *jumper;
	...
	goto *jumper
	

это сугубо GCC'шные дела.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я тоже пользуюсь протопотоками. Но только в маленьких процессорах.

Мне кажется код получается более читабельный там где нужны автоматы. 

С локальными переменными да бывает забываешь про static. А PT_YIELD я похоже никогда не применял.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, uriy сказал:

А PT_YIELD я похоже никогда не применял

И как тогда переключались потоки? Получается замкнутый цикл без выхода...

Изменено пользователем mantech

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 минут назад, mantech сказал:

И как тогда переключались потоки? Получается замкнутый цикл без выхода...

Скорее всего использовались PT_WAIT_UNTIL или PT_WAIT_WHILE, внутри которых скрыт PT_YIELD.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...