123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807 |
- /*
- * catmouse.c
- *
- * 30-1-2003 : GWA : Stub functions created for CS161 Asst1.
- * 26-11-2007: KMS : Modified to use cat_eat and mouse_eat
- * 21-04-2009: KMS : modified to use cat_sleep and mouse_sleep
- * 21-04-2009: KMS : added sem_destroy of CatMouseWait
- * 05-01-2012: TBB : added comments to try to clarify use/non use of volatile
- * 22-08-2013: TBB: made cat and mouse eating and sleeping time optional parameters
- * 27-04-2014: KMS: change this to simulation driver that invokes student-implemented synch functions
- * 26-01-2015: TBB: adding info about which cat and mouse are eating to be used for debugging
- *
- */
- /*
- * CS350 Students Note!
- *
- * You may not modify the code in this file in any way!
- *
- */
- /*
- *
- * Includes
- *
- */
- #include <types.h>
- #include <lib.h>
- #include <test.h>
- #include <clock.h>
- #include <thread.h>
- #include <synch.h>
- #include <synchprobs.h>
- /* An animal number that won't ever be used */
- #define INVALID_ANIMAL_NUM (999999)
- /* Useful for debugging */
- static int do_print_state = 0;
- /* functions defined and used internally */
- static void initialize_bowls(void);
- static void cleanup_bowls(void);
- static void cat_eat(unsigned int bowlnumber, int eat_time, unsigned int cat_num);
- static void cat_sleep(int sleep_time);
- static void mouse_eat(unsigned int bowlnumber, int eat_time, unsigned int mouse_num);
- static void mouse_sleep(int sleep_time);
- static void cat_simulation(void *ptr, unsigned long catnumber);
- static void mouse_simulation(void *ptr, unsigned long mousenumber);
- static void print_state(void);
- /*
- *
- * Problem parameters
- *
- * Values for these parameters are set by the main driver
- * function, catmouse(), based on the problem parameters
- * that are passed in from the kernel menu command or
- * kernel command line.
- * changing them.
- *
- * These are only ever modified by one thread, at creation time,
- * so they do not need to be volatile.
- */
- static int NumBowls; // number of food bowls
- static int NumCats; // number of cats
- static int NumMice; // number of mice
- static int NumLoops; // number of times each cat and mouse should eat
- static int CatEatTime = 1; // length of time a cat spends eating
- static int CatSleepTime = 2; // length of time a cat spends sleeping
- static int MouseEatTime = 1; // length of time a mouse spends eating
- static int MouseSleepTime = 2; // length of time a mouse spends sleeping
- /*
- * Once the main driver function (catmouse()) has created the cat and mouse
- * simulation threads, it uses this semaphore to block until all of the
- * cat and mouse simulations are finished.
- */
- static struct semaphore *CatMouseWait;
- /*
- *
- * shared simulation state
- *
- * note: this is state should be used only by the
- * functions in this file, hence the static declarations
- *
- */
- /* An array with of structs with one entry for each bowl
- * bowl[i-1].animal = 'c' if a cat is eating at the ith bowl
- * bowl[i-1].animal = 'm' if a mouse is eating at the ith bowl
- * bowl[i-1].animal = '-' otherwise
- *
- * If
- * bowl[i-1].animal = 'c'
- * bowl[i-1].which = 1 means that cat 1 is eating at bowl[i-1]
- * If
- * bowl[i-1].animal = '-'
- * bowl[i-1].which = INVALID_ANIMAL_NUM
- */
- /* The elements within the structure can be changed by multiple
- * threads so the contents are volatile.
- */
- struct bowl {
- volatile char animal; /* 'c' for cat, 'm' for mouse */
- volatile unsigned int which; /* Which cat or mouse */
- };
- struct bowl *bowls;
- /* how many cats are currently eating?
- * modified by multiple threads, so volatile
- */
- static volatile int eating_cats_count;
- /* how many mice are currently eating?
- * modified by different threads, so volatile
- */
- static volatile int eating_mice_count;
- /* semaphore used to provide mutual exclusion
- * for reading and writing the shared simulation state
- * The actual mutex is created/initizliaed by one thread and not
- * modified by others: not volatile
- */
- static struct semaphore *mutex;
- /* performance statistics */
- static volatile time_t cat_total_wait_secs;
- static volatile uint32_t cat_total_wait_nsecs;
- static volatile int cat_wait_count;
- static volatile time_t mouse_total_wait_secs;
- static volatile uint32_t mouse_total_wait_nsecs;
- static volatile int mouse_wait_count;
- /* mutex to provide mutual exclusion to performance stats */
- static struct semaphore *perf_mutex;
- /*
- * initialize_bowls()
- *
- * Purpose:
- * initializes simulation of cats and mice and bowls
- *
- * Arguments:
- * unsigned int bowlcount: the number of food bowls to simulate
- *
- * Returns:
- * 0 on success, 1 otherwise
- */
- static void
- initialize_bowls()
- {
- int i;
- KASSERT(NumBowls > 0);
- bowls = kmalloc(NumBowls*sizeof(struct bowl));
- if (bowls == NULL) {
- panic("initialize_bowls: unable to allocate space for %d bowls\n",NumBowls);
- }
- /* initialize bowls */
- for(i=0;i<NumBowls;i++) {
- bowls[i].animal = '-';
- bowls[i].which = INVALID_ANIMAL_NUM;
- }
- eating_cats_count = eating_mice_count = 0;
- /* intialize mutex semaphore */
- mutex = sem_create("bowl mutex",1);
- if (mutex == NULL) {
- panic("initialize_bowls: could not create mutex\n");
- }
- /* intialize perf_mutex semaphore */
- perf_mutex = sem_create("stats mutex",1);
- if (perf_mutex == NULL) {
- panic("initialize_bowls: could not create perf_mutex\n");
- }
- cat_total_wait_secs = 0;
- cat_total_wait_nsecs = 0;
- cat_wait_count = 0;
- mouse_total_wait_secs = 0;
- mouse_total_wait_nsecs = 0;
- mouse_wait_count = 0;
-
- return;
- }
- /*
- * cleanup_bowls()
- *
- * Purpose:
- * Releases resources created by initialize_bowls.
- *
- * Arguments:
- * None
- *
- * Returns:
- * Nothing
- */
- static void
- cleanup_bowls()
- {
- if (mutex != NULL) {
- sem_destroy( mutex );
- mutex = NULL;
- }
- if (perf_mutex != NULL) {
- sem_destroy( perf_mutex );
- perf_mutex = NULL;
- }
- if (bowls != NULL) {
- kfree( (void *) bowls );
- bowls = NULL;
- }
- }
- /*
- * print_state_on/off()
- *
- * Purpose:
- * Turn the printing of the simulation state on/off.
- *
- * Arguments:
- * none
- *
- * Returns:
- * nothing
- */
- void
- print_state_on()
- {
- do_print_state = 1;
- }
- void
- print_state_off()
- {
- do_print_state = 0;
- }
- /*
- * print_state()
- *
- * Purpose:
- * displays the simulation state
- *
- * Arguments:
- * none
- *
- * Returns:
- * nothing
- *
- * Notes:
- * this assumes that it is being called from within
- * a critical section - it does not provide its own
- * mutual exclusion
- */
- static void
- print_state()
- {
- int i;
- if (NumCats > 100 || NumMice > 100) {
- panic("Formatting is set up to only handle two digit numbers for cat and mice numbers\n");
- }
- if (!do_print_state) {
- return;
- }
- kprintf(" Eating Cats: %3d Eating Mice: %3d ",eating_cats_count,
- eating_mice_count);
- for(i=0;i<NumBowls;i++) {
- kprintf("%c",bowls[i].animal);
- if (bowls[i].which == INVALID_ANIMAL_NUM) {
- kprintf("%2s", "--");
- } else {
- kprintf("%02d",bowls[i].which);
- }
- kprintf(" ");
- }
- kprintf("\n");
- return;
- }
- /*
- * cat_eat()
- *
- * Purpose:
- * simulates a cat eating from a bowl, and checks to
- * make sure that none of the simulation requirements
- * have been violated.
- *
- * Arguments:
- * unsigned int bowlnumber: which bowl the cat should eat from
- * int eat_time: how long to eat
- * unsigned int cat_num: which cat is eating (used for debugging)
- *
- * Returns:
- * nothing
- *
- */
- void
- cat_eat(unsigned int bowlnumber, int eat_time, unsigned int cat_num)
- {
- /* check the bowl number */
- KASSERT(bowlnumber > 0);
- KASSERT((int)bowlnumber <= NumBowls);
- /* check and update the simulation state to indicate that
- * the cat is now eating at the specified bowl */
- P(mutex);
- /* first check whether allowing this cat to eat will
- * violate any simulation requirements */
- if (bowls[bowlnumber-1].animal == 'c') {
- /* there is already a cat eating at the specified bowl */
- panic("cat_eat: attempt to make cat %d eat from bowl %d while cat %d is already eating there!\n",
- cat_num, bowlnumber, bowls[bowlnumber-1].which);
- }
- if (eating_mice_count > 0) {
- /* there is already a mouse eating at some bowl */
- panic("cat_eat: attempt to make cat %d eat while mice are eating!\n", cat_num);
- }
- KASSERT(bowls[bowlnumber-1].animal == '-');
- KASSERT(bowls[bowlnumber-1].which == INVALID_ANIMAL_NUM);
- KASSERT(eating_mice_count == 0);
- /* now update the state to indicate that the cat is eating */
- eating_cats_count += 1;
- bowls[bowlnumber-1].animal = 'c';
- bowls[bowlnumber-1].which = cat_num;
- print_state();
- DEBUG(DB_SYNCPROB,"cat %d starts to eat at bowl %d [%d:%d]\n",
- cat_num, bowlnumber, eating_cats_count, eating_mice_count);
- V(mutex); // end critical section
- /* simulate eating by introducing a delay
- * note that eating is not part of the critical section */
- clocksleep(eat_time);
- /* update the simulation state to indicate that
- * the cat is finished eating */
- P(mutex); // start critical section
- KASSERT(eating_cats_count > 0);
- KASSERT(bowls[bowlnumber-1].animal=='c');
- eating_cats_count -= 1;
- bowls[bowlnumber-1].animal='-';
- bowls[bowlnumber-1].which=INVALID_ANIMAL_NUM;
- print_state();
- DEBUG(DB_SYNCPROB,"cat %d finished eating at bowl %d [%d:%d]\n",
- cat_num,bowlnumber,eating_cats_count,eating_mice_count);
- V(mutex); // end critical section
- return;
- }
- /*
- * cat_sleep()
- *
- * Purpose:
- * simulates a cat sleeping
- *
- * Arguments: none
- *
- * Returns: nothing
- *
- */
- void
- cat_sleep(int sleep_time)
- {
- /* simulate sleeping by introducing a delay */
- clocksleep(sleep_time);
- return;
- }
- /*
- * mouse_eat()
- *
- * Purpose:
- * simulates a mouse eating from a bowl, and checks to
- * make sure that none of the simulation requirements
- * have been violated.
- *
- * Arguments:
- * unsigned int bowlnumber: which bowl the mouse should eat from
- * int eat_time: how long to eat for
- * unsigned int mouse_num: which mouse is eating (for debugging)
- *
- * Returns:
- * nothing
- *
- */
- void
- mouse_eat(unsigned int bowlnumber, int eat_time, unsigned int mouse_num)
- {
- /* check the bowl number */
- KASSERT(bowlnumber > 0);
- KASSERT((int)bowlnumber <= NumBowls);
- /* check and updated the simulation state to indicate that
- * the mouse is now eating at the specified bowl. */
- P(mutex); // start critical section
- /* first check whether allowing this mouse to eat will
- * violate any simulation requirements */
- if (bowls[bowlnumber-1].animal == 'm') {
- /* there is already a mouse eating at the specified bowl */
- panic("mouse_eat: attempt to make mouse %d eat from bowl %d while mouse %d is there!\n",
- mouse_num, bowlnumber, bowls[bowlnumber-1].which);
- }
- if (eating_cats_count > 0) {
- /* there is already a cat eating at some bowl */
- panic("mouse_eat: attempt to make mouse %d eat while cats are eating!\n", mouse_num);
- }
- KASSERT(bowls[bowlnumber-1].animal=='-');
- KASSERT(bowls[bowlnumber-1].which==INVALID_ANIMAL_NUM);
- KASSERT(eating_cats_count == 0);
- /* now update the state to indicate that the mouse is eating */
- eating_mice_count += 1;
- bowls[bowlnumber-1].animal = 'm';
- bowls[bowlnumber-1].which = mouse_num;
- print_state();
- DEBUG(DB_SYNCPROB,"mouse %d starts to eat at bowl %d [%d:%d]\n",
- mouse_num,bowlnumber,eating_cats_count,eating_mice_count);
- V(mutex); // end critical section
- /* simulate eating by introducing a delay
- * note that eating is not part of the critical section */
- clocksleep(eat_time);
- /* update the simulation state to indicate that
- * the mouse is finished eating */
- P(mutex); // start critical section
- KASSERT(eating_mice_count > 0);
- eating_mice_count -= 1;
- KASSERT(bowls[bowlnumber-1].animal=='m');
- KASSERT(bowls[bowlnumber-1].which==mouse_num);
- bowls[bowlnumber-1].animal='-';
- bowls[bowlnumber-1].which=INVALID_ANIMAL_NUM;
- print_state();
- DEBUG(DB_SYNCPROB,"mouse %d finishes eating at bowl %d [%d:%d]\n",
- mouse_num,bowlnumber,eating_cats_count,eating_mice_count);
- V(mutex); // end critical section
- return;
- }
- /*
- * mouse_sleep()
- *
- * Purpose:
- * simulates a mouse sleeping
- *
- * Arguments: none
- *
- * Returns: nothing
- *
- */
- void
- mouse_sleep(int sleep_time)
- {
- /* simulate sleeping by introducing a delay */
- clocksleep(sleep_time);
- return;
- }
- /*
- * cat_simulation()
- *
- * Arguments:
- * void * unusedpointer: currently unused.
- * unsigned long catnumber: holds cat identifier from 0 to NumCats-1.
- *
- * Returns:
- * nothing.
- *
- * Notes:
- * Each cat simulation thread runs this function.
- *
- */
- static
- void
- cat_simulation(void * unusedpointer,
- unsigned long catnumber)
- {
- int i;
- unsigned int bowl;
- time_t before_sec, after_sec, wait_sec;
- uint32_t before_nsec, after_nsec, wait_nsec;
- /* avoid unused variable warnings. */
- (void) unusedpointer;
- (void) catnumber;
- for(i=0;i<NumLoops;i++) {
- /* make the cat sleep */
- cat_sleep(CatSleepTime);
- /* choose bowl. legal bowl numbers range from 1 to NumBowls */
- bowl = ((unsigned int)random() % NumBowls) + 1;
- gettime(&before_sec,&before_nsec);
- cat_before_eating(bowl); /* student-implemented function */
- gettime(&after_sec,&after_nsec);
- /* make the cat eat */
- cat_eat(bowl, CatEatTime, catnumber);
- cat_after_eating(bowl); /* student-implemented function */
- /* update wait time statistics */
- getinterval(before_sec,before_nsec,after_sec,after_nsec,&wait_sec,&wait_nsec);
- P(perf_mutex);
- cat_total_wait_secs += wait_sec;
- cat_total_wait_nsecs += wait_nsec;
- if (cat_total_wait_nsecs > 1000000000) {
- cat_total_wait_nsecs -= 1000000000;
- cat_total_wait_secs ++;
- }
- cat_wait_count++;
- V(perf_mutex);
- }
- /* indicate that this cat simulation is finished */
- V(CatMouseWait);
- }
- /*
- * mouse_simulation()
- *
- * Arguments:
- * void * unusedpointer: currently unused.
- * unsigned long mousenumber: holds mouse identifier from 0 to NumMice-1.
- *
- * Returns:
- * nothing.
- *
- * Notes:
- * each mouse simulation thread runs this function
- *
- */
- static
- void
- mouse_simulation(void * unusedpointer,
- unsigned long mousenumber)
- {
- int i;
- unsigned int bowl;
- time_t before_sec, after_sec, wait_sec;
- uint32_t before_nsec, after_nsec, wait_nsec;
- /* Avoid unused variable warnings. */
- (void) unusedpointer;
- (void) mousenumber;
- for(i=0;i<NumLoops;i++) {
- /* make the mouse sleep */
- mouse_sleep(MouseSleepTime);
- /* choose bowl. legal bowl numbers range from 1 to NumBowls */
- bowl = ((unsigned int)random() % NumBowls) + 1;
- gettime(&before_sec,&before_nsec);
- mouse_before_eating(bowl); /* student-implemented function */
- gettime(&after_sec,&after_nsec);
- /* make the mouse eat */
- mouse_eat(bowl, MouseEatTime, mousenumber);
- mouse_after_eating(bowl); /* student-implemented function */
- /* update wait time statistics */
- getinterval(before_sec,before_nsec,after_sec,after_nsec,&wait_sec,&wait_nsec);
- P(perf_mutex);
- mouse_total_wait_secs += wait_sec;
- mouse_total_wait_nsecs += wait_nsec;
- if (mouse_total_wait_nsecs > 1000000000) {
- mouse_total_wait_nsecs -= 1000000000;
- mouse_total_wait_secs ++;
- }
- mouse_wait_count++;
- V(perf_mutex);
- }
- /* indicate that this mouse is finished */
- V(CatMouseWait);
- }
- /*
- * catmouse()
- *
- * Arguments:
- * int nargs: should be 5 or 9
- * char ** args: args[1] = number of food bowls
- * args[2] = number of cats
- * args[3] = number of mice
- * args[4] = number of loops
- * Optional parameters
- * args[5] = cat eating time
- * args[6] = cat sleeping time
- * args[7] = mouse eating time
- * args[8] = mouse sleeping time
- *
- * Returns:
- * 0 on success.
- *
- * Notes:
- * Driver code to start up cat_simulation() and
- * mouse_simulation() threads.
- */
- int
- catmouse(int nargs,
- char ** args)
- {
- int catindex, mouseindex, error;
- int i;
- int mean_cat_wait_usecs, mean_mouse_wait_usecs;
- time_t before_sec, after_sec, wait_sec;
- uint32_t before_nsec, after_nsec, wait_nsec;
- int total_bowl_milliseconds, total_eating_milliseconds, utilization_percent;
- /* check and process command line arguments */
- if ((nargs != 9) && (nargs != 5)) {
- kprintf("Usage: <command> NUM_BOWLS NUM_CATS NUM_MICE NUM_LOOPS\n");
- kprintf("or\n");
- kprintf("Usage: <command> NUM_BOWLS NUM_CATS NUM_MICE NUM_LOOPS ");
- kprintf("CAT_EATING_TIME CAT_SLEEPING_TIME MOUSE_EATING_TIME MOUSE_SLEEPING_TIME\n");
- return 1; // return failure indication
- }
- /* check the problem parameters, and set the global variables */
- NumBowls = atoi(args[1]);
- if (NumBowls <= 0) {
- kprintf("catmouse: invalid number of bowls: %d\n",NumBowls);
- return 1;
- }
- NumCats = atoi(args[2]);
- if (NumCats < 0) {
- kprintf("catmouse: invalid number of cats: %d\n",NumCats);
- return 1;
- }
- NumMice = atoi(args[3]);
- if (NumMice < 0) {
- kprintf("catmouse: invalid number of mice: %d\n",NumMice);
- return 1;
- }
- NumLoops = atoi(args[4]);
- if (NumLoops <= 0) {
- kprintf("catmouse: invalid number of loops: %d\n",NumLoops);
- return 1;
- }
- if (nargs == 9) {
- CatEatTime = atoi(args[5]);
- if (CatEatTime < 0) {
- kprintf("catmouse: invalid cat eating time: %d\n",CatEatTime);
- return 1;
- }
-
- CatSleepTime = atoi(args[6]);
- if (CatSleepTime < 0) {
- kprintf("catmouse: invalid cat sleeping time: %d\n",CatSleepTime);
- return 1;
- }
-
- MouseEatTime = atoi(args[7]);
- if (MouseEatTime < 0) {
- kprintf("catmouse: invalid mouse eating time: %d\n",MouseEatTime);
- return 1;
- }
-
- MouseSleepTime = atoi(args[8]);
- if (MouseSleepTime < 0) {
- kprintf("catmouse: invalid mouse sleeping time: %d\n",MouseSleepTime);
- return 1;
- }
- }
- if ((NumMice >= INVALID_ANIMAL_NUM) || (NumCats >= INVALID_ANIMAL_NUM)) {
- panic("Trying to use too many cats or mice: limit = %d\n", INVALID_ANIMAL_NUM);
- }
- kprintf("Using %d bowls, %d cats, and %d mice. Looping %d times.\n",
- NumBowls,NumCats,NumMice,NumLoops);
- kprintf("Using cat eating time %d, cat sleeping time %d\n", CatEatTime, CatSleepTime);
- kprintf("Using mouse eating time %d, mouse sleeping time %d\n", MouseEatTime, MouseSleepTime);
- /* create the semaphore that is used to make the main thread
- wait for all of the cats and mice to finish */
- CatMouseWait = sem_create("CatMouseWait",0);
- if (CatMouseWait == NULL) {
- panic("catmouse: could not create semaphore\n");
- }
- /* initialize our simulation state */
- initialize_bowls();
- /* initialize the synchronization functions */
- catmouse_sync_init(NumBowls);
- /* get current time, for measuring total simulation time */
- gettime(&before_sec,&before_nsec);
- /*
- * Start NumCats cat_simulation() threads and NumMice mouse_simulation() threads.
- * Alternate cat and mouse creation.
- */
- for (catindex = 0; catindex < NumCats; catindex++) {
- error = thread_fork("cat_simulation thread", NULL, cat_simulation, NULL, catindex);
- if (error) {
- panic("cat_simulation: thread_fork failed: %s\n", strerror(error));
- }
- if (catindex < NumMice) {
- error = thread_fork("mouse_simulation thread", NULL, mouse_simulation, NULL, catindex);
- if (error) {
- panic("mouse_simulation: thread_fork failed: %s\n",strerror(error));
- }
- }
- }
- /* launch any remaining mice */
- for(mouseindex = catindex; mouseindex < NumMice; mouseindex++) {
- error = thread_fork("mouse_simulation thread", NULL, mouse_simulation, NULL, mouseindex);
- if (error) {
- panic("mouse_simulation: thread_fork failed: %s\n",strerror(error));
- }
- }
-
- /* wait for all of the cats and mice to finish before
- terminating */
- for(i=0;i<(NumCats+NumMice);i++) {
- P(CatMouseWait);
- }
- /* get current time, for measuring total simulation time */
- gettime(&after_sec,&after_nsec);
- /* compute total simulation time */
- getinterval(before_sec,before_nsec,after_sec,after_nsec,&wait_sec,&wait_nsec);
- /* compute and report bowl utilization */
- total_bowl_milliseconds = (wait_sec*1000 + wait_nsec/1000000)*NumBowls;
- total_eating_milliseconds = (NumCats*CatEatTime + NumMice*MouseEatTime)*NumLoops*1000;
- if (total_bowl_milliseconds > 0) {
- utilization_percent = total_eating_milliseconds*100/total_bowl_milliseconds;
- kprintf("STATS: Bowl utilization: %d%%\n",utilization_percent);
- }
- /* clean up the semaphore that we created */
- sem_destroy(CatMouseWait);
- /* clean up the synchronization state */
- catmouse_sync_cleanup(NumBowls);
- /* clean up resources used for tracking bowl use */
- cleanup_bowls();
- if (cat_wait_count > 0) {
- /* some rounding error here - not significant if cat_wait_count << 1000000 */
- mean_cat_wait_usecs = (cat_total_wait_secs*1000000+cat_total_wait_nsecs/1000)/cat_wait_count;
- kprintf("STATS: Mean cat waiting time: %d.%d seconds\n",
- mean_cat_wait_usecs/1000000,mean_cat_wait_usecs%1000000);
- }
- if (mouse_wait_count > 0) {
- /* some rounding error here - not significant if mouse_wait_count << 1000000 */
- mean_mouse_wait_usecs = (mouse_total_wait_secs*1000000+mouse_total_wait_nsecs/1000)/mouse_wait_count;
- kprintf("STATS: Mean mouse waiting time: %d.%d seconds\n",
- mean_mouse_wait_usecs/1000000,mean_mouse_wait_usecs%1000000);
- }
- return 0;
- }
- /*
- * End of catmouse.c
- */
|