Want more features on Pastebin? Sign Up, it's FREE!
Guest

portable coroutine implementation (sketch)

By: kotabe on Jul 3rd, 2015 (edited)  |  syntax: C  |  size: 1.88 KB  |  views: 270  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print  |  clone
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. // portable coroutine implementation (sketch)
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <setjmp.h>
  5.  
  6. jmp_buf contexts[2];
  7. int cid = 0; // coroutine id
  8.  
  9. void printsp()
  10. {
  11.   int x;
  12.   printf("stack pointer = %p\n", &x);
  13. }
  14.  
  15. // execute the func on the specified stack
  16. void exec_on_altstack(void *stkbase, size_t stksz, void (*func)())
  17. {
  18.   size_t diff = (void*)&diff - stkbase - stksz;
  19.   // allocate a dummy local variable to change the stack pointer
  20.   char dummy[diff];
  21.   dummy[0] = '\0';  // don't remove dummy, optimizer
  22.   (*func)();
  23. }
  24.  
  25. // context switch
  26. void csw(int target) {
  27.   if (_setjmp(contexts[cid]) == 0) {
  28.     printf("# coroutine[%d] context saved\n", cid);
  29.     cid = target;
  30.     _longjmp(contexts[target], 1);
  31.   } else {
  32.     printf("# coroutine[%d] resumes\n", cid);
  33.   }
  34. }
  35.  
  36. void test() {
  37.   printf("test started\n");
  38.   printsp();
  39.   csw(0);
  40.   printf("test resumed\n");
  41.   csw(0);
  42.   printf("test resumed2\n");
  43.   csw(0);
  44. }
  45.  
  46. extern int main(int argc, char **argv)
  47. {
  48.   printsp();
  49.   size_t stksz = 4096;
  50.   void *stkbase = malloc(stksz);
  51.   printf("allocated stack = %p to %p\n", stkbase, stkbase + stksz - 1);
  52.   if (_setjmp(contexts[cid]) == 0) {
  53.     cid = 1;
  54.     exec_on_altstack(stkbase, stksz, test);
  55.   } else {
  56.     printf("main started\n");
  57.     csw(1);
  58.     printf("main resumed\n");
  59.     csw(1);
  60.     printf("main resumed2\n");
  61.   }
  62.   return 0;
  63. }
  64.  
  65. /* executed on OSX 10.10.4
  66.  
  67. ~/stacktest% ./a.out
  68. stack pointer = 0x7fff5917492c
  69. allocated stack = 0x7feb08804200 to 0x7feb088051ff
  70. test started
  71. stack pointer = 0x7feb088051bc
  72. # coroutine[1] context saved
  73. main started
  74. # coroutine[0] context saved
  75. # coroutine[1] resumes
  76. test continued
  77. # coroutine[1] context saved
  78. # coroutine[0] resumes
  79. main resumed
  80. # coroutine[0] context saved
  81. # coroutine[1] resumes
  82. test continued2
  83. # coroutine[1] context saved
  84. # coroutine[0] resumes
  85. main resumed2
  86.  
  87. */
clone this paste RAW Paste Data