void Threading::Semaphore::Post(int multiple) { for (int i = 0; i < multiple; ++i) { MACH_CHECK(semaphore_signal(m_sema)); } __atomic_add_fetch(&m_counter, multiple, __ATOMIC_SEQ_CST); }
Threading::Semaphore::Semaphore() { // other platforms explicitly make a thread-private (unshared) semaphore // here. But it seems Mach doesn't support that. MACH_CHECK(semaphore_create(mach_task_self(), (semaphore_t *)&m_sema, SYNC_POLICY_FIFO, 0)); __atomic_store_n(&m_counter, 0, __ATOMIC_SEQ_CST); }
int32 ReadReg (uint32 pa, int32 lnt) { struct reglink *p; for (p = ®table[0]; p->low != 0; p++) { if ((pa >= p->low) && (pa < p->high) && p->read) return p->read (pa); } MACH_CHECK (MCHK_READ); }
bool Threading::Semaphore::WaitWithoutYield(const wxTimeSpan& timeout) { // This method is the reason why there has to be a special Darwin // implementation of Semaphore. Note that semaphore_timedwait() is prone // to returning with KERN_ABORTED, which basically signifies that some // signal has worken it up. The best official "documentation" for // semaphore_timedwait() is the way it's used in Grand Central Dispatch, // which is open-source. // on x86 platforms, mach_absolute_time() returns nanoseconds // TODO(aktau): on iOS a scale value from mach_timebase_info will be necessary u64 const kOneThousand = 1000; u64 const kOneBillion = kOneThousand * kOneThousand * kOneThousand; u64 const delta = timeout.GetMilliseconds().GetValue() * (kOneThousand * kOneThousand); mach_timespec_t ts; kern_return_t kr = KERN_ABORTED; for (u64 now = mach_absolute_time(), deadline = now + delta; kr == KERN_ABORTED; now = mach_absolute_time()) { if (now > deadline) { // timed out by definition return false; } u64 timeleft = deadline - now; ts.tv_sec = timeleft / kOneBillion; ts.tv_nsec = timeleft % kOneBillion; // possible return values of semaphore_timedwait() (from XNU sources): // internal kernel val -> return value // THREAD_INTERRUPTED -> KERN_ABORTED // THREAD_TIMED_OUT -> KERN_OPERATION_TIMED_OUT // THREAD_AWAKENED -> KERN_SUCCESS // THREAD_RESTART -> KERN_TERMINATED // default -> KERN_FAILURE kr = semaphore_timedwait(m_sema, ts); } if (kr == KERN_OPERATION_TIMED_OUT) { return false; } // while it's entirely possible to have KERN_FAILURE here, we should // probably assert so we can study and correct the actual error here // (the thread dying while someone is wainting for it). MACH_CHECK(kr); __atomic_sub_fetch(&m_counter, 1, __ATOMIC_SEQ_CST); return true; }
void Threading::Semaphore::WaitWithoutYield() { pxAssertMsg(!wxThread::IsMain(), "Unyielding semaphore wait issued from the main/gui thread. Please use Wait() instead."); MACH_CHECK(semaphore_wait(m_sema)); __atomic_sub_fetch(&m_counter, 1, __ATOMIC_SEQ_CST); }
void Threading::Semaphore::Post() { MACH_CHECK(semaphore_signal(m_sema)); __atomic_add_fetch(&m_counter, 1, __ATOMIC_SEQ_CST); }
void Threading::Semaphore::Reset() { MACH_CHECK(semaphore_destroy(mach_task_self(), (semaphore_t) m_sema)); MACH_CHECK(semaphore_create(mach_task_self(), (semaphore_t *) &m_sema, SYNC_POLICY_FIFO, 0)); __atomic_store_n(&m_counter, 0, __ATOMIC_SEQ_CST); }
Threading::Semaphore::~Semaphore() throw() { MACH_CHECK(semaphore_destroy(mach_task_self(), (semaphore_t) m_sema)); __atomic_store_n(&m_counter, 0, __ATOMIC_SEQ_CST); }