/* * Common code for cmd_prog and cmd_shell. * * This function uses the one_thread_only() function to make * the kernel menu thread wait until the newly-launched program * has finished. The one_thread_only() function is a bit ugly * (it works in this specific situation but not more generally) * Once you have A2 working, you should be able to use your * call your waitpid implementation (instead of one_thread_only()) * to provide the necessary synchronization. * * Also note that because the subprogram's thread uses the "args" * array and strings, there will be a race condition between the * subprogram and the menu input code if the menu thread is not * made to wait (using one_thread_only or some other mechanism) */ static int common_prog(int nargs, char **args) { int result; #if OPT_SYNCHPROBS kprintf("Warning: this probably won't work with a " "synchronization-problems kernel.\n"); #endif result = thread_fork(args[0] /* thread name */, args /* thread arg */, nargs /* thread arg */, cmd_progthread, NULL); if (result) { kprintf("thread_fork failed: %s\n", strerror(result)); return result; } /* this function is a bit of a hack that is used to make * the kernel menu thread wait until the newly-forked * thread completes before the menu thread returns */ while (!one_thread_only()) { clocksleep(1); } return 0; }
/* * Common code for cmd_prog and cmd_shell. * * Note that this does not wait for the subprogram to finish, but * returns immediately to the menu. This is usually not what you want, * so you should have it call your system-calls-assignment waitpid * code after forking. * * Also note that because the subprogram's thread uses the "args" * array and strings, until you do this a race condition exists * between that code and the menu input code. */ static int common_prog(int nargs, char **args) { int result; #if OPT_SYNCHPROBS kprintf("Warning: this probably won't work with a " "synchronization-problems kernel.\n"); #endif #if OPT_BADSYNCH kprintf("Starting %s, menu will sleep for %d second(s)...\n", args[0], menusleep_secs); #endif result = thread_fork(args[0] /* thread name */, args /* thread arg */, nargs /* thread arg */, cmd_progthread, NULL); if (result) { kprintf("thread_fork failed: %s\n", strerror(result)); return result; } #if OPT_BADSYNCH clocksleep(menusleep_secs); #endif return 0; }
/* * 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; }
void cat_eat(unsigned int bowlnumber, int eat_time) { /* check the argument */ if ((bowlnumber == 0) || ((int)bowlnumber > num_bowls)) { panic("cat_eat: invalid bowl number %d\n",bowlnumber); } /* check and update the simulation state to indicate that * the cat is now eating at the specified bowl */ P(mutex); // start critical section /* first check whether allowing this cat to eat will * violate any simulation requirements */ if (bowls[bowlnumber-1] == 'c') { /* there is already a cat eating at the specified bowl */ panic("cat_eat: attempt to make two cats eat from bowl %d!\n",bowlnumber); } if (eating_mice_count > 0) { /* there is already a mouse eating at some bowl */ panic("cat_eat: attempt to make a cat eat while mice are eating!\n"); } KASSERT(bowls[bowlnumber-1]=='-'); KASSERT(eating_mice_count == 0); /* now update the state to indicate that the cat is eating */ eating_cats_count += 1; bowls[bowlnumber-1] = 'c'; /* print a summary of the current state */ kprintf("cat_eat (bowl %3d) start: ",bowlnumber); print_state(); kprintf("\n"); 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]=='c'); eating_cats_count -= 1; bowls[bowlnumber-1]='-'; /* print a summary of the current state */ kprintf("cat_eat (bowl %3d) finish: ",bowlnumber); print_state(); kprintf("\n"); V(mutex); // end critical section return; }
static void shower() { clocksleep(1); // The thread enjoys a refreshing shower! //clocksleep(1); }
/* who should be "cat" or "mouse" */ static void lock_eat(const char *who, int num, int bowl, int iteration) { kprintf("%s: %d starts eating: bowl %d, iteration %d\n", who, num, bowl, iteration); clocksleep(1); kprintf("%s: %d ends eating: bowl %d, iteration %d\n", who, num, bowl, iteration); }
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; }
static void cat(void * unusedpointer, unsigned long catnumber) { int whichBowl = 0; // 0 = neither bowl, 1 = bowlOne, 2 = bowlTwo (void) unusedpointer; //(void) catnumber; lock_acquire(l); //wait until there are no mioce eating and there is at most 1 cat eating while((catsEating > 1) || (miceEating > 0)) { cv_wait(c, l); } //choose a bowl if(!bowlOneUsed){ bowlOneUsed = 1; whichBowl = 1; } else if(!bowlTwoUsed){ bowlTwoUsed = 1; whichBowl = 2; } else panic("No bowl open for cat, even though we waited for an open bowl"); catsEating++; //cat eats lock_release(l); kprintf("cat %lu starts eating at bowl %d \n", catnumber, whichBowl); clocksleep(1); kprintf("cat %lu done eating at bowl %d \n", catnumber, whichBowl); lock_acquire(l); if(whichBowl == 1) bowlOneUsed = 0; else if (whichBowl == 2) bowlTwoUsed = 0; else panic("Neither bowl was used (cat)!"); catsEating--; cv_broadcast(c, l); lock_release(l); }
void baby_bird(void) { int sleep_time; do { // Don't try to eat until mama has filled the bowl /* This handles an issue where the bowl lock is released so that mama can refill bowl, but other babies enter scheduler first and claim the lock. */ while (food_in_bowl <= 0); kprintf("\nBaby bird acquiring bowl lock...\n"); lock_acquire(bowl_lock); // Lock out other babies kprintf("Baby bird has acquired the lock.\n"); kprintf("Baby bird is now eating...\n"); food_in_bowl--; // eat a portion kprintf("%d worms remain.\n", food_in_bowl); if (food_in_bowl <=0) { kprintf("\nOut of food.\n"); kprintf("Signalling mama...\n"); cv_signal(mama, bowl_lock); // alert mama to refill kprintf("I told mama to refill the bowl...\n"); kprintf("Releasing bowl lock...\n"); lock_release(bowl_lock); // release the lock } else { kprintf("Baby bird is releasing the lock...\n"); lock_release(bowl_lock); // Unlock the bowl } kprintf("Baby bird is sleeping...\n\n"); sleep_time = random() % MAXSLEEP; clocksleep(sleep_time); // Sleep a random number of seconds } while (1); }
/* * mouse_sleep() * * Purpose: * simulates a mouse sleeping * * Arguments: none * * Returns: nothing * */ void mouse_sleep() { /* simulate sleeping by introducing a delay */ clocksleep(MOUSESLEEPINGTIME); return; }
/* * cat_sleep() * * Purpose: * simulates a cat sleeping * * Arguments: none * * Returns: nothing * */ void cat_sleep() { /* simulate sleeping by introducing a delay */ clocksleep(CATSLEEPINGTIME); return; }
int catmouse(int nargs, char ** args) { int index, error, index2; /* * Avoid unused variable warnings. */ (void) nargs; (void) args; l = lock_create(lname); c = cv_create(cname); catsEating = 0; miceEating = 0; bowlOneUsed = 0; bowlTwoUsed = 0; /* * Start NMICE mouse() threads. */ for (index2 = 0; index2 < NMICE; index2++) { error = thread_fork("mouse thread", NULL, index2, mouse, NULL ); /* * panic() on error. */ if (error) { panic("mouse: thread_fork failed: %s\n", strerror(error) ); } } /* * Start NCATS cat() threads. */ for (index = 0; index < NCATS; index++) { error = thread_fork("cat thread", NULL, index, cat, NULL ); /* * panic() on error. */ if (error) { panic("cat: thread_fork failed: %s\n", strerror(error) ); } } //join threads with a CV if you have time, deallocate threads after join //cv_destroy(c); //lock_destroy(l); //we dont want the main thread to finish before the others clocksleep(10); return 0; }