typedef struct { int value;//资源数目 wait_queue_t wait_queue;//等待队列 } semaphore_t;
static __noinline void __up(semaphore_t *sem, uint32_t wait_state) { bool intr_flag; local_intr_save(intr_flag); { wait_t *wait; //如果没有正在等待的进程,直接资源++ if ((wait = wait_queue_first(&(sem->wait_queue))) == NULL) { sem->value ++; } //否则唤醒位于等待队列中的进程 else { assert(wait->proc->wait_state == wait_state); wakeup_wait(&(sem->wait_queue), wait, wait_state, 1); } } local_intr_restore(intr_flag); } static __noinline uint32_t __down(semaphore_t *sem, uint32_t wait_state) { bool intr_flag; local_intr_save(intr_flag);//关中断 //如果资源数大于零直接资源--,返回 if (sem->value > 0) { sem->value --; local_intr_restore(intr_flag); return 0; } wait_t __wait, *wait = &__wait; wait_current_set(&(sem->wait_queue), wait, wait_state);//挂起 local_intr_restore(intr_flag);//开中断 schedule();//等待被唤醒 local_intr_save(intr_flag); //重新调度 wait_current_del(&(sem->wait_queue), wait); local_intr_restore(intr_flag); if (wait->wakeup_flags != wait_state) { return wait->wakeup_flags; } return 0; }
定时器、屏蔽/使能中断、等待队列wait_queue支持test_and_set_bit等原子操作机器指令
在ucore信号量中使用的是开关中断.
? 管程内部的共享变量;
? 管程内部的条件变量;
? 管程内部并发执行的进程;
? 对局部于管程内部的共享数据设置初始值的语句。
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;
哎这个next一开始搞得我很迷,其实就是说由于唤醒别人而自己睡着的进程个数。他们被唤醒是无条件的,只要保证对管程的互斥访问即可。
每一个条件变量有它自己的等待队列,那么这个next是由于唤醒了别人,自己被挂在next上了,每个进程执行结束之后先查一查有没有挂在next上的进程,有的话先唤醒这个进程(Vnext),没有的话就放其他进程进来(Vmutex)。
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); } // Suspend calling thread on a condition variable waiting for condition Atomically unlocks // mutex and suspends calling thread on conditional variable after waking up locks mutex. Notice: mp is mutex semaphore for monitor‘s procedures 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); /* * cv.count ++; * if(mt.next_count>0) * signal(mt.next) * else * signal(mt.mutex); * wait(cv.sem); * cv.count --; */ cvp->count++; if(cvp->owner->next_count > 0) up(&(cvp->owner->next)); else up(&(cvp->owner->mutex)); down(&(cvp->sem)); cvp->count --; cprintf("cond_wait end: cvp %x, cvp->count %d, cvp->owner->next_count %d\n", cvp, cvp->count, cvp->owner->next_count); }
为了让整个管程正常运行,还需在管程中的每个函数的入口和出口增加相关操作,即:
function_in_monitor (…) { sem.wait(monitor.mutex); //----------------------------- the real body of function; //----------------------------- if(monitor.next_count > 0) sem_signal(monitor.next); else sem_signal(monitor.mutex); }
这样带来的作用有两个,(1)只有一个进程在执行管程中的函数。(2)避免由于执行了cond_signal函数而睡眠的进程无法被唤醒。对于第二点,如果进程A由于执行了cond_signal函数而睡眠(这会让monitor.next_count大于0,且执行sem_wait(monitor.next)),则其他进程在执行管程中的函数的出口,会判断monitor.next_count是否大于0,如果大于0,则执行sem_signal(monitor.next),从而执行了cond_signal函数而睡眠的进程被唤醒。上诉措施将使得管程正常执行。
原文:https://www.cnblogs.com/obob/p/11767012.html