Advertisement
kotabe

portable coroutine implementation (sketch)

Jul 3rd, 2015 (edited)
3,145
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 1.96 KB | None | 0 0
  1. // portable coroutine implementation (sketch)
  2. // note that Clang (LLVM) compiler requires -fno-stack-check option
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <setjmp.h>
  6.  
  7. jmp_buf contexts[2];
  8. int cid = 0; // coroutine id
  9.  
  10. void printsp()
  11. {
  12.   int x;
  13.   printf("stack pointer = %p\n", &x);
  14. }
  15.  
  16. // execute the func on the specified stack
  17. void exec_on_altstack(void *stkbase, size_t stksz, void (*func)())
  18. {
  19.   size_t diff = (void*)&diff - stkbase - stksz;
  20.   // allocate a dummy local variable to change the stack pointer
  21.   volatile char dummy[diff];
  22.   dummy[0] = '\0';  // don't remove dummy, optimizer
  23.   (*func)();
  24. }
  25.  
  26. // context switch
  27. void csw(int target) {
  28.   if (_setjmp(contexts[cid]) == 0) {
  29.     printf("# coroutine[%d] context saved\n", cid);
  30.     cid = target;
  31.     _longjmp(contexts[target], 1);
  32.   } else {
  33.     printf("# coroutine[%d] resumes\n", cid);
  34.   }
  35. }
  36.  
  37. void test() {
  38.   printf("test started\n");
  39.   printsp();
  40.   csw(0);
  41.   printf("test resumed\n");
  42.   csw(0);
  43.   printf("test resumed2\n");
  44.   csw(0);
  45. }
  46.  
  47. extern int main(int argc, char **argv)
  48. {
  49.   printsp();
  50.   size_t stksz = 4096;
  51.   void *stkbase = malloc(stksz);
  52.   printf("allocated stack = %p to %p\n", stkbase, stkbase + stksz - 1);
  53.   if (_setjmp(contexts[cid]) == 0) {
  54.     cid = 1;
  55.     exec_on_altstack(stkbase, stksz, test);
  56.   } else {
  57.     printf("main started\n");
  58.     csw(1);
  59.     printf("main resumed\n");
  60.     csw(1);
  61.     printf("main resumed2\n");
  62.   }
  63.   return 0;
  64. }
  65.  
  66. /* executed on OSX 10.10.4
  67.  
  68. ~/stacktest% ./a.out
  69. stack pointer = 0x7fff5917492c
  70. allocated stack = 0x7feb08804200 to 0x7feb088051ff
  71. test started
  72. stack pointer = 0x7feb088051bc
  73. # coroutine[1] context saved
  74. main started
  75. # coroutine[0] context saved
  76. # coroutine[1] resumes
  77. test continued
  78. # coroutine[1] context saved
  79. # coroutine[0] resumes
  80. main resumed
  81. # coroutine[0] context saved
  82. # coroutine[1] resumes
  83. test continued2
  84. # coroutine[1] context saved
  85. # coroutine[0] resumes
  86. main resumed2
  87.  
  88. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement