mutex:初始值为1,用于对管程的互斥访问
next:初始值为0,作为一个等待队列,用于阻塞已获得mutex的进程,next_count用于记录阻塞于next的进程数,类似于条件变量中的等待队列,唤醒等待进程的信号不可存储,即只可以唤醒事先进入等待队列的进程,而不能记录信号用来使后来的进程避免等待。
cv:条件变量,使需要等待某一条件出现的进程进入响应的等待队列,先等待后唤醒,使用semaphore来模拟,信号量初值为0
typedef struct condvar{
semaphore_t sem; // the sem semaphore is used to down the waiting proc, and the signaling proc should up the waiting proc
int count; // the number of waiters on condvar
monitor_t * owner; // the owner(monitor) of this condvar
} condvar_t;
typedef struct monitor{
semaphore_t mutex; // the mutex lock for going into the routines in monitor, should be initialized to 1
semaphore_t next; // the next semaphore is used to down the signaling proc itself, and the other OR wakeuped waiting proc should wake up the sleeped signaling proc.
int next_count; // the number of of sleeped signaling proc
condvar_t *cv; // the condvars in monitor
} monitor_t;
用于唤醒等待在某条件变量等待队列的进程。初始时先判断是否有进程等待,没有则不做操作,一次唤醒操作将丢失,有进程等待则唤醒。ucore使用的管程方案当唤醒某等待进程时,唤醒者阻塞自身,将使用管程的权利出让给被唤醒者。由于唤醒者在调用cond_signal之前必然已经获得了mutex,唤醒者在保持mutex的情况下等待在next的等待队列中,直到被唤醒者归还使用管程的权利,将唤醒者从next唤醒。
void
cond_signal (condvar_t *cvp) {
//LAB7 EXERCISE1: YOUR CODE
cprintf("cond_signal begin: cvp %x, cvp->count %d, cvp->owner->next_count %d\n", cvp, cvp->count, cvp->owner->next_count);
/*
* cond_signal(cv) {
* if(cv.count>0) {
* mt.next_count ++;
* signal(cv.sem);
* wait(mt.next);
* mt.next_count--;
* }
* }
*/
if(cvp->count>0) {
cvp->owner->next_count ++;
up(&(cvp->sem));
down(&(cvp->owner->next));
cvp->owner->next_count --;
}
cprintf("cond_signal end: cvp %x, cvp->count %d, cvp->owner->next_count %d\n", cvp, cvp->count, cvp->owner->next_count);
}
用于等待某条件出现,被cond_signal唤醒。此处的if判断只能指向else,并释放mutex,然后进入等待,直到唤醒者进程获得mutex将其唤醒并阻塞于next。
void
cond_wait (condvar_t *cvp) {
//LAB7 EXERCISE1: YOUR CODE
cprintf("cond_wait begin: cvp %x, cvp->count %d, cvp->owner->next_count %d\n", cvp, cvp->count, cvp->owner->next_count);
cvp->count++;
if ((cvp->owner)->next_count > 0)
up(&((cvp->owner)->next));
else
up(&((cvp->owner)->mutex));
down(&(cvp->sem));
cvp->count--;
/*
* cv.count ++;
* if(mt.next_count>0)
* signal(mt.next)
* else
* signal(mt.mutex);
* wait(cv.sem);
* cv.count --;
*/
cprintf("cond_wait end: cvp %x, cvp->count %d, cvp->owner->next_count %d\n", cvp, cvp->count, cvp->owner->next_count);
}
执行cond_wait的进程
获得mutex -> 释放mutex -> 进入条件等待 -> 执行 -> 唤醒阻塞于next的进程
执行cond_signal的进程
-> 获得mutex -> 唤醒等待条件的进程 -> 等待于next
-> 释放mutex