os161-1.99
 All Data Structures
catmouse.c
00001 /*
00002  * catmouse.c
00003  *
00004  * 30-1-2003 : GWA : Stub functions created for CS161 Asst1.
00005  * 26-11-2007: KMS : Modified to use cat_eat and mouse_eat
00006  * 21-04-2009: KMS : modified to use cat_sleep and mouse_sleep
00007  * 21-04-2009: KMS : added sem_destroy of CatMouseWait
00008  * 05-01-2012: TBB : added comments to try to clarify use/non use of volatile
00009  * 22-08-2013: TBB: made cat and mouse eating and sleeping time optional parameters
00010  * 27-04-2014: KMS: change this to simulation driver that invokes student-implemented synch functions
00011  *
00012  */
00013 
00014 
00015 /*
00016  *  CS350 Students Note!
00017  *
00018  *  You may not modify the code in this file in any way!
00019  *
00020  */
00021 
00022 
00023 /*
00024  * 
00025  * Includes
00026  *
00027  */
00028 
00029 #include <types.h>
00030 #include <lib.h>
00031 #include <test.h>
00032 #include <clock.h>
00033 #include <thread.h>
00034 #include <synch.h>
00035 #include <synchprobs.h>
00036 
00037 /* functions defined and used internally */
00038 static void initialize_bowls(void);
00039 static void cleanup_bowls(void);
00040 static void cat_eat(unsigned int bowlnumber, int eat_time);
00041 static void cat_sleep(int sleep_time);
00042 static void mouse_eat(unsigned int bowlnumber, int eat_time);
00043 static void mouse_sleep(int sleep_time);
00044 static void cat_simulation(void *ptr, unsigned long catnumber);
00045 static void mouse_simulation(void *ptr, unsigned long mousenumber);
00046 /* static void print_state(void); */
00047 
00048 /*
00049  *
00050  * Problem parameters
00051  *
00052  * Values for these parameters are set by the main driver
00053  *  function, catmouse(), based on the problem parameters
00054  *  that are passed in from the kernel menu command or
00055  *  kernel command line.
00056  *  changing them.
00057  *
00058  * These are only ever modified by one thread, at creation time,
00059  * so they do not need to be volatile.
00060  */
00061 static int NumBowls;  // number of food bowls
00062 static int NumCats;   // number of cats
00063 static int NumMice;   // number of mice
00064 static int NumLoops;  // number of times each cat and mouse should eat
00065 
00066 static int CatEatTime = 1;      // length of time a cat spends eating
00067 static int CatSleepTime = 2;    // length of time a cat spends sleeping
00068 static int MouseEatTime = 1;    // length of time a mouse spends eating
00069 static int MouseSleepTime = 2;  // length of time a mouse spends sleeping
00070 
00071 /*
00072  * Once the main driver function (catmouse()) has created the cat and mouse
00073  * simulation threads, it uses this semaphore to block until all of the
00074  * cat and mouse simulations are finished.
00075  */
00076 static struct semaphore *CatMouseWait;
00077 
00078 /*
00079  *
00080  * shared simulation state
00081  * 
00082  * note: this is state should be used only by the 
00083  *  functions in this file, hence the static declarations
00084  *
00085  */
00086 
00087 /* a character array with one entry for each bowl
00088  *  bowl[i-1] = 'c' if a cat is eating at the ith bowl
00089  *  bowl[i-1] = 'm' if a mouse is eating at the ith bowl
00090  *  bowl[i-1] = '-' otherwise */
00091 
00092 /* The elements within the array can be changed by multiple 
00093  * threads so the contents are volatile.
00094  */
00095 static volatile char *bowls;
00096 
00097 /* how many cats are currently eating? 
00098  * modified by multiple threads, so volatile 
00099  */
00100 static volatile int eating_cats_count;
00101 
00102 /* how many mice are currently eating? 
00103  * modified by different threads, so volatile 
00104  */
00105 static volatile int eating_mice_count;
00106 
00107 /* semaphore used to provide mutual exclusion
00108  * for reading and writing the shared simulation state 
00109  * The actual mutex is created/initizliaed by one thread and not 
00110  * modified by others: not volatile 
00111  */
00112 static struct semaphore *mutex;
00113 
00114 /* performance statistics */
00115 static volatile time_t cat_total_wait_secs;
00116 static volatile uint32_t cat_total_wait_nsecs;
00117 static volatile int cat_wait_count;
00118 static volatile time_t mouse_total_wait_secs;
00119 static volatile uint32_t mouse_total_wait_nsecs;
00120 static volatile int mouse_wait_count;
00121 
00122 /* mutex to provide mutual exclusion to performance stats */
00123 static struct semaphore *perf_mutex;
00124 
00125 
00126 /*
00127  * initialize_bowls()
00128  * 
00129  * Purpose:
00130  *   initializes simulation of cats and mice and bowls
00131  *
00132  * Arguments:
00133  *   unsigned int bowlcount:  the number of food bowls to simulate
00134  *
00135  * Returns:
00136  *   0 on success, 1 otherwise
00137  */
00138 
00139 static void
00140 initialize_bowls()
00141 {
00142   int i;
00143 
00144   KASSERT(NumBowls > 0);
00145 
00146   bowls = kmalloc(NumBowls*sizeof(char));
00147   if (bowls == NULL) {
00148     panic("initialize_bowls: unable to allocate space for %d bowls\n",NumBowls);
00149   }
00150   /* initialize bowls */
00151   for(i=0;i<NumBowls;i++) {
00152     bowls[i] = '-';
00153   }
00154   eating_cats_count = eating_mice_count = 0;
00155 
00156   /* intialize mutex semaphore */
00157   mutex = sem_create("bowl mutex",1);
00158   if (mutex == NULL) {
00159     panic("initialize_bowls: could not create mutex\n");
00160   }
00161   /* intialize perf_mutex semaphore */
00162   perf_mutex = sem_create("stats mutex",1);
00163   if (perf_mutex == NULL) {
00164     panic("initialize_bowls: could not create perf_mutex\n");
00165   }
00166 
00167   cat_total_wait_secs = 0;
00168   cat_total_wait_nsecs = 0;
00169   cat_wait_count = 0;
00170   mouse_total_wait_secs = 0;
00171   mouse_total_wait_nsecs = 0;
00172   mouse_wait_count = 0;
00173   
00174   return;
00175 }
00176 
00177 
00178 /*
00179  * cleanup_bowls()
00180  * 
00181  * Purpose:
00182  *   Releases resources created by initialize_bowls.
00183  *
00184  * Arguments:
00185  *   None
00186  *
00187  * Returns:
00188  *   Nothing
00189  */
00190 
00191 static void
00192 cleanup_bowls()
00193 {
00194   if (mutex != NULL) {
00195     sem_destroy( mutex );
00196     mutex = NULL;
00197   }
00198   if (perf_mutex != NULL) {
00199     sem_destroy( perf_mutex );
00200     perf_mutex = NULL;
00201   }
00202   if (bowls != NULL) {
00203     kfree( (void *) bowls );
00204     bowls = NULL;
00205   }
00206 }
00207 
00208 /*
00209  * print_state()
00210  * 
00211  * Purpose:
00212  *   displays the simulation state
00213  *
00214  * Arguments:
00215  *   none
00216  *
00217  * Returns:
00218  *   nothing
00219  *
00220  * Notes:
00221  *   this assumes that it is being called from within
00222  *   a critical section - it does not provide its own
00223  *   mutual exclusion
00224  */
00225 
00226 /*   not currently used */
00227 /*
00228 static void
00229 print_state()
00230 {
00231   int i;
00232 
00233   kprintf(" Eating Cats: %3d  Eating Mice: %3d   ",eating_cats_count,
00234     eating_mice_count);
00235   for(i=0;i<NumBowls;i++) {
00236     kprintf("%c",bowls[i]);
00237   }
00238   return;
00239 }
00240 */
00241 
00242 
00243 /*
00244  * cat_eat()
00245  *
00246  * Purpose:
00247  *   simulates a cat eating from a bowl, and checks to
00248  *   make sure that none of the simulation requirements
00249  *   have been violated.
00250  *
00251  * Arguments:
00252  *   unsigned int bowlnumber: which bowl the cat should eat from
00253  *
00254  * Returns:
00255  *   nothing
00256  *
00257  */
00258 
00259 void
00260 cat_eat(unsigned int bowlnumber, int eat_time)
00261 {
00262 
00263   /* check the bowl number */
00264   KASSERT(bowlnumber > 0);
00265   KASSERT((int)bowlnumber <= NumBowls);
00266 
00267   /* check and update the simulation state to indicate that
00268    * the cat is now eating at the specified bowl */
00269   P(mutex);
00270 
00271   /* first check whether allowing this cat to eat will
00272    * violate any simulation requirements */
00273   if (bowls[bowlnumber-1] == 'c') {
00274     /* there is already a cat eating at the specified bowl */
00275     panic("cat_eat: attempt to make two cats eat from bowl %d!\n",bowlnumber);
00276   }
00277   if (eating_mice_count > 0) {
00278     /* there is already a mouse eating at some bowl */
00279     panic("cat_eat: attempt to make a cat eat while mice are eating!\n");
00280   }
00281   KASSERT(bowls[bowlnumber-1]=='-');
00282   KASSERT(eating_mice_count == 0);
00283 
00284   /* now update the state to indicate that the cat is eating */
00285   eating_cats_count += 1;
00286   bowls[bowlnumber-1] = 'c';
00287 
00288   DEBUG(DB_SYNCPROB,"cat starts to eat at bowl %d [%d:%d]\n",
00289         bowlnumber,eating_cats_count,eating_mice_count);
00290   V(mutex);  // end critical section
00291 
00292   /* simulate eating by introducing a delay
00293    * note that eating is not part of the critical section */
00294   clocksleep(eat_time);
00295 
00296   /* update the simulation state to indicate that
00297    * the cat is finished eating */
00298   P(mutex);  // start critical section
00299   KASSERT(eating_cats_count > 0);
00300   KASSERT(bowls[bowlnumber-1]=='c');
00301   eating_cats_count -= 1;
00302   bowls[bowlnumber-1]='-';
00303 
00304   DEBUG(DB_SYNCPROB,"cat finished eating at bowl %d [%d:%d]\n",
00305         bowlnumber,eating_cats_count,eating_mice_count);
00306   V(mutex);  // end critical section
00307 
00308   return;
00309 }
00310 
00311 /*
00312  * cat_sleep()
00313  *
00314  * Purpose:
00315  *   simulates a cat sleeping
00316  *
00317  * Arguments: none
00318  *
00319  * Returns: nothing
00320  *
00321  */
00322 void
00323 cat_sleep(int sleep_time)
00324 {
00325   /* simulate sleeping by introducing a delay */
00326   clocksleep(sleep_time);
00327   return;
00328 }
00329 
00330 
00331 /*
00332  * mouse_eat()
00333  *
00334  * Purpose:
00335  *   simulates a mouse eating from a bowl, and checks to
00336  *   make sure that none of the simulation requirements
00337  *   have been violated.
00338  *
00339  * Arguments:
00340  *   unsigned int bowlnumber: which bowl the mouse should eat from
00341  *
00342  * Returns:
00343  *   nothing
00344  *
00345  */
00346 
00347 void
00348 mouse_eat(unsigned int bowlnumber, int eat_time)
00349 {
00350   /* check the bowl number */
00351   KASSERT(bowlnumber > 0);
00352   KASSERT((int)bowlnumber <= NumBowls);
00353 
00354   /* check and updated the simulation state to indicate that
00355    * the mouse is now eating at the specified bowl. */
00356   P(mutex);  // start critical section
00357 
00358   /* first check whether allowing this mouse to eat will
00359    * violate any simulation requirements */
00360   if (bowls[bowlnumber-1] == 'm') {
00361     /* there is already a mouse eating at the specified bowl */
00362     panic("mouse_eat: attempt to make two mice eat from bowl %d!\n",bowlnumber);
00363   }
00364   if (eating_cats_count > 0) {
00365     /* there is already a cat eating at some bowl */
00366     panic("mouse_eat: attempt to make a mouse eat while cats are eating!\n");
00367   }
00368   KASSERT(bowls[bowlnumber-1]=='-');
00369   KASSERT(eating_cats_count == 0);
00370 
00371   /* now update the state to indicate that the mouse is eating */
00372   eating_mice_count += 1;
00373   bowls[bowlnumber-1] = 'm';
00374 
00375   DEBUG(DB_SYNCPROB,"mouse starts to eat at bowl %d [%d:%d]\n",
00376         bowlnumber,eating_cats_count,eating_mice_count);
00377   V(mutex);  // end critical section
00378 
00379   /* simulate eating by introducing a delay
00380    * note that eating is not part of the critical section */
00381   clocksleep(eat_time);
00382 
00383   /* update the simulation state to indicate that
00384    * the mouse is finished eating */
00385   P(mutex); // start critical section
00386 
00387   KASSERT(eating_mice_count > 0);
00388   eating_mice_count -= 1;
00389   KASSERT(bowls[bowlnumber-1]=='m');
00390   bowls[bowlnumber-1]='-';
00391 
00392   DEBUG(DB_SYNCPROB,"mouse finishes eating at bowl %d [%d:%d]\n",
00393         bowlnumber,eating_cats_count,eating_mice_count);
00394   V(mutex);  // end critical section
00395   return;
00396 }
00397 
00398 /*
00399  * mouse_sleep()
00400  *
00401  * Purpose:
00402  *   simulates a mouse sleeping
00403  *
00404  * Arguments: none
00405  *
00406  * Returns: nothing
00407  *
00408  */
00409 void
00410 mouse_sleep(int sleep_time)
00411 {
00412   /* simulate sleeping by introducing a delay */
00413   clocksleep(sleep_time);
00414   return;
00415 }
00416 
00417 /*
00418  * cat_simulation()
00419  *
00420  * Arguments:
00421  *      void * unusedpointer: currently unused.
00422  *      unsigned long catnumber: holds cat identifier from 0 to NumCats-1.
00423  *
00424  * Returns:
00425  *      nothing.
00426  *
00427  * Notes:
00428  *      Each cat simulation thread runs this function.
00429  *
00430  */
00431 
00432 static
00433 void
00434 cat_simulation(void * unusedpointer, 
00435                unsigned long catnumber)
00436 {
00437   int i;
00438   unsigned int bowl;
00439   time_t before_sec, after_sec, wait_sec;
00440   uint32_t before_nsec, after_nsec, wait_nsec;
00441 
00442   /* avoid unused variable warnings. */
00443   (void) unusedpointer;
00444   (void) catnumber;
00445 
00446 
00447   for(i=0;i<NumLoops;i++) {
00448 
00449     /* make the cat sleep */
00450     cat_sleep(CatSleepTime);
00451 
00452     /* choose bowl.  legal bowl numbers range from 1 to NumBowls */
00453     bowl = ((unsigned int)random() % NumBowls) + 1;
00454 
00455     gettime(&before_sec,&before_nsec);
00456     cat_before_eating(bowl); /* student-implemented function */
00457     gettime(&after_sec,&after_nsec);
00458 
00459     /* make the cat eat */
00460     cat_eat(bowl, CatEatTime);
00461 
00462     cat_after_eating(bowl); /* student-implemented function */
00463 
00464     /* update wait time statistics */
00465     getinterval(before_sec,before_nsec,after_sec,after_nsec,&wait_sec,&wait_nsec);
00466     P(perf_mutex);
00467     cat_total_wait_secs += wait_sec;
00468     cat_total_wait_nsecs += wait_nsec;
00469     if (cat_total_wait_nsecs > 1000000000) {
00470       cat_total_wait_nsecs -= 1000000000;
00471       cat_total_wait_secs ++;
00472     }
00473     cat_wait_count++;
00474     V(perf_mutex);
00475   }
00476 
00477   /* indicate that this cat simulation is finished */
00478   V(CatMouseWait); 
00479 }
00480 
00481 /*
00482  * mouse_simulation()
00483  *
00484  * Arguments:
00485  *      void * unusedpointer: currently unused.
00486  *      unsigned long mousenumber: holds mouse identifier from 0 to NumMice-1.
00487  *
00488  * Returns:
00489  *      nothing.
00490  *
00491  * Notes:
00492  *      each mouse simulation thread runs this function
00493  *
00494  */
00495 
00496 static
00497 void
00498 mouse_simulation(void * unusedpointer,
00499           unsigned long mousenumber)
00500 {
00501   int i;
00502   unsigned int bowl;
00503   time_t before_sec, after_sec, wait_sec;
00504   uint32_t before_nsec, after_nsec, wait_nsec;
00505 
00506   /* Avoid unused variable warnings. */
00507   (void) unusedpointer;
00508   (void) mousenumber;
00509 
00510   for(i=0;i<NumLoops;i++) {
00511 
00512     /* make the mouse sleep */
00513     mouse_sleep(MouseSleepTime);
00514 
00515     /* choose bowl.  legal bowl numbers range from 1 to NumBowls */
00516     bowl = ((unsigned int)random() % NumBowls) + 1;
00517 
00518     gettime(&before_sec,&before_nsec);
00519     mouse_before_eating(bowl); /* student-implemented function */
00520     gettime(&after_sec,&after_nsec);
00521 
00522     /* make the mouse eat */
00523     mouse_eat(bowl, MouseEatTime);
00524 
00525     mouse_after_eating(bowl); /* student-implemented function */
00526 
00527     /* update wait time statistics */
00528     getinterval(before_sec,before_nsec,after_sec,after_nsec,&wait_sec,&wait_nsec);
00529     P(perf_mutex);
00530     mouse_total_wait_secs += wait_sec;
00531     mouse_total_wait_nsecs += wait_nsec;
00532     if (mouse_total_wait_nsecs > 1000000000) {
00533       mouse_total_wait_nsecs -= 1000000000;
00534       mouse_total_wait_secs ++;
00535     }
00536     mouse_wait_count++;
00537     V(perf_mutex);
00538   }
00539 
00540   /* indicate that this mouse is finished */
00541   V(CatMouseWait); 
00542 }
00543 
00544 /*
00545  * catmouse()
00546  *
00547  * Arguments:
00548  *      int nargs: should be 5 or 9
00549  *      char ** args: args[1] = number of food bowls
00550  *                    args[2] = number of cats
00551  *                    args[3] = number of mice
00552  *                    args[4] = number of loops
00553  * Optional parameters
00554  *                    args[5] = cat eating time
00555  *                    args[6] = cat sleeping time
00556  *                    args[7] = mouse eating time
00557  *                    args[8] = mouse sleeping time
00558  *
00559  * Returns:
00560  *      0 on success.
00561  *
00562  * Notes:
00563  *      Driver code to start up cat_simulation() and
00564  *      mouse_simulation() threads.
00565  */
00566 
00567 int
00568 catmouse(int nargs,
00569          char ** args)
00570 {
00571   int catindex, mouseindex, error;
00572   int i;
00573   int mean_cat_wait_usecs, mean_mouse_wait_usecs;
00574   time_t before_sec, after_sec, wait_sec;
00575   uint32_t before_nsec, after_nsec, wait_nsec;
00576   int total_bowl_milliseconds, total_eating_milliseconds, utilization_percent;
00577 
00578   /* check and process command line arguments */
00579   if ((nargs != 9) && (nargs != 5)) {
00580     kprintf("Usage: <command> NUM_BOWLS NUM_CATS NUM_MICE NUM_LOOPS\n");
00581     kprintf("or\n");
00582     kprintf("Usage: <command> NUM_BOWLS NUM_CATS NUM_MICE NUM_LOOPS ");
00583     kprintf("CAT_EATING_TIME CAT_SLEEPING_TIME MOUSE_EATING_TIME MOUSE_SLEEPING_TIME\n");
00584     return 1;  // return failure indication
00585   }
00586 
00587   /* check the problem parameters, and set the global variables */
00588   NumBowls = atoi(args[1]);
00589   if (NumBowls <= 0) {
00590     kprintf("catmouse: invalid number of bowls: %d\n",NumBowls);
00591     return 1;
00592   }
00593   NumCats = atoi(args[2]);
00594   if (NumCats < 0) {
00595     kprintf("catmouse: invalid number of cats: %d\n",NumCats);
00596     return 1;
00597   }
00598   NumMice = atoi(args[3]);
00599   if (NumMice < 0) {
00600     kprintf("catmouse: invalid number of mice: %d\n",NumMice);
00601     return 1;
00602   }
00603   NumLoops = atoi(args[4]);
00604   if (NumLoops <= 0) {
00605     kprintf("catmouse: invalid number of loops: %d\n",NumLoops);
00606     return 1;
00607   }
00608 
00609   if (nargs == 9) {
00610     CatEatTime = atoi(args[5]);
00611     if (CatEatTime < 0) {
00612       kprintf("catmouse: invalid cat eating time: %d\n",CatEatTime);
00613       return 1;
00614     }
00615   
00616     CatSleepTime = atoi(args[6]);
00617     if (CatSleepTime < 0) {
00618       kprintf("catmouse: invalid cat sleeping time: %d\n",CatSleepTime);
00619       return 1;
00620     }
00621   
00622     MouseEatTime = atoi(args[7]);
00623     if (MouseEatTime < 0) {
00624       kprintf("catmouse: invalid mouse eating time: %d\n",MouseEatTime);
00625       return 1;
00626     }
00627   
00628     MouseSleepTime = atoi(args[8]);
00629     if (MouseSleepTime < 0) {
00630       kprintf("catmouse: invalid mouse sleeping time: %d\n",MouseSleepTime);
00631       return 1;
00632     }
00633   }
00634 
00635   kprintf("Using %d bowls, %d cats, and %d mice. Looping %d times.\n",
00636           NumBowls,NumCats,NumMice,NumLoops);
00637   kprintf("Using cat eating time %d, cat sleeping time %d\n", CatEatTime, CatSleepTime);
00638   kprintf("Using mouse eating time %d, mouse sleeping time %d\n", MouseEatTime, MouseSleepTime);
00639 
00640   /* create the semaphore that is used to make the main thread
00641      wait for all of the cats and mice to finish */
00642   CatMouseWait = sem_create("CatMouseWait",0);
00643   if (CatMouseWait == NULL) {
00644     panic("catmouse: could not create semaphore\n");
00645   }
00646 
00647   /* initialize our simulation state */
00648   initialize_bowls();
00649 
00650   /* initialize the synchronization functions */
00651   catmouse_sync_init(NumBowls);
00652 
00653   /* get current time, for measuring total simulation time */
00654   gettime(&before_sec,&before_nsec);
00655 
00656   /*
00657    * Start NumCats cat_simulation() threads and NumMice mouse_simulation() threads.
00658    * Alternate cat and mouse creation.
00659    */
00660   for (catindex = 0; catindex < NumCats; catindex++) {
00661     error = thread_fork("cat_simulation thread", NULL, cat_simulation, NULL, catindex);
00662     if (error) {
00663       panic("cat_simulation: thread_fork failed: %s\n", strerror(error));
00664     }
00665     if (catindex < NumMice) {
00666       error = thread_fork("mouse_simulation thread", NULL, mouse_simulation, NULL, catindex);
00667       if (error) {
00668         panic("mouse_simulation: thread_fork failed: %s\n",strerror(error));
00669       }
00670     } 
00671   }
00672   /* launch any remaining mice */
00673   for(mouseindex = catindex; mouseindex < NumMice; mouseindex++) {
00674     error = thread_fork("mouse_simulation thread", NULL, mouse_simulation, NULL, mouseindex);
00675     if (error) {
00676       panic("mouse_simulation: thread_fork failed: %s\n",strerror(error));
00677     }
00678   }
00679   
00680   /* wait for all of the cats and mice to finish before
00681      terminating */  
00682   for(i=0;i<(NumCats+NumMice);i++) {
00683     P(CatMouseWait);
00684   }
00685 
00686   /* get current time, for measuring total simulation time */
00687   gettime(&after_sec,&after_nsec);
00688   /* compute total simulation time */
00689   getinterval(before_sec,before_nsec,after_sec,after_nsec,&wait_sec,&wait_nsec);
00690   /* compute and report bowl utilization */
00691   total_bowl_milliseconds = (wait_sec*1000 + wait_nsec/1000000)*NumBowls;
00692   total_eating_milliseconds = (NumCats*CatEatTime + NumMice*MouseEatTime)*NumLoops*1000;
00693   if (total_bowl_milliseconds > 0) {
00694     utilization_percent = total_eating_milliseconds*100/total_bowl_milliseconds;
00695     kprintf("Bowl utilization: %d%%\n",utilization_percent);
00696   }
00697 
00698   /* clean up the semaphore that we created */
00699   sem_destroy(CatMouseWait);
00700 
00701   /* clean up the synchronization state */
00702   catmouse_sync_cleanup(NumBowls);
00703 
00704   /* clean up resources used for tracking bowl use */
00705   cleanup_bowls();
00706 
00707   if (cat_wait_count > 0) {
00708     /* some rounding error here - not significant if cat_wait_count << 1000000 */
00709     mean_cat_wait_usecs = (cat_total_wait_secs*1000000+cat_total_wait_nsecs/1000)/cat_wait_count;
00710     kprintf("Mean cat waiting time: %d.%d seconds\n",mean_cat_wait_usecs/1000000,mean_cat_wait_usecs%1000000);
00711   }
00712   if (mouse_wait_count > 0) {
00713     /* some rounding error here - not significant if mouse_wait_count << 1000000 */
00714     mean_mouse_wait_usecs = (mouse_total_wait_secs*1000000+mouse_total_wait_nsecs/1000)/mouse_wait_count;
00715     kprintf("Mean mouse waiting time: %d.%d seconds\n",mean_mouse_wait_usecs/1000000,mean_mouse_wait_usecs%1000000);
00716   }
00717 
00718   return 0;
00719 }
00720 
00721 /*
00722  * End of catmouse.c
00723  */
 All Data Structures