/* 1 */ #define STARTING (0) /* 2 */ #define RUNNING (1) /* 3 */ #define RUNNABLE (2) /* 4 */ #define BLOCKED (3) /* 5 */ #define SLEEPING (4) /* 6 */ #define DEAD (5) /* 7 */ /* 8 */ struct kt_str /* 9 */ { /* 10 */ void (*func)(); /* function to call */ /* 11 */ void *arg; /* arg to pass that function */ /* 12 */ int tid; /* Unique thread id */ /* 13 */ int state; /* queue state */ /* 14 */ JRB blocked_list; /* list I'm blocked on */ /* 15 */ JRB blocked_list_ptr; /* pointer to my node on the list */ /* 16 */ jmp_buf jmpbuf; /* stack/PC state */ /* 17 */ jmp_buf exitbuf; /* stack/PC state for immediate exit */ /* 18 */ char *stack; /* stack pointer */ /* 19 */ int stack_size; /* stack_size */ /* 20 */ unsigned int wake_time; /* Wake time */ /* 21 */ int die_now; /* 22 */ Ksem ks; /* in case I get killed */ /* 23 */ }; /* 24 */ /* 25 */ /* 26 */ typedef struct kt_str *K_t; /* 27 */ /* 28 */ static K_t ktRunning; /* running thread */ /* 29 */ static Dllist ktFree_me; /* threads waiting to be freed */ /* 30 */ static Dllist ktRunnable; /* run queue */ /* 31 */ static JRB ktBlocked; /* waiting for thread action */ /* 32 */ static JRB ktSleeping; /* waiting for Godot */ /* 33 */ static JRB ktActive; /* list of active threads */ /* 34 */ /* 35 */ static int KtInit_d = 0; /* 36 */ /* 37 */ static K_t ktOriginal; /* global for main thread */ /* 38 */ /* 39 */ void kt_exit() /* 40 */ { /* 41 */ JRB tmp; /* 42 */ /* 43 */ InitKThreadSystem(); /* 44 */ /* 45 */ if (ktRunning == ktOriginal) { /* 46 */ ktRunning->state = DEAD; /* 47 */ /* 48 */ tmp = jrb_find_int(ktActive, ktRunning->tid); /* 49 */ jrb_delete_node(tmp); /* 50 */ /* 51 */ tmp = jrb_find_int(ktBlocked, ktRunning->tid); /* 52 */ if (tmp != NULL) { /* 53 */ WakeKThread((K_t)tmp->val.v); /* 54 */ } /* 55 */ /* 56 */ KtSched(); /* 57 */ /* 58 */ fprintf(stderr, "Error: main thread returned\n"); /* 59 */ exit(1); /* 60 */ } else { /* 61 */ longjmp(ktRunning->exitbuf,1); /* LONGJMP #1 */ /* 62 */ } /* 63 */ } /* 64 */ /* 65 */ /* 66 */ void KtSched() /* 67 */ { /* 68 */ K_t kt; /* 69 */ JRB jb; /* 70 */ unsigned int sp; /* 71 */ unsigned int now; /* 72 */ JRB tmp; /* 73 */ Dllist dtmp; /* 74 */ /* 75 */ if(setjmp(ktRunning->jmpbuf) != 0) { /* 76 */ FreeFinishedThreads(); /* 77 */ if(ktRunning->die_now) kt_exit(); /* 78 */ return; /* 79 */ } /* 80 */ /* 81 */ start: /* 82 */ if (!jrb_empty(ktSleeping)) { /* 83 */ now = time(0); /* 84 */ while(!jrb_empty(ktSleeping)) { /* 85 */ kt = (K_t) jval_v(jrb_val(jrb_first(ktSleeping))); /* 86 */ if(kt->wake_time > now) break; /* 87 */ WakeKThread(kt); /* 88 */ } /* 89 */ } /* 90 */ /* 91 */ /* 92 */ if(dll_empty(ktRunnable)) { /* 93 */ /* 94 */ if(!jrb_empty(ktSleeping)) { /* 95 */ kt = jval_v(jrb_val(jrb_first(ktSleeping))); /* 96 */ sleep(now - kt->wake_time); /* 97 */ goto start; /* 98 */ } /* 99 */ /* 100 */ jb = jrb_find_int(ktBlocked,0); /* 101 */ if(jb != NULL) { /* 102 */ WakeKThread((K_t)jval_v(jrb_val(jb))); /* 103 */ goto start; /* 104 */ } /* 105 */ /* 106 */ if(!jrb_empty(ktBlocked)) exit(1); /* 107 */ exit(0); /* 108 */ } /* 109 */ /* 110 */ dtmp = dll_first(ktRunnable); /* 111 */ kt = (K_t) dtmp->val.v; /* 112 */ dll_delete_node(dtmp); /* 113 */ /* 114 */ if(kt->state == RUNNABLE) { /* 115 */ ktRunning = kt; /* 116 */ ktRunning->state = RUNNING; /* 117 */ longjmp(ktRunning->jmpbuf,1); /* LONGJMP #2 */ /* 118 */ } /* 119 */ /* 120 */ if(kt->state == STARTING) { /* 121 */ if(setjmp(kt->jmpbuf) == 0) { /* 122 */ sp = (unsigned int)&((kt->stack[kt->stack_size-1])); /* 123 */ while((sp % 8) != 0) sp--; /* 124 */ #ifdef LINUX /* 125 */ kt->jmpbuf->__jmpbuf[JB_BP] = (int)sp; /* 126 */ kt->jmpbuf->__jmpbuf[JB_SP] = (int)sp-1024; /* 127 */ #endif /* 128 */ #ifdef SOLARIS /* 129 */ kt->jmpbuf[JB_FP] = (int)sp; /* 130 */ kt->jmpbuf[JB_SP] = (int)sp-1024; /* 131 */ #endif /* 132 */ kt->state = RUNNING; /* 133 */ ktRunning = kt; /* 134 */ longjmp(kt->jmpbuf,1); /* LONGJMP #3 */ /* 135 */ /* 136 */ } else { /* 137 */ /* 138 */ FreeFinishedThreads(); /* 139 */ /* 140 */ if(setjmp(ktRunning->exitbuf) == 0) { /* 141 */ if(ktRunning->die_now == 0) { /* 142 */ ktRunning->func(ktRunning->arg); /* 143 */ } /* 144 */ } /* 145 */ /* 146 */ jb = jrb_find_int(ktActive,ktRunning->tid); /* 147 */ if(jb == NULL) exit(1); /* 148 */ jrb_delete_node(jb); /* 149 */ /* 150 */ jb = jrb_find_int(ktBlocked,ktRunning->tid); /* 151 */ if(jb != NULL) WakeKThread((K_t) jb->val.v) /* 152 */ /* 153 */ FreeFinishedThreads(); /* 154 */ ktRunning->state = DEAD; /* 155 */ dll_append(ktFree_me,new_jval_v(ktRunning)); /* 156 */ ktRunning = NULL; /* 157 */ goto start; /* 158 */ } /* 159 */ } /* 160 */ exit(1); /* 161 */ } /* 162 */