/*
 * Win32 semaphores
 *
 * Copyright 1998 Alexandre Julliard
 */

#include <assert.h>
#include "windows.h"
#include "winerror.h"
#include "k32obj.h"
#include "process.h"
#include "thread.h"
#include "heap.h"

typedef struct
{
    K32OBJ        header;
    THREAD_QUEUE  wait_queue;
    LONG          count;
    LONG          max;
} SEMAPHORE;

static BOOL32 SEMAPHORE_Signaled( K32OBJ *obj, DWORD thread_id );
static BOOL32 SEMAPHORE_Satisfied( K32OBJ *obj, DWORD thread_id );
static void SEMAPHORE_AddWait( K32OBJ *obj, DWORD thread_id );
static void SEMAPHORE_RemoveWait( K32OBJ *obj, DWORD thread_id );
static void SEMAPHORE_Destroy( K32OBJ *obj );

const K32OBJ_OPS SEMAPHORE_Ops =
{
    SEMAPHORE_Signaled,    /* signaled */
    SEMAPHORE_Satisfied,   /* satisfied */
    SEMAPHORE_AddWait,     /* add_wait */
    SEMAPHORE_RemoveWait,  /* remove_wait */
    NULL,                  /* read */
    NULL,                  /* write */
    SEMAPHORE_Destroy      /* destroy */
};


/***********************************************************************
 *           CreateSemaphore32A   (KERNEL32.174)
 */
HANDLE32 WINAPI CreateSemaphore32A( SECURITY_ATTRIBUTES *sa, LONG initial,
                                    LONG max, LPCSTR name )
{
    HANDLE32 handle;
    SEMAPHORE *sem;

    /* Check parameters */

    if ((max <= 0) || (initial < 0) || (initial > max))
    {
        SetLastError( ERROR_INVALID_PARAMETER );
        return INVALID_HANDLE_VALUE32;
    }

    SYSTEM_LOCK();
    sem = (SEMAPHORE *)K32OBJ_Create( K32OBJ_SEMAPHORE, sizeof(*sem),
                                      name, SEMAPHORE_ALL_ACCESS, sa, &handle);
    if (sem)
    {
        /* Finish initializing it */
        sem->wait_queue = NULL;
        sem->count      = initial;
        sem->max        = max;
        K32OBJ_DecCount( &sem->header );
    }
    SYSTEM_UNLOCK();
    return handle;
}


/***********************************************************************
 *           CreateSemaphore32W   (KERNEL32.175)
 */
HANDLE32 WINAPI CreateSemaphore32W( SECURITY_ATTRIBUTES *sa, LONG initial,
                                    LONG max, LPCWSTR name )
{
    LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
    HANDLE32 ret = CreateSemaphore32A( sa, initial, max, nameA );
    if (nameA) HeapFree( GetProcessHeap(), 0, nameA );
    return ret;
}


/***********************************************************************
 *           OpenSemaphore32A   (KERNEL32.545)
 */
HANDLE32 WINAPI OpenSemaphore32A( DWORD access, BOOL32 inherit, LPCSTR name )
{
    HANDLE32 handle = 0;
    K32OBJ *obj;
    SYSTEM_LOCK();
    if ((obj = K32OBJ_FindNameType( name, K32OBJ_SEMAPHORE )) != NULL)
    {
        handle = HANDLE_Alloc( PROCESS_Current(), obj, access, inherit, -1 );
        K32OBJ_DecCount( obj );
    }
    SYSTEM_UNLOCK();
    return handle;
}


/***********************************************************************
 *           OpenSemaphore32W   (KERNEL32.546)
 */
HANDLE32 WINAPI OpenSemaphore32W( DWORD access, BOOL32 inherit, LPCWSTR name )
{
    LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
    HANDLE32 ret = OpenSemaphore32A( access, inherit, nameA );
    if (nameA) HeapFree( GetProcessHeap(), 0, nameA );
    return ret;
}


/***********************************************************************
 *           ReleaseSemaphore   (KERNEL32.583)
 */
BOOL32 WINAPI ReleaseSemaphore( HANDLE32 handle, LONG count, LONG *previous )
{
    SEMAPHORE *sem;

    SYSTEM_LOCK();
    if (!(sem = (SEMAPHORE *)HANDLE_GetObjPtr( PROCESS_Current(), handle,
                                               K32OBJ_SEMAPHORE,
                                               SEMAPHORE_MODIFY_STATE, NULL )))
    {
        SYSTEM_UNLOCK();
        return FALSE;
    }
    if (previous) *previous = sem->count;
    if (sem->count + count > sem->max)
    {
        SYSTEM_UNLOCK();
        SetLastError( ERROR_TOO_MANY_POSTS );
        return FALSE;
    }
    if (sem->count > 0)
    {
        /* There cannot be any thread waiting if the count is > 0 */
        assert( sem->wait_queue == NULL );
        sem->count += count;
    }
    else
    {
        sem->count = count;
        SYNC_WakeUp( &sem->wait_queue, count );
    }
    K32OBJ_DecCount( &sem->header );
    SYSTEM_UNLOCK();
    return TRUE;
}


/***********************************************************************
 *           SEMAPHORE_Signaled
 */
static BOOL32 SEMAPHORE_Signaled( K32OBJ *obj, DWORD thread_id )
{
    SEMAPHORE *sem = (SEMAPHORE *)obj;
    assert( obj->type == K32OBJ_SEMAPHORE );
    return (sem->count > 0);
}


/***********************************************************************
 *           SEMAPHORE_Satisfied
 *
 * Wait on this object has been satisfied.
 */
static BOOL32 SEMAPHORE_Satisfied( K32OBJ *obj, DWORD thread_id )
{
    SEMAPHORE *sem = (SEMAPHORE *)obj;
    assert( obj->type == K32OBJ_SEMAPHORE );
    assert( sem->count > 0 );
    sem->count--;
    return FALSE;  /* Not abandoned */
}


/***********************************************************************
 *           SEMAPHORE_AddWait
 *
 * Add current thread to object wait queue.
 */
static void SEMAPHORE_AddWait( K32OBJ *obj, DWORD thread_id )
{
    SEMAPHORE *sem = (SEMAPHORE *)obj;
    assert( obj->type == K32OBJ_SEMAPHORE );
    THREAD_AddQueue( &sem->wait_queue, THREAD_ID_TO_THDB(thread_id) );
}


/***********************************************************************
 *           SEMAPHORE_RemoveWait
 *
 * Remove thread from object wait queue.
 */
static void SEMAPHORE_RemoveWait( K32OBJ *obj, DWORD thread_id )
{
    SEMAPHORE *sem = (SEMAPHORE *)obj;
    assert( obj->type == K32OBJ_SEMAPHORE );
    THREAD_RemoveQueue( &sem->wait_queue, THREAD_ID_TO_THDB(thread_id) );
}


/***********************************************************************
 *           SEMAPHORE_Destroy
 */
static void SEMAPHORE_Destroy( K32OBJ *obj )
{
    SEMAPHORE *sem = (SEMAPHORE *)obj;
    assert( obj->type == K32OBJ_SEMAPHORE );
    /* There cannot be any thread on the list since the ref count is 0 */
    assert( sem->wait_queue == NULL );
    obj->type = K32OBJ_UNKNOWN;
    HeapFree( SystemHeap, 0, sem );
}
