/* * Mutexes * * Mutexes can be held by only one thread * at a time, the following exceptions may * be raised: * * exception deadlock (mutex m, thread self) * * Raised when a thread attempts to reacquire the mutex * * exception notowned (mutex m, thread self, mutex_owner owner) * * Raised when a thread attempts to release a mutex not owned by it. */ /* A mutex is either owned by a thread or nobody */ typedef union { thread owner; void nobody; } mutex_owner; public typedef struct { semaphore sem; mutex_owner owner; } mutex_struct; public typedef *mutex_struct mutex; namespace Mutex { public typedef *mutex_struct mutex; public exception deadlock (mutex m, thread self) /* * raised when attempting to lock a mutex locked by self */; public exception notowned (mutex m, thread self, mutex_owner owner) /* * raised when attempting to release a mutex which is not locked */; public bool acquire (mutex m) /* * Lock 'm' */ { if (m->owner == (mutex_owner.owner) Thread::current()) raise deadlock (m, Thread::current ()); Semaphore::wait(m->sem); m->owner = (mutex_owner.owner) Thread::current (); return true; } public bool try_acquire (mutex m) /* * If 'm' is unlocked, acquire (m) and return true * else return false */ { if (m->owner == (mutex_owner.owner) Thread::current()) raise deadlock (m, Thread::current()); bool ret = Semaphore::test (m->sem); if (ret) m->owner = (mutex_owner.owner) Thread::current(); return ret; } public void release (mutex m) /* * Unlock 'm' */ { if (m->owner != (mutex_owner.owner) Thread::current()) raise notowned (m, Thread::current (), m->owner); m->owner = mutex_owner.nobody; Semaphore::signal (m->sem); } public mutex_owner owner (mutex m) /* * Return owner of 'm' */ { return m->owner; } public mutex new () /* * Create new (unlocked) mutex */ { return reference ((mutex_struct) { sem = Semaphore::new (1), owner = mutex_owner.nobody }); } }