static void suicide() { int ret = setFlag(1); assert(ret == 0); ULT_DestroyThread(ULT_SELF); assert(0); }
//New theads must run stub //Destroyed implicitly when it returns to stub void stub(void (*root)(void *), void *arg) { root(arg); // Thread starts by calling root function //printf("Thread[%d] ending\n", runningThread->id); Tid ret = ULT_DestroyThread(ULT_SELF); assert(ret == ULT_NONE); // we should only get here if we are the last thread. exit(0); // all threads are done, so process should exit }
void stub(void (*root)(void *), void *arg) { // thread starts here Tid ret; root(arg); // call root function ret = ULT_DestroyThread(ULT_SELF); assert(ret == ULT_NONE); // we should only get here if we are the last thread. exit(0); // all threads are done, so process should exit }
void stub(void (*root)(void *), void *arg) { if(debug) printf("%s","In the stub\n"); if(debug) printf("%s%s%s","Running stub passed arg ",(char*)arg,"\n"); // thread starts here Tid ret; root(arg); // call root function ret = ULT_DestroyThread(ULT_SELF); assert(ret == ULT_NONE); // we should only get here if we are the last thread. exit(0); // all threads are done, so process should exit }
// Tests creation, yielding, destruction, and yielding to a nonexistent thread // arg is the string to print within the method. void funkyTown(char* arg) { printf("%s",arg); Tid weave = ULT_CreateThread((void (*)(void *))doALittleDance, "Make a little love\n"); Tid ret = ULT_Yield(weave); assert(ret == weave); Tid ret2 = ULT_DestroyThread(weave); assert(ret2 == weave); Tid ret3 = ULT_Yield(ret2); assert(ret3 = ULT_INVALID); }
void grandFinale() { int ret; printf("For my grand finale, I will destroy myself\n"); printf("while my talented assistant prints Done.\n"); ret = ULT_CreateThread((void (*)(void *))finale, NULL); assert(ULT_isOKRet(ret)); ULT_DestroyThread(ULT_SELF); assert(0); }
void stub() { Tid ret; /* call function */ __asm__ ( "mov %esi,(%esp);" // move parg onto stack "call %edi;" // call function on parg ); ret = ULT_DestroyThread(ULT_SELF); assert(ret == ULT_NONE); exit(0); }
int main(int argc, char **argv) { printf("Starting our tests....\n"); Tid IAmNotValid = 5; Tid linen; Tid cotton; Tid silk; // Get it? Because they are threads... printf("Testing destruction of a nonexistent thread.\n"); IAmNotValid = ULT_DestroyThread(IAmNotValid); assert(IAmNotValid == ULT_INVALID); printf("Testing creation of a thread and yielding to it.\n"); linen = ULT_CreateThread((void (*)(void *))doALittleDance, "Make a little love\n"); cotton = ULT_Yield(linen); assert(cotton == linen); printf("Testing destruction of a thread.\n"); Tid ret = ULT_DestroyThread(linen); assert(ret == linen); printf("Testing creation of a thread with a more complex root function, and then yielding to it.\n"); silk = ULT_CreateThread((void (*)(void *))funkyTown, "In the funkyTown method and the arg was passed just fine. Woohoo.\n"); Tid cloth = ULT_Yield(silk); assert(cloth == silk); printf("Testing destruction of a thread that has already terminated naturally.\n"); Tid deleteAttempt = ULT_DestroyThread(silk); assert(deleteAttempt == ULT_INVALID); printf("You have passed all your tests! Nice dude!\n"); return 1; }
void preemptiveTests() { static const int duration = 10; int ret; int ii; startAlarmHelper(); spin(2); interruptsQuiet(); potato[0] = 1; for(ii = 1; ii < NPOTATO; ii++){ potato[ii] = 0; } printf("Running hot potato test. This will take %d seconds\n", duration); for(ii = 0; ii < NPOTATO; ii++){ potatoTids[ii] = ULT_CreateThread((void (*)(void *))doPotato, (void *)ii); assert(ULT_isOKRet(potatoTids[ii])); } spin(duration); printf("Hot potato done. Cleaning up\n"); for(ii = 0; ii < NPOTATO; ii++){ ret = ULT_DestroyThread(ULT_ANY); assert(ULT_isOKRet(ret)); } printf("Done.\n"); }
void basicThreadTests() { Tid ret; Tid ret2; printf("Starting tests...\n"); /* * Initial thread yields */ ret = ULT_Yield(ULT_SELF); assert(ULT_isOKRet(ret)); printf("Initial thread returns from Yield(SELF)\n"); ret = ULT_Yield(0); /* See ULT.h -- initial thread must be Tid 0 */ assert(ULT_isOKRet(ret)); printf("Initial thread returns from Yield(0)\n"); ret = ULT_Yield(ULT_ANY); assert(ret == ULT_NONE); printf("Initial thread returns from Yield(ANY)\n"); ret = ULT_Yield(0xDEADBEEF); assert(ret == ULT_INVALID); printf("Initial thread returns from Yield(INVALID)\n"); ret = ULT_Yield(16); assert(ret == ULT_INVALID); printf("Initial thread returns from Yield(INVALID2)\n"); /* * Create a thread */ ret = ULT_CreateThread((void (*)(void *))hello, "World"); assert(ULT_isOKRet(ret)); ret2 = ULT_Yield(ret); assert(ret2 == ret); /* * Create 10 threads */ int ii; static const int NTHREAD = 10; Tid children[NTHREAD]; char msg[NTHREAD][1024]; for(ii = 0; ii < NTHREAD; ii++){ ret = snprintf(msg[ii], 1023, "Hello from thread %d\n", ii); assert(ret > 0); children[ii] = ULT_CreateThread((void (*)(void *))hello, msg[ii]); assert(ULT_isOKRet(children[ii])); } for(ii = 0; ii < NTHREAD; ii++){ ret = ULT_Yield(children[ii]); assert(ret == children[ii]); } /* * Destroy 11 threads we just created */ ret = ULT_DestroyThread(ret2); assert(ret == ret2); for(ii = 0; ii < NTHREAD; ii++){ ret = ULT_DestroyThread(children[ii]); assert(ret == children[ii]); } /* * Create maxthreads-1 threads */ printf("Creating %d threads\n", ULT_MAX_THREADS-1); for(ii = 0; ii < ULT_MAX_THREADS-1; ii++){ ret = ULT_CreateThread((void (*)(void *))fact, (void *)10); assert(ULT_isOKRet(ret)); } /* * Now we're out of threads. Next create should fail. */ ret = ULT_CreateThread((void (*)(void *))fact, (void *)10); assert(ret == ULT_NOMORE); /* * Now let them all run. */ printf("Running %d threads\n", ULT_MAX_THREADS-1); for(ii = 0; ii < ULT_MAX_THREADS; ii++) { ret = ULT_Yield(ii); if(ii == 0){ /* * Guaranteed that first yield will find someone. * Later ones may or may not depending on who * stub schedules on exit. */ assert(ULT_isOKRet(ret)); } } /* * They should have cleaned themselves up when * they finished running. Create maxthreads-1 threads. */ printf("Creating %d threads\n", ULT_MAX_THREADS-1); for(ii = 0; ii < ULT_MAX_THREADS-1; ii++){ ret = ULT_CreateThread((void (*)(void *))fact, (void *)10); assert(ULT_isOKRet(ret)); } /* * Now destroy some explicitly and let the others run */ printf("Destorying %d threads, running the rest\n", ULT_MAX_THREADS/2); for(ii = 0; ii < ULT_MAX_THREADS; ii+=2){ ret = ULT_DestroyThread(ULT_ANY); assert(ULT_isOKRet(ret)); } for(ii = 0; ii < ULT_MAX_THREADS; ii++){ ret = ULT_Yield(ii); } printf("Trying some destroys even though I'm the only thread\n"); ret = ULT_DestroyThread(ULT_ANY); assert(ret == ULT_NONE); ret = ULT_DestroyThread(42); assert(ret == ULT_INVALID); ret = ULT_DestroyThread(-42); assert(ret == ULT_INVALID); ret = ULT_DestroyThread(ULT_MAX_THREADS + 1000); assert(ret == ULT_INVALID); /* * Create a thread that destroys itself. * Control should come back here after * that thread runs. */ printf("Testing destroy self\n"); int flag = setFlag(0); ret = ULT_CreateThread((void (*)(void *))suicide, NULL); assert(ULT_isOKRet(ret)); ret = ULT_Yield(ret); assert(ULT_isOKRet(ret)); flag = setFlag(0); assert(flag == 1); /* Other thread ran */ /* That thread is gone now */ ret = ULT_Yield(ret); assert(ret == ULT_INVALID); }