// Dolphin OS - OSSemaphore.c
// RE by org - kvzorganic@mail.ru

typedef struct OSSemaphore
{
    s32           count;
    OSThreadQueue queue;
} OSSemaphore;

void OSInitSemaphore(OSSemaphore *sem, s32 count)
{
    BOOL enabled = OSDisableInterrupts();
    OSInitThreadQueue(&sem->queue);
    sem->count = count;
    OSRestoreInterrupts(enabled);
}

s32 OSWaitSemaphore(OSSemaphore *sem)
{
    BOOL enabled = OSDisableInterrupts();
    s32  count;    // previous value

    do
    {
        OSSleepThread(&sem->queue);
    } while((count = sem->count) <= 0);

    sem->count--;
    OSRestoreInterrupts(enabled);
    return count;
}

s32 OSTryWaitSemaphore(OSSemaphore *sem)
{
    BOOL enabled = OSDisableInterrupts();
    s32  count;    // previous value

    if((count = sem->count) > 0)
    {
        sem->count--;
    }

    OSRestoreInterrupts(enabled);
    return count;
}

s32 OSSignalSemaphore(OSSemaphore *sem)
{
    BOOL enabled = OSDisableInterrupts();
    s32  count   = sem->count++;

    OSWakeupThread(&sem->queue);

    OSRestoreInterrupts(enabled);
    return count;
}

s32 OSGetSemaphoreCount(OSSemaphore *sem)
{
    return sem->count;
}
