/* MyInitThreads () initializes the thread package. Must be the first * function called by any user program that uses the thread package. */ void setStackSpace(int pos) { if(pos < 1){ thread[0].clean = 0; longjmp(thread[0].clean_env, 2); } char s[STACKSIZE]; if( setjmp(thread[MAXTHREADS - pos].clean_env) == 0){ if(DEBUG == 1) Printf("thread %d env %d\n", MAXTHREADS - pos, thread[MAXTHREADS - pos].clean_env); if (((int) &s[STACKSIZE-1]) - ((int) &s[0]) + 1 != STACKSIZE) { if(DEBUG == 1) Printf ("Stack space reservation failed\n"); Exit (); } setStackSpace(pos - 1); }else{ thread[head].clean = 0; if(DEBUG == 1) Printf("setting jump for thread %d\n", head); if (setjmp (thread[head].env) == 0) { /* save context of 1 */ if(DEBUG == 1) Printf("setting env as %d\n", thread[head].env); longjmp (thread[current_tid].env, 1); /* back to thread 0 */ } void (*f)() = thread[current_tid].func; /* f saves func on top of stack */ int p = thread[current_tid].param; /* p saves param on top of stack */ if(DEBUG == 1) Printf("Executing thread %d program\n",MAXTHREADS - pos ); /* here when thread 1 is scheduled for the first time */ (*f) (p); /* execute func (param) */ MyExitThread (); /* thread 1 is done - exit */ } }
void MyInitThreads () { int i; int t; int s; if (MyInitThreadsCalled) { /* run only once */ Printf ("InitThreads: should be called only once\n"); Exit (); } for (i = 0; i < MAXTHREADS; i++) { /* initialize thread table */ thread[i].valid = 0; queue[i].valid = 0; queue[i].prev = -1; queue[i].next = -1; } thread[0].valid = 1; /* initialize thread 0 */ addFront(0); if(debug){ Printf("Front: %d Back: %d prev: %d next: %d size: %d \n",front,back,queue[0].prev,queue[0].next,queuesize ); } if ((s =setjmp(thread[0].env_clean)) == 0){ for (i = 1; i <= MAXTHREADS; i ++){ char s[i*STACKSIZE]; if (((int) &s[STACKSIZE-1]) - ((int) &s[0]) + 1 != STACKSIZE) Exit (); if ((t = setjmp(thread[i].env_clean)) != 0){ if(debug) Printf("longjmp %d\n",t); (*thread[t-1].func) (thread[t-1].param); MyExitThread(); } } } else{ (*thread[0].func) (thread[0].param); MyExitThread(); } MyInitThreadsCalled = 1; }
void yieldTo(int n) { int stackvar = n * 2; Printf("%d: [0] yieldTo(%d) -> %d\n", MyGetThread(), n, stackvar); Printf(" Yielding: %d -> %d\n", MyGetThread(), n); Printf(" Yielded: %d -> %d\n", MyYieldThread(n), MyGetThread()); MyExitThread (); Printf("%d: [1] yieldTo(%d) -> %d\n", MyGetThread(), n, stackvar); Printf(" Scheding: %d -> ?\n", MyGetThread()); MySchedThread(); Printf("%d: [2] yieldTo(%d) -> %d\n", MyGetThread(), n, stackvar); }
void MyInitThreads () { int i; int setjum_ret; thread[0].valid = 1; /* the initial thread is 0 */ thread[0].clean = 1; for (i = 1; i < MAXTHREADS; i++) { /* all other threads invalid */ thread[i].valid = 0; thread[i].clean = 1; } MyInitThreadsCalled = 1; init_queue(&tid_queue); enqueue(&tid_queue, 0); char s[STACKSIZE]; setjum_ret = setjmp(thread[0].clean_env); if(DEBUG == 1) Printf("thread %d env %d\n", 0, thread[0].clean_env); if( setjum_ret == 0){ if (((int) &s[STACKSIZE-1]) - ((int) &s[0]) + 1 != STACKSIZE) { if(DEBUG == 1) Printf ("Stack space reservation failed\n"); Exit (); } setStackSpace(MAXTHREADS - 1); }else if(setjum_ret == 2){ if(DEBUG == 1) Printf("finish carving stack\n"); return; }else{ thread[0].clean = 0; if(DEBUG == 1) Printf("setting jump for thread %d\n", 0); if (setjmp (thread[0].env) == 0) { /* save context of 1 */ if(DEBUG == 1) Printf("setting env as %d\n", thread[0].env); longjmp (thread[current_tid].env, 1); /* back to thread 0 */ } void (*f)() = thread[current_tid].func; /* f saves func on top of stack */ int p = thread[current_tid].param; /* p saves param on top of stack */ /* here when thread 1 is scheduled for the first time */ (*f) (p); /* execute func (param) */ MyExitThread(); return; } }
void Main() { int stackvar = -5; MyInitThreads(); MySpawnThread(yieldTo, 1); MySpawnThread(yieldTo, 0); MySpawnThread(yieldTo, 4); MySpawnThread(yieldTo, 2); Printf("%d: [0] yieldTo(%d) -> %d\n", MyGetThread(), 3, stackvar); Printf(" Yielding: %d -> %d\n", MyGetThread(), 3); MyYieldThread(3); Printf("%d: [1] yieldTo(%d) -> %d\n", MyGetThread(), 3, stackvar); Printf(" Scheding: %d -> ?\n", MyGetThread()); MySchedThread(); Printf("%d: [2] yieldTo(%d) -> %d\n", MyGetThread(), 3, stackvar); MySpawnThread(yieldTo, 4); MySpawnThread(yieldTo, 7); MySpawnThread(yieldTo, 8); MySpawnThread(yieldTo, 6); MyExitThread (); }
void exitThread() { if(useDefault) ExitThread(); else MyExitThread(); }