int main() { int ndx, odx; void* status = (void*)100; printf("test thread create, cancel, join\n"); printf("main: enter\n"); gtthread_init(period); gtthread_yield(); for(odx=0; odx<10; ++odx) { //gtthread_create( &t[odx], thrX, (void*)odx); //gtthread_create( &t[odx], thrR, (void*)odx); gtthread_create( &t[odx], thrY, (void*)odx); } gtthread_yield(); for(ndx=0; ndx<20; ++ndx) { usleep(100*1000); puts(">"); gtthread_yield(); } for(odx=0; odx<10; ++odx) { gtthread_join( t[odx], &status); printf("thread %d return %d\n",odx,(long)status); } printf("main: exit\n"); fflush(stdout); return EXIT_SUCCESS; }
int main() { gtthread_t t1, t2, t3, t4, t5; gtthread_init(1000); gtthread_mutex_init(>tm); gtthread_create(&t1, func1, (void*) 1); gtthread_create(&t2, func1, (void*) 2); gtthread_join(t1, NULL); gtthread_join(t2, NULL); gtthread_mutex_lock(>tm); gtthread_create(&t3, func2, (void*) 3); gtthread_create(&t4, func2, (void*) 4); printf("This should print before threads 3 and 4 finish\n"); gtthread_mutex_unlock(>tm); gtthread_join(t3, NULL); gtthread_join(t4, NULL); printf("Testing yield with one schedulable thread... "); gtthread_yield(); gtthread_yield(); gtthread_yield(); printf("done!\n"); printf("Deadlocking with thread 5...\n"); gtthread_mutex_lock(>tm); gtthread_create(&t5, func3, NULL); gtthread_join(t5, NULL); gtthread_mutex_unlock(>tm); printf("!!! ERROR !!! Failed to deadlock with thread 5\n"); return 0; }
int main() { int ndx, tdx; void* status = (void*)100; int result; printf("test thread create N, join N\n"); printf("main: enter\n"); gtthread_init(period); gtthread_yield(); for(tdx=0; tdx<1000; ++tdx) { gtthread_create( &t[tdx], thrX, (void*)tdx); //gtthread_create( &t[tdx], thrR, (void*)tdx); //gtthread_create( &t[tdx], thrY, (void*)tdx); } puts(">"); gtthread_yield(); for(tdx=0; tdx<1000; ++tdx) { result = gtthread_join( t[tdx], &status); if(result) printf("main.join %d\n",result); printf("thread %d return %d\n",tdx,(long)status); } printf("main: exit\n"); fflush(stdout); return EXIT_SUCCESS; }
void *philosopher(void *arg){ short i; gtthread_mutex_t f1,f2; switch((int)arg){ case 1: f1=m5; f2=m1;break; case 2: f1=m2; f2=m1;break; case 3: f1=m3; f2=m2;break; case 4: f1=m4; f2=m3;break; case 5: f1=m5; f2=m4;break; } while(1){ printf("Philosopher #%d tries to acquire fork %lu\n",(int)arg,f1); gtthread_mutex_lock(&f1); printf("Philosopher #%d tries to acquire fork %lu\n",(int)arg,f2); gtthread_mutex_lock(&f2); printf("Philosopher #%d eating with fork %lu and %lu\n",(int)arg,f1,f2); gtthread_yield(); i=rand()%9999; while(--i>0); printf("Philosopher #%d releasing fork %lu\n",(int)arg,f2); gtthread_mutex_unlock(&f2); printf("Philosopher #%d releasing fork %lu\n",(int)arg,f1); gtthread_mutex_unlock(&f1); printf("Philosopher #%d thinking\n",(int)arg); gtthread_yield(); i=rand()%9999; while(--i>0); } }
void *func1(void *arg) { gtthread_t *gtt = (gtthread_t*) arg; gtthread_yield(); // ensure that the global is set first gtthread_yield(); gtthread_yield(); int res = gtthread_equal(g_gtt, *gtt); printf("First test is equal: %s\n", res ? "correct" : "incorrect"); return NULL; }
void *func2(void *arg) { gtt_tuple *tuple = (gtt_tuple*) arg; gtthread_yield(); // ensure that the tuple is set first gtthread_yield(); gtthread_yield(); int res = gtthread_equal(tuple->gtt1, tuple->gtt2); printf("Second test is not equal: %s\n", !res ? "correct" : "incorrect"); return NULL; }
void *func3(void *arg) { gtthread_t gtt = gtthread_self(); gtthread_yield(); // ensure that the global is set first gtthread_yield(); gtthread_yield(); int res = gtthread_equal(g_gtt, gtt); printf("Third test is equal: %s\n", res ? "correct" : "incorrect"); gtthread_t *ret = malloc(sizeof(gtt)); memcpy(ret, >t, sizeof(gtt)); return ret; }
int gtthread_join(gtthread_t thread, void **status){ int i = 0; steque_node_t* current; //TODO: No need to block and unblock signals? if (gtthread_equal(thread, gtthread_self())){ printf("cannot join same thread\n"); return -1; } //Searching for node with gtthread_t thread current = q->front; for (i = 0; (i < q->N); i++) { if(gtthread_equal(thread, ((node_t*)current -> item) -> id)) { break; } current = current -> next; } //Checking for canceled thread, blocking otherwise while (1){ if (((node_t*)current -> item) -> canceled == 1){ if(status != NULL){ *status = ((node_t*)current -> item) -> returns; } break; } gtthread_yield(); } return 0; }
/* The gtthread_join() function is analogous to pthread_join. All gtthreads are joinable. */ int gtthread_join(gtthread_t thread, void **status){ gtthread_blk_t *join; DEBUG_MSG("gtthread_join\n"); sigprocmask(SIG_BLOCK, &vtalrm, NULL); // disable alarm signal join = get_thread(thread); sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); // enable alarm signal if(join == NULL) return FAIL; while(join->state != TERMINATED){ DEBUG_MSG("Thread # %ld join: not TERMINATED!\n", join->tID); gtthread_yield(); } DEBUG_MSG("Thread # %ld join: TERMINATED!\n", join->tID); //sigprocmask(SIG_BLOCK, &vtalrm, NULL); // disable alarm signal join->state = JOINED; if (status != NULL) *status = join->retval; //sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); // enable alarm signal return SUCCESS; }
void *thr3(void *in) { int i, j = 0; void *ret; gtthread_t t4; printf("thr3 started with parameter %d\n", (int) in); fflush(stdout); gtthread_create(&t4, thr4, (void *) 4); for (i = 0; i < LOOP_MAX; i++) { printf("thr3!\n"); fflush(stdout); j++; if (i % YIELD_VAL == 0) { gtthread_yield(); } } gtthread_join(t4, &ret); printf("thr4 joined thr3 with value %d!\n", (int) ret); fflush(stdout); printf("thr3 finished with parameter %d\n", (int) in); fflush(stdout); return (void *) j + 3; }
void *thr2(void *in) { int i, j = 0; void *ret; gtthread_t t5; printf("thr2 started with parameter %d\n", (int) in); fflush(stdout); gtthread_create(&t5, thr5, NULL); for (i = 0; i < (LOOP_MAX + (LOOP_MAX / 2)); i++) { printf("thr2!\n"); fflush(stdout); j++; if (i % YIELD_VAL == 0) { gtthread_yield(); } } gtthread_join(t5, NULL); printf("thr5 joined thr2 with value %d!\n", (int) ret); fflush(stdout); printf("thr2 finished with parameter %d\n", (int) in); fflush(stdout); return (void *) j + 2; }
void *thr4(void *in) { int i, j = 0; printf("thr4 started with parameter %d\n", (int) in); fflush(stdout); for (i = 0; i < LOOP_MAX; i++) { printf("thr4!\n"); fflush(stdout); j++; gtthread_mutex_lock(&count_lock); count++; gtthread_mutex_unlock(&count_lock); if (i % YIELD_VAL == 0) { gtthread_yield(); } } printf("thr4 finished with parameter %d\n", (int) in); fflush(stdout); return (void *) j + 4; }
void *func1(void *arg) { long x = (long) arg; for(int i = 5; i; --i) { gtthread_yield(); printf("Message from thr%ld\n", x); } return NULL; }
/* see man pthread_join(3) */ int gtthread_join(gtthread_t thread, void **status){ gtid_t thread_id; dlink_t* temp_dlink; thread_id = thread.threadid; BlockSignals(); temp_dlink = FindNode(schedule_queue,thread_id); if(temp_dlink == NULL){ return -1; } else if(temp_dlink == schedule_queue->begin) { while(schedule_queue->main_exited==0){ UnblockSignals(); gtthread_yield(); BlockSignals(); } if(temp_dlink->thread_block->cancelled==1){ *status = (void*)(int)-1; } else if(status!=NULL){ *status = temp_dlink->thread_block->returnval; } UnblockSignals(); return 0; } else{ while(!(temp_dlink->thread_block->exited || temp_dlink->thread_block->finished|| temp_dlink->thread_block->cancelled)){ UnblockSignals(); gtthread_yield(); BlockSignals(); } if(temp_dlink->thread_block->cancelled==1){ if(status!=NULL){ *status = (void*)(int)-1; } } else if(status!=NULL){ *status = temp_dlink->thread_block->returnval; } UnblockSignals(); return 0; } }
int main() { int i; gtthread_t t1, t2, t3, t6; void *ret; gtthread_mutex_init(&count_lock); gtthread_init(5); gtthread_create(&t1, thr1, (void *) 1); gtthread_create(&t2, thr2, (void *) 2); gtthread_create(&t3, thr3, (void *) 3); gtthread_create(&t6, thr6, (void *) 6); for (i = 0; i < LOOP_MAX; i++) { printf("Main thread!\n"); fflush(stdout); gtthread_mutex_lock(&count_lock); count++; gtthread_mutex_unlock(&count_lock); if (i % YIELD_VAL == 0) { gtthread_yield(); } } printf("main waiting for thr1...\n"); fflush(stdout); gtthread_join(t1, &ret); printf("thr1 joined main with value %d!\n", (int) ret); fflush(stdout); gtthread_cancel(t2); printf("thr2 cancelled!\n"); fflush(stdout); printf("main waiting for thr3...\n"); fflush(stdout); gtthread_join(t3, &ret); printf("thr3 joined main with value %d!\n", (int) ret); fflush(stdout); printf("main waiting for thr6...\n"); fflush(stdout); gtthread_join(t6, &ret); printf("thr6 joined main with value %d!\n", (int) ret); fflush(stdout); gtthread_mutex_lock(&count_lock); printf("Final count value: %lu\n", count); fflush(stdout); gtthread_mutex_unlock(&count_lock); gtthread_mutex_destroy(&count_lock); return EXIT_SUCCESS; }
void *thrX(void *in) { int ndx; int th = (int)(long)in; int dur = (int)hold[th]; printf("thrX: enter\n"); fflush(stdout); for(ndx=0; ndx<10; ++ndx) { gtthread_mutex_lock(&m[0]); printf("thrX: lock %d\n",th); fflush(stdout); gtthread_yield(); usleep(dur*1000); printf("thrX: unlock %d\n",th); fflush(stdout); gtthread_mutex_unlock(&m[0]); gtthread_yield(); } printf("thrX: exit\n"); fflush(stdout); gtthread_exit(in); return in; }
void *thrH(void *in) { int ndx; int th = (int)in; int dur = (int)hold[th]; gtthread_mutex_t* mtx = m[0]; printf("thrH: enter\n"); fflush(stdout); for(ndx=0; ndx<10; ++ndx) { gtthread_mutex_lock(mutex); printf("thrH: lock %d\n",th); fflush(stdout); gtthread_yield(); usleep(dur*1000); gtthread_yield(); printf("thrH: unlock %d\n",th); fflush(stdout); gtthread_mutex_unlock(mutex); gtthread_yield(); } printf("thrH: exit\n"); fflush(stdout); return in; }
void *thrY(void *in) { int ndx; printf("thrY: enter\n"); fflush(stdout); for(ndx=0; ndx<5; ++ndx) { usleep(10*1000); puts("Y"); gtthread_yield(); } printf("thrY: exit\n"); fflush(stdout); return in; }
void* thr2(void *in) { gtthread_mutex_lock(&g_mutex); gtthread_mutex_unlock(&g_mutex); int k = 0; for (k = 0; k < 5; ++k) { gtthread_mutex_lock(&g_mutex); printf("thr2 hello\n"); gtthread_mutex_unlock(&g_mutex); gtthread_yield(); } return NULL; }
void *thrR(void *in) { int ndx; printf("thrR: enter\n"); fflush(stdout); ++steps[(long)in]; for(ndx=0; ndx<10; ++ndx) { usleep(100*1000); puts("R"); gtthread_yield(); } printf("thrR: exit\n"); fflush(stdout); return in; }
void* worker(void* arg) { int i; gtthread_mutex_lock(&g_mutex); for(i=0; i < 3; i++) { printf("thread %ld\n", (long)arg); gtthread_yield(); } gtthread_mutex_unlock(&g_mutex); return NULL; }
/* The gtthread_create() function mirrors the pthread_create() function, only default attributes are always assumed. */ int gtthread_create(gtthread_t *thread, void *(*start_routine)(void *), void *arg){ ucontext_t uctx; gtthread_blk_t *th_blk; DEBUG_MSG("gtthread_create\n"); //sigprocmask(SIG_BLOCK, &vtalrm, NULL); // disable alarm signal /************************* Initialize the context *************************************/ if(getcontext(&uctx) == -1) return FAIL; uctx.uc_stack.ss_sp = (char*) malloc(SIGSTKSZ); uctx.uc_stack.ss_size = SIGSTKSZ; uctx.uc_link = NULL; makecontext(&uctx, (void (*) (void))(thread_handler), 2, start_routine, arg); // modify the context /************************** Initialize the thread block *************************************/ th_blk = (gtthread_blk_t *)malloc(sizeof(gtthread_blk_t)); if(th_blk == NULL) return FAIL; th_blk->tID = thread_ID++; th_blk->state = READY; th_blk->uctx = uctx; if(th_blk->uctx.uc_stack.ss_size == SIGSTKSZ) DEBUG_MSG("Correct assign\n"); /********************************************************************************************/ steque_enqueue(&thread_queue, th_blk); // add the thread to the scheduler queue //sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); // enable alarm signal *thread = th_blk->tID; //list_thread(); gtthread_yield(); return SUCCESS; }
void *thr5(void *in) { int i, j = 0; for (i = 0; i < LOOP_MAX; i++) { printf("thr5!\n"); fflush(stdout); j++; if (i % YIELD_VAL == 0) { gtthread_yield(); } } return (void *) 5; }
int main() { printf("test6b. Should print 'main hello' then 'thr1 hello' and 'thr2 hello' for 5 times interleaving (but no mixed up prints e.g. 'th1 thr2 hello hello')\n"); gtthread_init(50000L); gtthread_mutex_init(&g_mutex); gtthread_mutex_lock(&g_mutex); gtthread_create( &t1, thr1, NULL); gtthread_create( &t2, thr2, NULL); gtthread_yield(); printf("main hello\n"); gtthread_mutex_unlock(&g_mutex); gtthread_join(t2, NULL); gtthread_join(t1, NULL); return EXIT_SUCCESS; }
void *func2(void *arg) { long x = (long) arg; volatile int y; for(int i = 5; i; --i) { gtthread_mutex_lock(>tm); gtthread_yield(); char *dst = buffer, *src = "\tThis is a locked message from thread "; while((*dst++ = *src++)) { y = 5000000; while(--y); } printf("%s%ld\n", buffer, x); memset(buffer, ' ', 50); gtthread_mutex_unlock(>tm); } return NULL; }
/* The gtthread_exit() function is analogous to pthread_exit. */ void gtthread_exit(void* retval){ gtthread_blk_t *term; DEBUG_MSG("gtthread_exit\n"); sigprocmask(SIG_BLOCK, &vtalrm, NULL); // disable alarm signal term = (gtthread_blk_t *)steque_front(&thread_queue); if(term->state != RUNNING) { DEBUG_MSG("ERROR state when gtthread_exit: term->state != RUNNING\n"); return; } term->state = TERMINATED; term->retval = retval; sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); // enable alarm signal gtthread_yield(); }
int gtthread_mutex_lock(gtthread_mutex_t *mutex){ blockTimer(); // Possibly reentrant lock if(mutex->mutex_owner == current_context->thread_id && mutex->mutex_lock==1){ unblockTimer(); return 0; } // Wait till the lock is free while(mutex->mutex_lock == 1 && mutex->mutex_owner != current_context->thread_id){ unblockTimer(); gtthread_yield(); blockTimer(); }; mutex->mutex_lock = 1; mutex->mutex_owner = current_context->thread_id; unblockTimer(); return 0; }