Guest User

Untitled

a guest
Feb 22nd, 2018
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.38 KB | None | 0 0
  1. /**
  2. * This was something to play around with longjmp/setjmp and the stack that it would require.
  3. * This code does not work as the direction this experiment was going would require context
  4. * switching that I didn't want to happen.
  5. */
  6. #include <setjmp.h>
  7. #include <ucontext.h>
  8. #include <unistd.h>
  9. #include <stdio.h>
  10. #include <stdint.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13.  
  14. enum f_states {
  15. STATE_ERROR = -1,
  16. STATE_NULL = 0,
  17. STATE_NEW,
  18. STATE_RUNNING
  19. };
  20.  
  21. struct future_t {
  22. jmp_buf *rip; // return to
  23. struct future *msg_from;
  24. };
  25. typedef struct future_t future;
  26.  
  27.  
  28. struct message {
  29. uint64_t msg_type;
  30. jmp_buf *rip; // return to
  31. ssize_t data_s;
  32. void *data;
  33. };
  34.  
  35. #define MSG_ACK (struct message){ .rip = &self->private, .msg_type = 1 }
  36.  
  37. struct coroutine_t {
  38. ucontext_t ctx;
  39. jmp_buf private; // only cr can change
  40.  
  41. struct coroutine_t *parent; // only `root` can have parent == NULL
  42. char name[100];
  43. char stack[4096 * 4]; // 4 pages
  44. };
  45.  
  46. typedef struct coroutine_t coroutine;
  47.  
  48.  
  49. #define mkln(prefix, fmt) ({ \
  50. char __t [512]; \
  51. bzero(__t, sizeof(__t)); \
  52. snprintf(__t, sizeof(__t), "%s :: %s\n", prefix, fmt); \
  53. __t; \
  54. })
  55.  
  56. #define pp(fmt, ...) printf(mkln(self->name, fmt), ##__VA_ARGS__);
  57.  
  58.  
  59.  
  60. intptr_t func_y(coroutine *self) {
  61. enum f_states state = STATE_NULL;
  62. struct message *msg = NULL;
  63. intptr_t rc = 0;
  64.  
  65.  
  66. do {
  67. pp("do");
  68.  
  69. if (STATE_RUNNING == state) {
  70. rc = _setjmp(self->private);
  71. pp("setjmp = %p", rc);
  72. }
  73.  
  74. if (STATE_ERROR == rc) {
  75. pp("error setjmp");
  76. state = STATE_ERROR;
  77.  
  78. } else if (STATE_RUNNING == state && STATE_NULL == rc) {
  79. pp("block");
  80. if (self->parent == NULL) {
  81. pp("ERR init w/o parent");
  82. state = STATE_ERROR;
  83. rc = -1;
  84. } else {
  85. pp("setcontext to parent");
  86. _longjmp(self->parent->private, (intptr_t)&MSG_ACK);
  87. }
  88.  
  89. } else if (STATE_NULL == rc) {
  90. pp("first execution");
  91. state = STATE_RUNNING;
  92.  
  93. } else /* rc == future */ {
  94. pp("sending reply");
  95. msg = (struct message*)&rc;
  96.  
  97. msg->data_s ++;
  98.  
  99. pp("data_t = %d", msg->data_s);
  100.  
  101. if (NULL != msg->rip) {
  102. // save loc before jump
  103. //rc = _setjmp(self->private);
  104. pp("longjmp to %p", *msg->rip);
  105. //if (rc == 0)
  106. _longjmp(*msg->rip, (intptr_t)msg);
  107. } else {
  108. state = STATE_ERROR;
  109. }
  110. }
  111. } while(state >= STATE_NEW);
  112.  
  113. pp("exiting");
  114. return rc;
  115. }
  116.  
  117. coroutine * crinit(const char *name, intptr_t (*func)(coroutine*), coroutine *parent) {
  118. coroutine *new = malloc(sizeof(coroutine));
  119. if (new == NULL) {
  120. perror("coroutine new = malloc()");
  121. return NULL;
  122. }
  123.  
  124. bzero(new, sizeof(coroutine));
  125.  
  126. strncpy(new->name, name, sizeof(new->name));
  127.  
  128. if (-1 == getcontext(&new->ctx)) {
  129. perror("getcontext");
  130. return NULL;
  131. }
  132.  
  133. new->ctx.uc_stack.ss_sp = new->stack;
  134. new->ctx.uc_stack.ss_size = sizeof(new->stack);
  135.  
  136. new->parent = parent;
  137. new->ctx.uc_link = &parent->ctx;
  138.  
  139. makecontext(&new->ctx, func, 1, new);
  140.  
  141. return new;
  142. }
  143.  
  144. int main(int argc, char *argv[]) {
  145. int32_t rc = 0;
  146. struct message msg;
  147. bzero(&msg, sizeof(msg));
  148.  
  149. // setup root context
  150. coroutine root;
  151. bzero(&root, sizeof(root));
  152. coroutine *self = &root;
  153. strncpy(self->name, "root", 4);
  154.  
  155. getcontext(&root.ctx);
  156. /*
  157. coroutine *self = crinit("root", func_y, NULL);
  158. if (self == NULL)
  159. return -1;
  160. */
  161.  
  162.  
  163. coroutine *A, *B = NULL;
  164.  
  165. rc = _setjmp(self->private);
  166. if (0 == rc) {
  167. A = crinit("fn_A", func_y, self);
  168. setcontext(&A->ctx);
  169. }
  170.  
  171. rc = _setjmp(self->private);
  172. if (0 == rc) {
  173. B = crinit("fn_B", func_y, self);
  174. setcontext(&B->ctx);
  175. }
  176.  
  177. // entering root loop
  178.  
  179. msg.rip = &self->private;
  180. msg.data_s = 0;
  181. intptr_t ptr = 0;
  182.  
  183. do {
  184. ptr = _setjmp(self->private);
  185. if (msg.data_s > 5) {
  186. pp("all finished");
  187. break;
  188. }
  189. _longjmp(A->private, (intptr_t)&msg);
  190. } while(1);
  191.  
  192. pp("Final value = %i", msg.data_s);
  193.  
  194. return rc;
  195. }
Add Comment
Please, Sign In to add comment