#include "object/semaphore.h" #include "scheduler/scheduler.h" glcr::RefPtr Semaphore::Create() { return glcr::AdoptPtr(new Semaphore()); } // FIXME: We almost certainly have some race conditions // between this and unlock where we could end up with // a thread in the blocked_threads_ queue while noone is holding the lock. void Semaphore::Signal() { __atomic_fetch_add(&lock_, 0x1, __ATOMIC_SEQ_CST); if (blocked_threads_.size() > 0) { auto thread = blocked_threads_.PopFront(); thread->SetState(Thread::RUNNABLE); gScheduler->Enqueue(thread); } } void Semaphore::Wait() { while (lock_ == 0) { auto thread = gScheduler->CurrentThread(); thread->SetState(Thread::BLOCKED); blocked_threads_.PushBack(thread); gScheduler->Yield(); } __atomic_fetch_sub(&lock_, 0x1, __ATOMIC_SEQ_CST); }