diff --git a/kern/conf/conf.kern b/kern/conf/conf.kern index 4b4fdaf..61f1b1d 100644 --- a/kern/conf/conf.kern +++ b/kern/conf/conf.kern @@ -442,7 +442,7 @@ file test/threadlisttest.c file test/threadtest.c file test/tt3.c file test/synchtest.c -file test/rwtest.c +file test/rwtest.c file test/semunit.c file test/hmacunit.c file test/kmalloctest.c diff --git a/kern/include/kern/secret.h b/kern/include/kern/secret.h index 16c3903..2b725e8 100644 --- a/kern/include/kern/secret.h +++ b/kern/include/kern/secret.h @@ -45,6 +45,6 @@ */ #undef SECRET_TESTING -#define SECRET "TEST" +#define SECRET "SECRET" #endif /* _SECRET_H_ */ diff --git a/kern/test/synchprobs.c b/kern/test/synchprobs.c index 07fec9a..65641f9 100644 --- a/kern/test/synchprobs.c +++ b/kern/test/synchprobs.c @@ -25,38 +25,12 @@ static uint32_t startcount; static struct lock *testlock; static struct cv *startcv; -static struct cv *endcv; +static struct semaphore *startsem; static struct semaphore *endsem; struct spinlock status_lock; static bool test_status = FAIL; - -static -void -inititems(uint32_t count) -{ - startcount = count; - - if (testlock==NULL) { - testlock = lock_create("testlock"); - if (testlock == NULL) { - panic("synchprobs: lock_create failed\n"); - } - } - if (startcv==NULL) { - startcv = cv_create("startcv"); - if (startcv == NULL) { - panic("synchprobs: cv_create failed\n"); - } - } - if (endsem==NULL) { - endsem = sem_create("endsem", 0); - if (endsem == NULL) { - panic("synchprobs: sem_create failed\n"); - } - } - spinlock_init(&status_lock); -} +const char *test_message; /* * Helper function to initialize the thread pool. @@ -66,6 +40,7 @@ void initialize_thread(volatile void* threads[], uint32_t index) { if (threads[index] != NULL) { test_status = FAIL; + test_message = "failed: incorrect thread type"; } threads[index] = curthread->t_stack; } @@ -78,6 +53,7 @@ void check_thread(volatile void* threads[], uint32_t index) { if (threads[index] != curthread->t_stack) { test_status = FAIL; + test_message = "failed: incorrect thread type"; } } @@ -113,6 +89,7 @@ void check_role(uint32_t index, int role) { if (whale_roles[index] != role) { test_status = FAIL; + test_message = "failed: incorrect role"; } } @@ -125,10 +102,8 @@ male_wrapper(void * unused1, unsigned long index) { lock_acquire(testlock); initialize_thread(whale_threads, (uint32_t)index); whale_roles[index] = MALE; - startcount--; lock_release(testlock); male((uint32_t)index); - V(endsem); return; } @@ -139,12 +114,12 @@ male_start(uint32_t index) { check_thread(whale_threads, index); check_role(index, MALE); male_start_count++; - cv_signal(startcv, testlock); lock_release(testlock); random_yielder(PROBLEMS_MAX_YIELDER); random_spinner(PROBLEMS_MAX_SPINNER); kprintf_n("%s starting\n", curthread->t_name); kprintf_t("."); + V(startsem); } void male_end(uint32_t index) { @@ -152,13 +127,13 @@ male_end(uint32_t index) { lock_acquire(testlock); check_thread(whale_threads, index); check_role(index, MALE); - cv_signal(endcv, testlock); male_end_count++; lock_release(testlock); random_yielder(PROBLEMS_MAX_YIELDER); random_spinner(PROBLEMS_MAX_SPINNER); kprintf_n("%s ending\n", curthread->t_name); kprintf_t("."); + V(endsem); } static @@ -170,10 +145,8 @@ female_wrapper(void * unused1, unsigned long index) { lock_acquire(testlock); initialize_thread(whale_threads, (uint32_t)index); whale_roles[index] = FEMALE; - startcount--; lock_release(testlock); female((uint32_t)index); - V(endsem); return; } @@ -184,12 +157,12 @@ female_start(uint32_t index) { check_thread(whale_threads, index); check_role(index, FEMALE); female_start_count++; - cv_signal(startcv, testlock); lock_release(testlock); random_yielder(PROBLEMS_MAX_YIELDER); random_spinner(PROBLEMS_MAX_SPINNER); kprintf_n("%s starting\n", curthread->t_name); kprintf_t("."); + V(startsem); } void female_end(uint32_t index) { @@ -197,13 +170,13 @@ female_end(uint32_t index) { lock_acquire(testlock); check_thread(whale_threads, index); check_role(index, FEMALE); - cv_signal(endcv, testlock); female_end_count++; lock_release(testlock); random_yielder(PROBLEMS_MAX_YIELDER); random_spinner(PROBLEMS_MAX_SPINNER); kprintf_n("%s ending\n", curthread->t_name); kprintf_t("."); + V(endsem); } static @@ -215,27 +188,25 @@ matchmaker_wrapper(void * unused1, unsigned long index) { lock_acquire(testlock); initialize_thread(whale_threads, (uint32_t)index); whale_roles[index] = MATCHMAKER; - startcount--; lock_release(testlock); matchmaker((uint32_t)index); - V(endsem); return; } void matchmaker_start(uint32_t index) { (void)index; + P(matcher_sem); lock_acquire(testlock); check_thread(whale_threads, index); check_role(index, MATCHMAKER); matchmaker_start_count++; - cv_signal(startcv, testlock); lock_release(testlock); random_yielder(PROBLEMS_MAX_YIELDER); random_spinner(PROBLEMS_MAX_SPINNER); kprintf_n("%s starting\n", curthread->t_name); kprintf_t("."); - P(matcher_sem); + V(startsem); } void matchmaker_end(uint32_t index) { @@ -251,12 +222,12 @@ matchmaker_end(uint32_t index) { match_count++; matchmaker_end_count++; - cv_signal(endcv, testlock); lock_release(testlock); random_yielder(PROBLEMS_MAX_YIELDER); random_spinner(PROBLEMS_MAX_SPINNER); kprintf_n("%s ending\n", curthread->t_name); kprintf_t("."); + V(endsem); } static @@ -265,6 +236,7 @@ check_zero(int count, const char *name) { (void)name; if (count != 0) { test_status = FAIL; + test_message = "failed: not all threads completed"; } } @@ -275,6 +247,8 @@ whalemating(int nargs, char **args) { int i, j, err = 0; char name[32]; + bool loop_status; + int total_count = 0; male_start_count = 0 ; male_end_count = 0 ; @@ -284,18 +258,13 @@ whalemating(int nargs, char **args) { matchmaker_end_count = 0; match_count = 0; - startcount = 3 * NMATING; testlock = lock_create("testlock"); if (testlock == NULL) { panic("sp1: lock_create failed\n"); } - startcv = cv_create("startcv"); - if (startcv == NULL) { - panic("sp1: cv_create failed\n"); - } - endcv = cv_create("endcv"); - if (endcv == NULL) { - panic("sp1: cv_create failed\n"); + startsem = sem_create("startsem", 0); + if (startsem == NULL) { + panic("sp1: sem_create failed\n"); } endsem = sem_create("endsem", 0); if (endsem == NULL) { @@ -306,7 +275,8 @@ whalemating(int nargs, char **args) { panic("sp1: sem_create failed\n"); } spinlock_init(&status_lock); - test_status = FAIL; + test_status = SUCCESS; + test_message = ""; whalemating_init(); @@ -326,6 +296,7 @@ whalemating(int nargs, char **args) { err = thread_fork(name, NULL, female_wrapper, NULL, index); break; } + total_count += 1; if (err) { panic("whalemating: thread_fork failed: (%s)\n", strerror(err)); } @@ -335,14 +306,12 @@ whalemating(int nargs, char **args) { /* Wait for males and females to start. */ for (i = 0; i < NMATING * 2; i++) { kprintf_t("."); - lock_acquire(testlock); - cv_wait(startcv, testlock); - lock_release(testlock); + P(startsem); } /* Make sure nothing is happening... */ - bool loop_status = SUCCESS; - for (i = 0; i < CHECK_TIMES && loop_status == SUCCESS; ) { + loop_status = SUCCESS; + for (i = 0; i < CHECK_TIMES && loop_status == SUCCESS; i++) { kprintf_t("."); random_spinner(PROBLEMS_MAX_SPINNER); lock_acquire(testlock); @@ -354,6 +323,7 @@ whalemating(int nargs, char **args) { } if (loop_status == FAIL) { test_status = FAIL; + test_message = "failed: uncoordinated matchmaking is occurring"; goto done; } @@ -367,6 +337,7 @@ whalemating(int nargs, char **args) { if (err) { panic("whalemating: thread_fork failed: (%s)\n", strerror(err)); } + total_count++; } /* @@ -380,26 +351,26 @@ whalemating(int nargs, char **args) { } for (i = 0; i < 3 * pivot; i++) { kprintf_t("."); - lock_acquire(testlock); - cv_wait(endcv, testlock); - lock_release(testlock); + P(endsem); + total_count--; } /* Make sure nothing else is happening... */ - bool loop_status = SUCCESS; - for (i = 0; i < CHECK_TIMES && loop_status == SUCCESS; ) { + loop_status = SUCCESS; + for (i = 0; i < CHECK_TIMES && loop_status == SUCCESS; i++) { kprintf_t("."); random_spinner(PROBLEMS_MAX_SPINNER); lock_acquire(testlock); if ((male_start_count != NMATING) || (female_start_count != NMATING) || - (male_end_count != pivot) || (female_end_count != pivot) || - (matchmaker_start_count != pivot) || (matchmaker_end_count != pivot)) { + (matchmaker_start_count != pivot) || (male_end_count != pivot) || + (female_end_count != pivot) || (matchmaker_end_count != pivot)) { loop_status = FAIL; } lock_release(testlock); } if (loop_status == FAIL) { test_status = FAIL; + test_message = "failed: uncoordinating matchmaking is occurring"; goto done; } @@ -408,12 +379,14 @@ whalemating(int nargs, char **args) { */ for (i = pivot; i < NMATING; i++) { + kprintf_t("."); V(matcher_sem); } for (i = 0; i < 3; i++) { - for (j = 0; j < NMATING; j++) { + for (j = pivot; j < NMATING; j++) { kprintf_t("."); P(endsem); + total_count--; } } @@ -435,22 +408,31 @@ whalemating(int nargs, char **args) { if (male == 0 || female == 0) { spinlock_acquire(&status_lock); test_status = FAIL; + test_message = "failed: not all males were matched"; spinlock_release(&status_lock); } } } else { spinlock_acquire(&status_lock); test_status = FAIL; + test_message = "failed: not all males were matched"; spinlock_release(&status_lock); } done: + for (i = 0; i < total_count; i++) { + P(endsem); + } + lock_destroy(testlock); - cv_destroy(startcv); - cv_destroy(endcv); + sem_destroy(startsem); sem_destroy(endsem); sem_destroy(matcher_sem); + kprintf_t("\n"); + if (test_status != SUCCESS) { + ksecprintf(SECRET, test_message, "sp1"); + } success(test_status, SECRET, "sp1"); return 0; @@ -493,7 +475,7 @@ check_intersection() { int n = 0; for (int i = 0; i < NUM_QUADRANTS; i++) { if (quadrant_array[i] > 1) { - // panic("stoplight: more than 1 car in same quadrant %d\n", i); + test_message = "failed: collision"; test_status = FAIL; } n += quadrant_array[i]; @@ -588,11 +570,13 @@ inQuadrant(int quadrant, uint32_t index) { switch (car_turn_times[index]) { case 0: if (pre_quadrant != UNKNOWN_CAR) { + test_message = "failed: invalid turn"; test_status = FAIL; } break; case 1: if (pre_quadrant != target_quadrant) { + test_message = "failed: invalid turn"; test_status = FAIL; } target_quadrant = (target_quadrant + NUM_QUADRANTS - 1) % NUM_QUADRANTS; @@ -600,6 +584,7 @@ inQuadrant(int quadrant, uint32_t index) { case 2: target_quadrant = (target_quadrant + NUM_QUADRANTS - 1) % NUM_QUADRANTS; if (pre_quadrant != target_quadrant) { + test_message = "failed: invalid turn"; test_status = FAIL; } target_quadrant = (target_quadrant + NUM_QUADRANTS - 1) % NUM_QUADRANTS; @@ -614,7 +599,7 @@ inQuadrant(int quadrant, uint32_t index) { car_turn_times[index]++; if (quadrant_array[quadrant] > 0) { - // panic("%s inQuadrant %d which already has another car\n", curthread->t_name, quadrant); + test_message = "failed: collision"; test_status = FAIL; } quadrant_array[quadrant]++; @@ -635,16 +620,19 @@ leaveIntersection(uint32_t index) { switch (car_turns[index]) { case GO_STRAIGHT: if (car_turn_times[index] != 2) { + test_message = "failed: incorrect turn"; test_status = FAIL; } break; case TURN_LEFT: if (car_turn_times[index] != 3) { + test_message = "failed: incorrect turn"; test_status = FAIL; } break; case TURN_RIGHT: if (car_turn_times[index] != 1) { + test_message = "failed: incorrect turn"; test_status = FAIL; } break; @@ -658,22 +646,16 @@ leaveIntersection(uint32_t index) { kprintf_n("%s left the intersection\n", curthread->t_name); } -// TODO: should we delete this? -struct semaphore * stoplightMenuSemaphore; - int stoplight(int nargs, char **args) { (void) nargs; (void) args; int i, direction, turn, err = 0; char name[32]; - - inititems(NCARS); - stoplight_init(); - test_status = SUCCESS; + int required_quadrant = 0; + int passed = 0; max_car_count = 0; all_quadrant = 0; - int required_quadrant = 0; for (i = 0; i < NUM_QUADRANTS; i++) { quadrant_array[i] = 0; @@ -685,7 +667,26 @@ int stoplight(int nargs, char **args) { car_directions[i] = -1; } + startcount = NCARS; + testlock = lock_create("testlock"); + if (testlock == NULL) { + panic("sp2: lock_create failed\n"); + } + startcv = cv_create("startcv"); + if (startcv == NULL) { + panic("sp2: cv_create failed\n"); + } + endsem = sem_create("endsem", 0); + if (endsem == NULL) { + panic("sp2: sem_create failed\n"); + } + spinlock_init(&status_lock); + test_status = SUCCESS; + + stoplight_init(); + for (i = 0; i < NCARS; i++) { + kprintf_t("."); direction = random() % 4; turn = random() % 3; @@ -712,39 +713,36 @@ int stoplight(int nargs, char **args) { } for (i = 0; i < NCARS; i++) { + kprintf_t("."); P(endsem); } stoplight_cleanup(); - if (test_status == FAIL) { - success(test_status, SECRET, "sp2"); - return 0; - } - - // Check all cars pass the intersection - int passed = 0; for (i = 0; i < NCARS; i++) { passed += car_locations[i] == PASSED_CAR ? 1 : 0; } - if (passed != NCARS) { - // panic("stoplight: not all cars pass the intersection, total: %d, passed: %d\n", NCARS, passed); - success(FAIL, SECRET, "sp2"); - return 0; + if (test_status == SUCCESS) { + if (passed != NCARS) { + test_message = "failed: not enough cars"; + test_status = FAIL; + } else if (all_quadrant != required_quadrant) { + test_message = "failed: didn't do the right turns"; + test_status = FAIL; + } else if (max_car_count <= 1) { + test_message = "failed: no concurrency achieved"; + test_status = FAIL; + } } - // Check hit quadrant times is same as required, for example, student can force all cars turn right - if (all_quadrant != required_quadrant) { - // panic("stoplight: you may make wrong turn for some cars\n"); - success(FAIL, SECRET, "sp2"); - return 0; - } + lock_destroy(testlock); + cv_destroy(startcv); + sem_destroy(endsem); - if (max_car_count <= 1) { - test_status = FAIL; - // panic("stoplight: only one car in the intersection at same time, did you use big lock?\n"); + kprintf_t("\n"); + if (test_status != SUCCESS) { + ksecprintf(SECRET, test_message, "sp2"); } - success(test_status, SECRET, "sp2"); return 0; diff --git a/kern/test/synchtest.c b/kern/test/synchtest.c index be94df6..1e41526 100644 --- a/kern/test/synchtest.c +++ b/kern/test/synchtest.c @@ -107,6 +107,7 @@ semtest(int nargs, char **args) kprintf_n("Starting sem1...\n"); for (i=0; i