⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 osapi_semaphore.c

📁 这是DVD中伺服部分的核心代码
💻 C
字号:
/*****************************************************************************
******************************************************************************
**                                                                          **
**  Copyright (c) 2006 Videon Central, Inc.                                 **
**  All rights reserved.                                                    **
**                                                                          **
**  The computer program contained herein contains proprietary information  **
**  which is the property of Videon Central, Inc.  The program may be used  **
**  and/or copied only with the written permission of Videon Central, Inc.  **
**  or in accordance with the terms and conditions stipulated in the        **
**  agreement/contract under which the programs have been supplied.         **
**                                                                          **
******************************************************************************
*****************************************************************************/
/**
 * @file osapi_semaphore.cpp
 *
 * $Revision: 1.9 $ 
 *
 * Operating System API (OSAPI) source file. Provides an abstraction from the
 * operating system.
 *
 * This is the implementation for win32
 *
 */

#include <windows.h>


#include "osapi.h"
#include "DbgPrint.h"
#ifdef DMALLOC
#include "dmalloc.h"
#endif


static OS_STATUS   WIN32SemaphoreCreate( HANDLE* handle, long initialCount, long maxCount, const char* name )
{
    *handle = NULL;

    *handle = CreateSemaphore(
                                NULL,                // security attributes
                                initialCount,        // initial count
                                maxCount,            // maximum count
                                NULL );              // ignore name as VDVD creates multiple semaphores with the same name(which is an error in windows)


    if ( *handle == NULL ) 
    {
        return ( OS_FAILURE );
    }
    else
    if ( GetLastError() == ERROR_ALREADY_EXISTS )
    {
        return ( OS_FAILURE );
    }

    return ( OS_OK );
}



static OS_STATUS   WIN32SemaphoreDelete( HANDLE handle )
{
    BOOL    returnValue;

    returnValue = CloseHandle(handle);
    if (returnValue == 0)
    {
        return ( OS_FAILURE );
    }

    return ( OS_OK );
}



static OS_STATUS   WIN32SemaphoreObtain( HANDLE handle, DWORD timeoutMilliseconds )
{
    DWORD   returnValue;

    returnValue = WaitForSingleObject(handle, timeoutMilliseconds );
    if (returnValue == WAIT_FAILED)
    {
        return ( OS_FAILURE );
    }

    if ( returnValue == WAIT_TIMEOUT ) 
    {
        return ( OS_TIMEOUT ) ;
    }
    
    return ( OS_OK );
}



static OS_STATUS   WIN32SemaphoreRelease( HANDLE handle )
{
    DWORD   returnValue;

    returnValue = ReleaseSemaphore(handle, +1, NULL);
    if (returnValue == 0)
    {
        return ( OS_FAILURE );
    }

    return ( OS_OK );
}




/* MACROS AND DEFINES */
#define DBG_OSAPI DBG_ERROR
#define DBG_ON(x) (DBG_OSAPI >= x)


#define MAX_NAME_SIZE MAX_PATH
typedef struct tagSemaphoreRecord           /* prefix: sem */
{
    ULONG           ulSemType;
    char            strName[MAX_NAME_SIZE];
    ULONG           ulCount;
    ULONG           ulMaxCount;
    HANDLE          handle;                 /* Critical sections */

} OS_SEMAPHORE;


OS_SEM_ID OS_SemBCreateNamed(int iOSOptions, OS_SEM_B_STATE semsInitialState, char *strName)
{
    OS_STATUS       status;
    OS_SEMAPHORE*   psemRecord = NULL;

    (void)iOSOptions;

    /* Check the validity of the initial semaphore state */
    if ( (semsInitialState != OS_SEM_EMPTY) && (semsInitialState != OS_SEM_FULL) )
    {
        DbgPrint(("OS_SemBCreate: Invalid initial state (%d)!\n", semsInitialState));
        goto error;
    }

    /* Allocate a record for the semaphore */
    psemRecord = (OS_SEMAPHORE *)OS_MemAlloc(sizeof(OS_SEMAPHORE));
    if (psemRecord == NULL)
    {
        DbgPrint(("OS_SemBCreate: Could not allocate semaphore record!\n"));
        goto error;
    }

    memset(psemRecord, 0, sizeof(OS_SEMAPHORE) );

    /* Set the semaphore type as binary */
    psemRecord->ulSemType = OS_SEM_BINARY;

    /* Set maximum to 1  */
    psemRecord->ulMaxCount = 1;

    /* Set count to the parameter */
    psemRecord->ulCount = semsInitialState;

    if ( strName != NULL ) 
    {
        strncpy(psemRecord->strName, strName, MAX_NAME_SIZE);
    }
    else
    {
        psemRecord->strName[0] = 0;
    }


    status = WIN32SemaphoreCreate( &psemRecord->handle, semsInitialState, 1, psemRecord->strName );
    if (status != OS_OK ) 
    {
        DbgPrint(("OS_SemBCreate: WIN32SemaphoreCreate failed"));
        goto error;
    }


    /* Return a handle to the binary semaphore */
    return (OS_SEM_ID)psemRecord;

error:
    if (NULL != psemRecord)
    {
        OS_MemFree(psemRecord);
    }
    return (0);
}



