TASK_DLLEXPORT int Task_wait_read(int fd, long msec) { Task *tp; struct timeval tv; fd_set set; int r; if (!canSwitch) { FD_ZERO(&set); FD_SET(fd, &set); calcTv(&tv, msec); r = t_select(FD_SETSIZE, &set, 0, 0, &tv); if (r > 0) return 0; else if (r == 0) return 1; else return r; } tp = currTask; FD_ZERO(&set); FD_SET(fd, &set); tv.tv_sec = tv.tv_usec = 0; r = t_select(FD_SETSIZE, &set, 0, 0, &tv); if (r != 0) { Task_yield(); if (r > 0) return 0; else return r; } FD_ZERO(&tp->rfileset); FD_SET(fd, &tp->rfileset); tp->wakeUp = calcWakeup(msec); removeFromList(tp); tp->isRead = 1; addToWait(tp); tp->isTimed = 0; Task_yield(); tp->isRead = 0; return tp->isTimed; }
//call before moving to a new area //called on a chef to check if other chefs //are executing recipes that could cause a deadlock //if a deadlock case could occur based on the order of the //recipes on the other two chefs, the called on chef downs its //own semaphore, which should be 0, going to sleep. //To wake a chef, call clearAreas(Data *mychef) void checkChefs(Data *mychef) { int i, j, semval; //loop through the array of data structs //protect shared list of data sem_wait(&s_list); for(i = 0; i < 3; i++) { sem_getvalue(&chefs[i].sem,&semval); if(mychef->step == -1) { if(mychef->recipe.tasks[0].a == chefs[i].recipe.tasks[chefs[i].step].a) { addToWait(mychef, &chefs[i]); //release data list and go to sleep sem_post(&s_list); sem_wait(&chefs[mychef->ID].sem); } } //check for deadlocks based on recipes //only loop through recipies of awake, executing chefs if((semval > -1)&&(chefs[i].ID != mychef->ID)) { for(j = chefs[i].recipe.numTasks; j > -1; j--) { //check a deadlock case in which my area is the next area of another chef //and my next area is currently occupied by that chef if((mychef->recipe.tasks[mychef->step].a == chefs[i].recipe.tasks[j+1].a) && (mychef->recipe.tasks[(mychef->step)+1].a == chefs[i].recipe.tasks[j].a)) { addToWait(mychef, &chefs[i]); //release data list and go to sleep sem_post(&s_list); sem_wait(&(chefs[mychef->ID].sem)); printf("Chef %d is going to sleep in %s area",mychef->ID, getAreaStr(mychef->recipe.tasks[mychef->step].a)); } } } //check if mychef's next area is currently occupied by another chef if(mychef->recipe.tasks[(mychef->step)+1].a == chefs[i].recipe.tasks[chefs[i].step].a) { addToWait(mychef, &chefs[i]); //release data list and go to sleep sem_post(&s_list); sem_wait(&(chefs[mychef->ID].sem)); } } }