#ifndef __KERN_SYNC_MONITOR_CONDVAR_H__ #define __KERN_SYNC_MOINTOR_CONDVAR_H__ #include /* In [OS CONCEPT] 7.7 section, the accurate define and approximate implementation of MONITOR was introduced. * INTRODUCTION: * Monitors were invented by C. A. R. Hoare and Per Brinch Hansen, and were first implemented in Brinch Hansen's * Concurrent Pascal language. Generally, a monitor is a language construct and the compiler usually enforces mutual exclusion. Compare this with semaphores, which are usually an OS construct. * DEFNIE & CHARACTERISTIC: * A monitor is a collection of procedures, variables, and data structures grouped together. * Processes can call the monitor procedures but cannot access the internal data structures. * Only one process at a time may be be active in a monitor. * Condition variables allow for blocking and unblocking. * cv.wait() blocks a process. * The process is said to be waiting for (or waiting on) the condition variable cv. * cv.signal() (also called cv.notify) unblocks a process waiting for the condition variable cv. * When this occurs, we need to still require that only one process is active in the monitor. This can be done in several ways: * on some systems the old process (the one executing the signal) leaves the monitor and the new one enters * on some systems the signal must be the last statement executed inside the monitor. * on some systems the old process will block until the monitor is available again. * on some systems the new process (the one unblocked by the signal) will remain blocked until the monitor is available again. * If a condition variable is signaled with nobody waiting, the signal is lost. Compare this with semaphores, in which a signal will allow a process that executes a wait in the future to no block. * You should not think of a condition variable as a variable in the traditional sense. * It does not have a value. * Think of it as an object in the OOP sense. * It has two methods, wait and signal that manipulate the calling process. * IMPLEMENTATION: * monitor mt { * ----------------variable------------------ * semaphore mutex; * semaphore next; * int next_count; * condvar {int count, sempahore sem} cv[N]; * other variables in mt; * --------condvar wait/signal--------------- * cond_wait (cv) { * cv.count ++; * if(mt.next_count>0) * signal(mt.next) * else * signal(mt.mutex); * wait(cv.sem); * cv.count --; * } * * cond_signal(cv) { * if(cv.count>0) { * mt.next_count ++; * signal(cv.sem); * wait(mt.next); * mt.next_count--; * } * } * --------routines in monitor--------------- * routineA_in_mt () { * wait(mt.mutex); * ... * real body of routineA * ... * if(next_count>0) * signal(mt.next); * else * signal(mt.mutex); * } */ typedef struct monitor monitor_t; 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; // Initialize variables in monitor. void monitor_init (monitor_t *cvp, size_t num_cv); // Unlock one of threads waiting on the condition variable. void cond_signal (condvar_t *cvp); // Suspend calling thread on a condition variable waiting for condition atomically unlock mutex in monitor, // and suspends calling thread on conditional variable after waking up locks mutex. void cond_wait (condvar_t *cvp); #endif /* !__KERN_SYNC_MONITOR_CONDVAR_H__ */