static void doPCTest(int nProd, int nCons, int nColors, PC *pc, Mailbox *mb) { int ii; int ret; for(ii = 0; ii < nProd; ii++){ PCTestArgs *args = (PCTestArgs *)malloc(sizeof(PCTestArgs)); assert(args); args->count = OP_COUNT * nCons / nProd; args->color = ii % nColors; args->pc = pc; args->mb = mb; if(verbose){ printf("Creating producer %d %d\n", args->count, args->color); } ret = ULT_CreateThread(( void (*)(void *))pcTestProducer, args); } for(ii = 0; ii < nCons; ii++){ PCTestArgs *args = (PCTestArgs *)malloc(sizeof(PCTestArgs)); assert(args); args->count = OP_COUNT; args->color = ii % nColors; args->pc = pc; args->mb = mb; if(verbose){ printf("Creating consumer %d %d\n", args->count, args->color); } ret = ULT_CreateThread(( void (*)(void *))pcTestConsumer, args); } if(verbose){ printf("All consumers and producers created\n"); } }
// 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); }
static void mbWorker0(Mailbox *mb) { ULT_CreateThread((void (*)(void *))mbWorker1, mb); int myPart = MAXMAIL/2; int ii; for(ii = 0; ii < myPart; ii++){ mb_increment(mb, 0); ULT_Yield(ULT_ANY); ULT_Yield(ULT_ANY); } return; }
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); }
void lockTests() { ULT_Yield(ULT_ANY); startAlarmHelper(); interruptsQuiet(); /* * One mailbox */ Mailbox *mb = (Mailbox *)malloc(sizeof(Mailbox)); assert(mb); mb_init(mb, 2, MAXMAIL); ULT_CreateThread((void (*)(void *))mbWorker0, mb); while(!mb_checkDone(mb)){ ULT_Yield(ULT_ANY); } int jj; for(jj = 0; jj < 1000; jj++){ ULT_Yield(ULT_ANY); } assert(mb_checkDone(mb)); free(mb); printf("One mailbox, two threads OK\n"); /* * Two mailboxen */ mb = (Mailbox *)malloc(sizeof(Mailbox)); assert(mb); mb_init(mb, 2, MAXMAIL); Mailbox *mb2 = (Mailbox *)malloc(sizeof(Mailbox)); assert(mb2); mb_init(mb2, 2, MAXMAIL); ULT_CreateThread((void (*)(void *))mbWorker0, mb); ULT_CreateThread((void (*)(void *))mbWorker0, mb2); while(!mb_checkDone(mb)){ ULT_Yield(ULT_ANY); } for(jj = 0; jj < 1000; jj++){ ULT_Yield(ULT_ANY); } assert(mb_checkDone(mb)); while(!mb_checkDone(mb2)){ ULT_Yield(ULT_ANY); } for(jj = 0; jj < 1000; jj++){ ULT_Yield(ULT_ANY); } assert(mb_checkDone(mb2)); free(mb); free(mb2); printf("Two mailboxen, four threads OK\n"); printf("lockTests OK\n"); }