diff --git a/invertedlogic/iLPlatform/iLSemaphore.inl b/invertedlogic/iLPlatform/iLSemaphore.inl index 683340d..4862cdb 100644 --- a/invertedlogic/iLPlatform/iLSemaphore.inl +++ b/invertedlogic/iLPlatform/iLSemaphore.inl @@ -1,9 +1,8 @@ +#if 0 // 1 + #include /* For O_* constants */ #include /* For mode constants */ - -#if 1 - typedef pthread_mutex_t iLMutex; typedef sem_t iLSemaphore; @@ -44,9 +43,10 @@ return iLR_OK; } -#else +#else // My mutex and semaphores -typedef uint32_t iLMutex; +#include "iLAtomics.h" +#include static inline iLResult iLMutex_Create(iLMutex* a_mutex) { @@ -54,16 +54,17 @@ return iLR_OK; } +//static inline iLResult iLMutex_Lock(iLMutex* a_mutex, int32_t a_maxSpinCount = 100000) static inline iLResult iLMutex_Lock(iLMutex* a_mutex) { int spinCount = 0; - while (__sync_lock_test_and_set(a_mutex, 1) == 1) + while (iLAtomic_CompareAndSwap32(a_mutex, 0, 1) != 0) // keep trying to set a_mutex to 1 until it is zero { spinCount++; - if (spinCount > 1000000) + if (spinCount > 100000) // a_maxSpinCount) { spinCount = 0; - pthread_yield(); + iLThread_Yield(); } } return iLR_OK; @@ -71,36 +72,56 @@ static inline iLResult iLMutex_Unlock(iLMutex* a_mutex) { - __sync_lock_release(a_mutex); + uint32_t oldVal = iLAtomic_CompareAndSwap32(a_mutex, 1, 0); + assert(oldVal == 1); // unlocking a mutex which isn't locked? return iLR_OK; } -struct iLSemaphore +static inline iLResult iLCondition_Create(iLCondition* a_cond) { - uint32_t count; - uint32_t maxCount; - uint32_t waitCount; - iLMutex mutex; - pthread_cond_t cond; -}; + a_cond->waiters = 0; + a_cond->signaled = 0; + return iLR_OK; +} -static inline iLResult iLSemaphore_Create(iLSemaphore* a_sem, uint32_t a_initCount, iLMutex* a_maxCount) +static inline iLResult iLCondition_Wait(iLCondition* a_cond, iLMutex* a_mutex) +{ + // Basically this unlocks the mutex, and then waits for cond to be signaled, then locks the mutex again + iLAtomic_Increment32(&a_cond->waiters); + iLMutex_Unlock(a_mutex); + // waiting here to be signaled - need to be woken but that is not something we can do ourselves + iLThread_Yield(); + iLMutex_Lock(a_mutex); + return iLR_OK; +} + +static inline iLResult iLCondition_Signal(iLCondition* /*a_cond*/) +{ + // TODO: check there is a waiter to be signalled, if there is, set one signaled, then wait for + // the waiters to decrease. Really this is a threads implementation feature, but not really + // implemented as you can plainly see + return iLR_OK; +} + +// Despite condition variables not being fully implemented, this semaphore implementation +// will still work, just somewhat inefficiently as it basically busy waits to be signalled +static inline iLResult iLSemaphore_Create(iLSemaphore* a_sem, uint32_t a_initCount, uint32_t a_maxCount) { a_sem->count = a_initCount; a_sem->maxCount = a_maxCount; a_sem->waitCount = 0; iLMutex_Create(&a_sem->mutex); - pthread_cond_init(&a_sem->cond, NULL); + iLCondition_Create(&a_sem->cond); return iLR_OK; } static inline iLResult iLSemaphore_Wait(iLSemaphore* a_sem) { iLMutex_Lock(&a_sem->mutex); - while(a_sem->count == 0) + while (a_sem->count == 0) { ++a_sem->waitCount; - pthread_cond_wait(&a_sem->cond, &a_sem->mutex); + iLCondition_Wait(&a_sem->cond, &a_sem->mutex); --a_sem->waitCount; } --a_sem->count; @@ -118,7 +139,7 @@ } if (a_sem->waitCount > 0) { - pthread_cond_signal(&a_sem->cond); + iLCondition_Signal(&a_sem->cond); } iLMutex_Unlock(&a_sem->mutex); return iLR_OK; @@ -126,4 +147,3 @@ #endif -