📄 osapi_semaphore.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 + -