OS_SEM_ID OS_SemBCreate(int iOSOptions, OS_SEM_B_STATE semsInitialState )
{
    return ( OS_SemBCreateNamed(iOSOptions, semsInitialState, NULL) );
}



OS_SEM_ID OS_SemCCreateNamed(int iOSOptions, int iInitialCount, char *strName)
{
    OS_STATUS       status;
    OS_SEMAPHORE*   psemRecord = NULL;

    (void)iOSOptions;

    /* Check the validity of the given initial count */
    if (iInitialCount < 0)
    {
        DbgPrint(("OS_SemCCreate: Invalid initial count (%d)!\n", iInitialCount));
        goto error;
    }

    /* Allocate a record for the semaphore */
    psemRecord = (OS_SEMAPHORE *)OS_MemAlloc(sizeof(OS_SEMAPHORE));
    if (psemRecord == NULL)
    {
        DbgPrint(("OS_SemCCreate: Could not allocate semaphore record!\n"));
        goto error;
    }

    /* Set the semaphore type as counting */
    psemRecord->ulSemType = OS_SEM_COUNTING;

    /* Set maximum count to some large number... */
    psemRecord->ulMaxCount = 32678;

    /* Set count to the parameter */
    psemRecord->ulCount = iInitialCount;

    if ( strName != NULL ) 
    {
        strncpy(psemRecord->strName, strName, MAX_NAME_SIZE);
    }
    else
    {
        psemRecord->strName[0] = 0;
    }


    status = WIN32SemaphoreCreate( &psemRecord->handle, iInitialCount, psemRecord->ulMaxCount, psemRecord->strName );
    if (status != OS_OK )
    {
        DbgPrint(("OS_SemBCreate: WIN32SemaphoreCreate failed"));
        goto error;
    }

    /* Return a handle to the counting semaphore */
    return (OS_SEM_ID)psemRecord;

error:
    if (NULL != psemRecord)
    {
        OS_MemFree(psemRecord);
    }
    return (0);
}



OS_SEM_ID OS_SemCCreate(int iOSOptions, int iInitialCount)
{
    return ( OS_SemCCreateNamed( iOSOptions, iInitialCount, NULL ) );
}



#if defined(NDEBUG)
OS_STATUS OS_SemDelete(OS_SEM_ID semId)
#else
OS_STATUS OS_SemDeleteDbg(OS_SEM_ID semId, char *srcFile, int srcLine)
#endif
{
    OS_STATUS   status;

    /* Cast the given semaphore identifier to a semaphore record */
    OS_SEMAPHORE *psemRecord = (OS_SEMAPHORE *)semId;

    if (semId == 0)
    {
        #if defined(NDEBUG)
        #else
            DbgPrint(("%s: BAD POINTER.  Called by %s:%u\n", __FUNCTION__, srcFile, srcLine));
        #endif
        return (OS_FAILURE);
    }

    /* release all wait states */
    OS_SemFlush(semId);


    status = WIN32SemaphoreDelete( psemRecord->handle );
    if (status == OS_FAILURE)
    {
        DbgPrint(("OS_SemDelete: WIN32SemaphoreDelete failed"));
        return (OS_FAILURE);
    }


    /* Delete the semaphore record */
    OS_MemFree(psemRecord);

    /* Return success */
    return (OS_OK);
}



OS_STATUS OS_SemFlush(OS_SEM_ID semId)
{
    OS_STATUS    status      = OS_OK;

    /* Check the validity of the semaphore */
    if (0 == semId)
    {
        DbgPrint(("OS_SemFlush: BAD POINTER\n"));
        return (OS_FAILURE);
    }

    // unblock all threads waiting on this semaphore
    // unnecessary, windows is smart enough to let you get the semaphore if task ends that has obtained it

    return (status);
}







static int ConvertTimeoutToMilliseconds( int timeout_in_ticks )
{
    uint64 answer;

    answer = (uint64)timeout_in_ticks;
    answer = answer * 1000;
    answer = answer / OS_GetTicksPerSecond();

    return (int)answer;
}


