#if 0 // 1
#include <fcntl.h> /* For O_* constants */
#include <sys/stat.h> /* For mode constants */
typedef pthread_mutex_t iLMutex;
typedef sem_t iLSemaphore;
static inline iLResult iLMutex_Create(iLMutex* a_mutex)
{
pthread_mutex_init(a_mutex, NULL);
return iLR_OK;
}
static inline iLResult iLMutex_Lock(iLMutex* a_mutex)
{
pthread_mutex_lock(a_mutex);
return iLR_OK;
}
static inline iLResult iLMutex_Unlock(iLMutex* a_mutex)
{
pthread_mutex_unlock(a_mutex);
return iLR_OK;
}
static inline iLResult iLSemaphore_Create(iLSemaphore* a_sem, uint32_t a_initCount, uint32_t a_maxCount)
{
a_sem = sem_open("/sem", O_CREAT, S_IRWXU, a_initCount);
return iLR_OK;
}
static inline iLResult iLSemaphore_Wait(iLSemaphore* a_sem)
{
sem_wait(a_sem);
return iLR_OK;
}
static inline iLResult iLSemaphore_Signal(iLSemaphore* a_sem, uint32_t a_count)
{
for (int i = 0; i < a_count; i++)
sem_post(a_sem);
return iLR_OK;
}
#else // My mutex and semaphores
#include "iLAtomics.h"
#include <assert.h>
static inline iLResult iLMutex_Create(iLMutex* a_mutex)
{
*a_mutex = 0;
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 (iLAtomic_CompareAndSwap32(a_mutex, 0, 1) != 0) // keep trying to set a_mutex to 1 until it is zero
{
spinCount++;
if (spinCount > 100000) // a_maxSpinCount)
{
spinCount = 0;
iLThread_Yield();
}
}
return iLR_OK;
}
static inline iLResult iLMutex_Unlock(iLMutex* a_mutex)
{
uint32_t oldVal = iLAtomic_CompareAndSwap32(a_mutex, 1, 0);
assert(oldVal == 1); // unlocking a mutex which isn't locked?
return iLR_OK;
}
static inline iLResult iLCondition_Create(iLCondition* a_cond)
{
a_cond->waiters = 0;
a_cond->signaled = 0;
return iLR_OK;
}
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);
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)
{
++a_sem->waitCount;
iLCondition_Wait(&a_sem->cond, &a_sem->mutex);
--a_sem->waitCount;
}
--a_sem->count;
iLMutex_Unlock(&a_sem->mutex);
return iLR_OK;
}
static inline iLResult iLSemaphore_Signal(iLSemaphore* a_sem, uint32_t a_count)
{
iLMutex_Lock(&a_sem->mutex);
a_sem->count += a_count;
if (a_sem->count > a_sem->maxCount)
{
a_sem->count = a_sem->maxCount;
}
if (a_sem->waitCount > 0)
{
iLCondition_Signal(&a_sem->cond);
}
iLMutex_Unlock(&a_sem->mutex);
return iLR_OK;
}
#endif