#include "bee2/core/mem.h"
#include "bee2/core/mt.h"
#include "bee2/core/util.h"
#ifdef OS_WIN
bool_t mtMtxCreate(mt_mtx_t* mtx)
{
ASSERT(memIsValid(mtx, sizeof(mt_mtx_t)));
return InitializeCriticalSectionAndSpinCount(mtx, 0x400);
}
bool_t mtMtxIsValid(const mt_mtx_t* mtx)
{
return memIsValid(mtx, sizeof(mt_mtx_t));
}
void mtMtxLock(mt_mtx_t* mtx)
{
ASSERT(mtMtxIsValid(mtx));
EnterCriticalSection(mtx);
}
void mtMtxUnlock(mt_mtx_t* mtx)
{
ASSERT(mtMtxIsValid(mtx));
LeaveCriticalSection(mtx);
}
void mtMtxClose(mt_mtx_t* mtx)
{
ASSERT(mtMtxIsValid(mtx));
DeleteCriticalSection(mtx);
}
#elif defined OS_UNIX
bool_t mtMtxCreate(mt_mtx_t* mtx)
{
ASSERT(memIsValid(mtx, sizeof(mt_mtx_t)));
return pthread_mutex_init(mtx, 0) == 0;
}
bool_t mtMtxIsValid(const mt_mtx_t* mtx)
{
return memIsValid(mtx, sizeof(mt_mtx_t));
}
void mtMtxLock(mt_mtx_t* mtx)
{
ASSERT(mtMtxIsValid(mtx));
pthread_mutex_lock(mtx);
}
void mtMtxUnlock(mt_mtx_t* mtx)
{
ASSERT(mtMtxIsValid(mtx));
pthread_mutex_unlock(mtx);
}
void mtMtxClose(mt_mtx_t* mtx)
{
ASSERT(mtMtxIsValid(mtx));
pthread_mutex_destroy(mtx);
}
#else
bool_t mtMtxCreate(mt_mtx_t* mtx)
{
return TRUE;
}
bool_t mtMtxIsValid(const mt_mtx_t* mtx)
{
return TRUE;
}
void mtMtxLock(mt_mtx_t* mtx)
{
ASSERT(mtMtxIsValid(mtx));
}
void mtMtxUnlock(mt_mtx_t* mtx)
{
ASSERT(mtMtxIsValid(mtx));
}
void mtMtxClose(mt_mtx_t* mtx)
{
ASSERT(mtMtxIsValid(mtx));
}
#endif
#ifdef OS_WIN
void mtSleep(u32 ms)
{
Sleep(ms);
}
#elif defined OS_UNIX
#include <time.h>
void mtSleep(u32 ms)
{
struct timespec ts;
ts.tv_sec = (time_t)ms, ts.tv_sec /= 1000;
ts.tv_nsec = (long)ms, ts.tv_nsec *= 1000, ts.tv_nsec *= 1000;
ts.tv_nsec %= 1000000000l;
nanosleep(&ts, 0);
}
#else
void mtSleep(u32 ms)
{
}
#endif
bool_t mtCallOnce(size_t* once, void (*fn)())
{
size_t t;
do
if ((t = mtAtomicCmpSwap(once, 0, SIZE_MAX)) == 0)
{
fn(), *once = 1;
break;
}
while (t == SIZE_MAX);
ASSERT(*once == 1);
return TRUE;
}
#ifdef OS_WIN
#if (O_PER_S == 8)
size_t mtAtomicIncr(size_t* ctr)
{
ASSERT(memIsAligned(ctr, O_PER_S));
return InterlockedIncrement64((i64 volatile*)ctr);
}
size_t mtAtomicDecr(size_t* ctr)
{
ASSERT(memIsAligned(ctr, O_PER_S));
return InterlockedDecrement64((i64 volatile*)ctr);
}
size_t mtAtomicCmpSwap(size_t* ctr, size_t cmp, size_t swap)
{
ASSERT(memIsAligned(ctr, O_PER_S));
return InterlockedCompareExchange64((i64 volatile*)ctr,
(i64)swap, (i64)cmp);
}
#elif (O_PER_S == 4)
size_t mtAtomicIncr(size_t* ctr)
{
ASSERT(memIsAligned(ctr, O_PER_S));
return InterlockedIncrement((i32 volatile*)ctr);
}
size_t mtAtomicDecr(size_t* ctr)
{
ASSERT(memIsAligned(ctr, O_PER_S));
return InterlockedDecrement((i32 volatile*)ctr);
}
size_t mtAtomicCmpSwap(size_t* ctr, size_t cmp, size_t swap)
{
ASSERT(memIsAligned(ctr, O_PER_S));
return InterlockedCompareExchange((i32 volatile*)ctr,
(i32)swap, (i32)cmp);
}
#elif (O_PER_S == 2)
size_t mtAtomicIncr(size_t* ctr)
{
ASSERT(memIsAligned(ctr, O_PER_S));
return InterlockedIncrement16((i16 volatile*)ctr);
}
size_t mtAtomicDecr(size_t* ctr)
{
ASSERT(memIsAligned(ctr, O_PER_S));
return InterlockedDecrement16((i16 volatile*)ctr);
}
size_t mtAtomicCmpSwap(size_t* ctr, size_t cmp, size_t swap)
{
ASSERT(memIsAligned(ctr, O_PER_S));
return InterlockedCompareExchange16((i16 volatile*)ctr,
(i16)swap, (i16)cmp);
}
#else
#error "Unsupported size_t"
#endif
#elif defined OS_UNIX
size_t mtAtomicIncr(size_t* ctr)
{
return __sync_add_and_fetch(ctr, SIZE_1);
}
size_t mtAtomicDecr(size_t* ctr)
{
return __sync_sub_and_fetch(ctr, SIZE_1);
}
size_t mtAtomicCmpSwap(size_t* ctr, size_t cmp, size_t swap)
{
return __sync_val_compare_and_swap(ctr, cmp, swap);
}
#else
size_t mtAtomicIncr(size_t* ctr)
{
ASSERT(memIsValid(ctr, O_PER_S));
return ++*ctr;
}
size_t mtAtomicDecr(size_t* ctr)
{
ASSERT(memIsValid(ctr, O_PER_S));
return --*ctr;
}
size_t mtAtomicCmpSwap(size_t* ctr, size_t cmp, size_t swap)
{
register size_t t;
ASSERT(memIsValid(ctr, O_PER_S));
*ctr = ((t = *ctr) == cmp) ? swap : t;
return t;
}
#endif