#if defined(NDEBUG)
OS_STATUS OS_SemTake(OS_SEM_ID semId, int iTimeout)
#else
OS_STATUS OS_SemTakeDbg(OS_SEM_ID semId, int iTimeout, char *srcFile, int srcLine)
#endif
{
    OS_STATUS       status;
    int iRet                 = OS_OK;
    OS_SEMAPHORE*   psemRecord = (OS_SEMAPHORE *)semId;

    /* Check the validity of the semaphore */
    if (semId == 0)
    {
        #if defined(NDEBUG)
        #else
            DbgPrint(("%s: BAD POINTER.  Called by %s:%u\n", __FUNCTION__, srcFile, srcLine));
        #endif
        goto error_handler;
    }

    /* Check the validity of the given timeout value */
    if (iTimeout < OS_WAIT_FOREVER)
    {
        DbgPrint(("%s: Invalid timeout value (%d)!\n", __FUNCTION__, iTimeout));
        goto error_handler;
    }


    if (OS_WAIT_FOREVER == iTimeout)
    {
        status = WIN32SemaphoreObtain( psemRecord->handle, INFINITE );
        if (status != OS_OK)
        {
            DbgPrint(("OS_SemTake: WIN32SemaphoreObtain\n" ));
            iRet = OS_FAILURE;
        }
    }
    else
    {

        status = WIN32SemaphoreObtain( psemRecord->handle, ConvertTimeoutToMilliseconds(iTimeout) );
        if (status != OS_OK)
        {
            if ( status == OS_TIMEOUT ) 
            {
                iRet = OS_TIMEOUT;
            }
            else
            {
                DbgPrint(("OS_SemTake: WIN32SemaphoreObtain failed\n"));
                iRet = OS_FAILURE;
            }
        }
     }


    if (( iRet == OS_OK ) && (psemRecord->ulCount > 0))
    {
        psemRecord->ulCount--;
    }

    /* Return status */
    return iRet;

error_handler:

    /* Return failure */
    return (OS_FAILURE);
}








#if defined(NDEBUG)
OS_STATUS OS_SemGive(OS_SEM_ID semId)
#else
OS_STATUS OS_SemGiveDbg(OS_SEM_ID semId, char *srcFile, int srcLine)
#endif
{
    OS_STATUS       status;
    OS_SEMAPHORE*   psemRecord = (OS_SEMAPHORE *)semId;


    /* Check the validity of the semaphore */
    if (semId == 0)
    {
        #if defined(NDEBUG)
        #else
            DbgPrint(("%s: BAD POINTER.  Called by %s:%u\n", __FUNCTION__, srcFile, srcLine));
        #endif
        goto error_handler;
    }


    /* If the semaphore is binary and the count is 1, return an error */
    if (psemRecord->ulSemType == OS_SEM_BINARY)
    {
        if (psemRecord->ulCount == 1)
        {
            return ( OS_SEM_FULL );
            goto error_handler;
        }
    }

    /* Increment the semaphore count */
    psemRecord->ulCount++;

    /* wake one waiting thread */
    status = WIN32SemaphoreRelease( psemRecord->handle );
    if (status != OS_OK)
    {
        DbgPrint(("%s: WIN32SemaphoreRelease failed\n",__FUNCTION__));
        goto error_handler;
    }

    /* Return successfully */
    return OS_OK;

error_handler:

    /* Return failure */
    return (OS_FAILURE);
}






/**
 * OS Semaphore Take function.
 *
 * @param
 *    semId - semaphore identifier
 *
 * @param
 *    ulMilliSeconds - semaphore take timeout value in milliseconds
 *
 * @retval
 *    OS_OK if successful
 *    OS_TIMEOUT if timout
 *    OS_FAILURE if not successful
 */
#if defined(NDEBUG)
OS_STATUS OS_SemTakeMsec(OS_SEM_ID semId, int timeoutInMilliseconds)
#else
OS_STATUS OS_SemTakeMsecDbg(OS_SEM_ID semId, int timeoutInMilliseconds, char *srcFile, int srcLine)
#endif
{
    OS_STATUS       status;
    int iRet                 = OS_OK;
    OS_SEMAPHORE*   psemRecord = (OS_SEMAPHORE *)semId;

    /* Check the validity of the semaphore */
    if (semId == 0)
    {
        #if defined(NDEBUG)
        #else
            DbgPrint(("%s: BAD POINTER.  Called by %s:%u\n", __FUNCTION__, srcFile, srcLine));
        #endif
        goto error_handler;
    }

    /* Check the validity of the given timeout value */
    if (timeoutInMilliseconds < OS_WAIT_FOREVER)
    {
        DbgPrint(("%s: Invalid timeout value (%d)!\n", __FUNCTION__, timeoutInMilliseconds));
        goto error_handler;
    }


    if (OS_WAIT_FOREVER == timeoutInMilliseconds)
    {
        status = WIN32SemaphoreObtain( psemRecord->handle, INFINITE );
        if (status != OS_OK)
        {
            DbgPrint(("OS_SemTake: WIN32SemaphoreObtain\n" ));
            iRet = OS_FAILURE;
        }
    }
    else
    {

        status = WIN32SemaphoreObtain( psemRecord->handle, timeoutInMilliseconds );
        if (status != OS_OK)
        {
            if ( status == OS_TIMEOUT ) 
            {
                iRet = OS_TIMEOUT;
            }
            else
            {
                DbgPrint(("OS_SemTake: WIN32SemaphoreObtain failed\n"));
                iRet = OS_FAILURE;
            }
        }
     }


    if (( iRet == OS_OK ) && (psemRecord->ulCount > 0))
    {
        psemRecord->ulCount--;
    }

    /* Return status */
    return iRet;

error_handler:

    /* Return failure */
    return (OS_FAILURE);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -