void PC_Put(PC *pc, int color) { Lock_Acquire(&pc->lock); assert(color <= pc->maxColor); while(pc->capacity == pc->used){ pc->waitingP++; Cond_Wait(&pc->spaceAvail, &pc->lock); pc->waitingP--; } pc->used++; addItem(color, &(pc->list)); assert(((Item *)List_Last(&(pc->list)))->color == color); if(pc->used == 1){ /* * Went from empty to non-empty. Signal */ if(pc->maxColor == 0){ Cond_Signal(&pc->stuffAvail, &pc->lock); } else{ Cond_Broadcast(&pc->stuffAvail, &pc->lock); } } assert(((Item *)List_Last(&(pc->list)))->color == color); Lock_Release(&pc->lock); }
int P(int sid) { struct Semaphore* sema = (&s_semaphoreList)->head; struct Mutex* mutex; struct Condition* cond; //find sem by sid while (sema != 0) { if (sema->sid == sid) { mutex = &(sema->mutex); // important cond = &(sema->cond); Enable_Interrupts(); Mutex_Lock(mutex); while(sema->count <= 0) { Cond_Wait(cond, mutex); //Print("WAKE UP!"); } sema->count--; Mutex_Unlock(mutex); Disable_Interrupts(); return 0; } sema = Get_Next_In_Semaphore_List(sema); } return -1; }
/* PROGRAM: Philosopher A program that simulates a philosopher participating in a dining philosophers' symposium. Each philosopher will join the symposium, alternating between thinking, going hungry and eating a bite, for a number of bites. After he has eaten the last bite, he leaves. */ int Philosopher(int argl, void* args) { int i,j; int bites; /* Number of bites (mpoykies) */ assert(argl == sizeof(int[2])); i = ((int*)args)[0]; bites = ((int*)args)[1]; Mutex_Lock(&mx); /* Philosopher arrives in thinking state */ state[i] = THINKING; print_state(" %d has arrived\n",i); Mutex_Unlock(&mx); for(j=0; j<bites; j++) { think(i); /* THINK */ Mutex_Lock(&mx); /* GO HUNGRY */ state[i] = HUNGRY; trytoeat(i); /* This may not succeed */ while(state[i]==HUNGRY) { print_state(" %d waits hungry\n",i); Cond_Wait(&mx, &(hungry[i])); /* If hungry we sleep. trytoeat(i) will wake us. */ } assert(state[i]==EATING); Mutex_Unlock(&mx); eat(i); /* EAT */ Mutex_Lock(&mx); state[i] = THINKING; /* We are done eating, think again */ print_state(" %d is thinking\n",i); trytoeat(LEFT(i)); /* Check if our left and right can eat NOW. */ trytoeat(RIGHT(i)); Mutex_Unlock(&mx); } Mutex_Lock(&mx); state[i] = NOTHERE; /* We are done (eaten all the bites) */ print_state(" %d is leaving\n",i); Mutex_Unlock(&mx); return i; }
int PC_Get(PC *pc, int color) { Lock_Acquire(&pc->lock); assert(color <= pc->maxColor); while(List_IsEmpty(&(pc->list)) || (((Item *)List_First(&(pc->list)))->color != color)){ pc->waitingC++; Cond_Wait(&pc->stuffAvail, &pc->lock); pc->waitingC--; } removeItem(color, &(pc->list)); pc->used--; Cond_Signal(&pc->spaceAvail, &pc->lock); /* * We just took top item off -- another getter may be * able to proceed */ Cond_Broadcast(&pc->stuffAvail, &pc->lock); Lock_Release(&pc->lock); return color; }
/* * Get buffer for given block, and mark it in use. * Must be called with cache mutex held. */ static int Get_Buffer(struct FS_Buffer_Cache *cache, ulong_t fsBlockNum, struct FS_Buffer **pBuf) { struct FS_Buffer *buf, *lru = 0; int rc; Debug("Request block %lu\n", fsBlockNum); KASSERT(IS_HELD(&cache->lock)); /* * Look for existing buffer. * As a side-effect, finds the least recently used * buffer that is not in use (if any). */ buf = Get_Front_Of_FS_Buffer_List(&cache->bufferList); while (buf != 0) { if (buf->fsBlockNum == fsBlockNum) { /* If buffer is in use, wait until it is available. */ while (buf->flags & FS_BUFFER_INUSE) { Debug("Waiting for block %lu\n", fsBlockNum); Cond_Wait(&cache->cond, &cache->lock); } goto done; } /* If buffer isn't in use, it's a candidate for LRU. */ if (!(buf->flags & FS_BUFFER_INUSE)) lru = buf; buf = Get_Next_In_FS_Buffer_List(buf); } /* * If number of allocated buffers does not exceed the * limit, allocate a new one. */ if (cache->numCached < FS_BUFFER_CACHE_MAX_BLOCKS) { buf = (struct FS_Buffer *)Malloc(sizeof(*buf)); if (buf != 0) { buf->data = Alloc_Page(); if (buf->data == 0) Free(buf); else { /* Successful creation */ buf->fsBlockNum = fsBlockNum; buf->flags = 0; Add_To_Front_Of_FS_Buffer_List(&cache->bufferList, buf); ++cache->numCached; goto readAndAcquire; } } } /* * If there is no LRU buffer, then we have exceeded * the number of available buffers. */ if (lru == 0) return ENOMEM; KASSERT(!noEvict); /* Make sure the LRU buffer is clean. */ if ((rc = Sync_Buffer(cache, lru)) != 0) return rc; /* LRU buffer is clean, so we can steal it. */ buf = lru; buf->flags = 0; buf->fsBlockNum = fsBlockNum; /* bugfix by neil. */ Move_To_Front(cache, buf); readAndAcquire: /* * The buffer selected should be clean (no uncommitted data), * and should have been moved to the front of the buffer list * (to show it has just been referenced). */ KASSERT(!(buf->flags & FS_BUFFER_DIRTY)); KASSERT(Get_Front_Of_FS_Buffer_List(&cache->bufferList) == buf); /* Read block data into buffer. */ if ((rc = Do_Buffer_IO(cache, buf, Block_Read)) != 0) return rc; done: /* Buffer is now in use. */ buf->flags |= FS_BUFFER_INUSE; /* Success! */ Debug("Acquired block %lu\n", fsBlockNum); *pBuf = buf; return 0; }