installed compromise mutex solution which implements a timeout, but

still uses the more efficent WIN32 critical section primitive
This commit is contained in:
Jeff Hill
2000-10-10 22:14:42 +00:00
parent f00cccc76e
commit 4af28c5ad6

View File

@@ -29,6 +29,8 @@
* Argonne National Laboratory
*/
#include <limits.h>
#ifndef VC_EXTRALEAN
# define VC_EXTRALEAN
#endif
@@ -36,6 +38,7 @@
# define WIN32_LEAN_AND_MEAN
#endif
/* including less than this causes conflicts with winsock2.h :-( */
#define _WIN32_WINNT 0x400
#include <winsock2.h>
#define epicsExportSharedSymbols
@@ -50,36 +53,33 @@ typedef struct binarySem {
HANDLE handle;
}binarySem;
typedef struct mutexSem {
HANDLE handle;
}mutexSem;
/*
* semBinaryCreate ()
*/
epicsShareFunc semBinaryId epicsShareAPI semBinaryCreate (int initialState)
epicsShareFunc semBinaryId epicsShareAPI semBinaryCreate ( semInitialState initialState )
{
binarySem *pSem;
pSem = malloc ( sizeof (*pSem) );
if (pSem) {
pSem->handle = CreateEvent (NULL, FALSE, initialState?TRUE:FALSE, NULL);
if (pSem->handle==0) {
free (pSem);
pSem = malloc ( sizeof ( *pSem ) );
if ( pSem ) {
pSem->handle = CreateEvent ( NULL, FALSE, initialState?TRUE:FALSE, NULL );
if ( pSem->handle == 0 ) {
free ( pSem );
pSem = 0;
}
}
return (semBinaryId) pSem;
return ( semBinaryId ) pSem;
}
/*
* semBinaryMustCreate ()
*/
epicsShareFunc semBinaryId epicsShareAPI semBinaryMustCreate (int initialState)
epicsShareFunc semBinaryId epicsShareAPI semBinaryMustCreate ( semInitialState initialState )
{
semBinaryId id = semBinaryCreate (initialState);
assert (id);
semBinaryId id = semBinaryCreate ( initialState );
assert ( id );
return id;
}
@@ -172,6 +172,12 @@ epicsShareFunc void epicsShareAPI semBinaryShow (semBinaryId id, unsigned level)
{
}
#if 0
typedef struct mutexSem {
HANDLE handle;
}mutexSem;
/*
* semMutexCreate ()
@@ -290,3 +296,276 @@ epicsShareFunc semTakeStatus epicsShareAPI semMutexTakeNoWait (semMutexId id)
epicsShareFunc void epicsShareAPI semMutexShow (semMutexId id, unsigned level)
{
}
#elif 0
typedef struct mutexSem {
CRITICAL_SECTION cs;
} mutexSem;
/*
* semMutexCreate ()
*/
epicsShareFunc semMutexId epicsShareAPI semMutexCreate ( void )
{
mutexSem *pSem;
pSem = malloc ( sizeof (*pSem) );
if ( pSem ) {
InitializeCriticalSection ( &pSem->cs );
}
return (semMutexId) pSem;
}
/*
* semMutexMustCreate ()
*/
epicsShareFunc semBinaryId epicsShareAPI semMutexMustCreate ()
{
semMutexId id = semMutexCreate ();
assert ( id );
return id;
}
/*
* semMutexDestroy ()
*/
epicsShareFunc void epicsShareAPI semMutexDestroy ( semMutexId id )
{
mutexSem *pSem = ( mutexSem * ) id;
DeleteCriticalSection ( &pSem->cs );
free ( pSem );
}
/*
* semMutexGive ()
*/
epicsShareFunc void epicsShareAPI semMutexGive ( semMutexId id )
{
mutexSem *pSem = ( mutexSem * ) id;
LeaveCriticalSection ( &pSem->cs );
}
/*
* semMutexTake ()
*/
epicsShareFunc semTakeStatus epicsShareAPI semMutexTake ( semMutexId id )
{
mutexSem *pSem = ( mutexSem * ) id;
EnterCriticalSection ( &pSem->cs );
return semTakeOK;
}
/*
* semMutexTakeTimeout ()
*/
epicsShareFunc semTakeStatus epicsShareAPI semMutexTakeTimeout ( semMutexId id, double timeOut )
{
mutexSem *pSem = ( mutexSem * ) id;
EnterCriticalSection ( &pSem->cs );
return semTakeOK;
}
/*
* semMutexTakeNoWait ()
*/
epicsShareFunc semTakeStatus epicsShareAPI semMutexTakeNoWait ( semMutexId id )
{
mutexSem *pSem = ( mutexSem * ) id;
if ( TryEnterCriticalSection ( &pSem->cs ) ) {
return semTakeOK;
}
else {
return semTakeTimeout;
}
}
/*
* semMutexShow ()
*/
epicsShareFunc void epicsShareAPI semMutexShow ( semMutexId id, unsigned level )
{
}
#else
typedef struct mutexSem {
CRITICAL_SECTION cs;
DWORD threadId;
HANDLE unlockSignal;
unsigned count;
} mutexSem;
/*
* semMutexCreate ()
*/
epicsShareFunc semMutexId epicsShareAPI semMutexCreate ( void )
{
mutexSem *pSem;
pSem = malloc ( sizeof (*pSem) );
if ( pSem ) {
pSem->unlockSignal = CreateEvent ( NULL, FALSE, FALSE, NULL );
if ( pSem->unlockSignal == 0 ) {
free ( pSem );
pSem = 0;
}
else {
InitializeCriticalSection ( &pSem->cs );
pSem->threadId = 0;
pSem->count = 0u;
}
}
return (semMutexId) pSem;
}
/*
* semMutexMustCreate ()
*/
epicsShareFunc semBinaryId epicsShareAPI semMutexMustCreate ()
{
semMutexId id = semMutexCreate ();
assert ( id );
return id;
}
/*
* semMutexDestroy ()
*/
epicsShareFunc void epicsShareAPI semMutexDestroy ( semMutexId id )
{
mutexSem *pSem = ( mutexSem * ) id;
DeleteCriticalSection ( &pSem->cs );
CloseHandle ( pSem->unlockSignal );
free ( pSem );
}
/*
* semMutexGive ()
*/
epicsShareFunc void epicsShareAPI semMutexGive ( semMutexId id )
{
mutexSem *pSem = ( mutexSem * ) id;
unsigned signalNeeded;
DWORD status;
EnterCriticalSection ( &pSem->cs );
//assert ( pSem->threadId == GetCurrentThreadId () );
assert ( pSem->count > 0u );
pSem->count--;
if ( pSem->count == 0 ) {
pSem->threadId = 0;
signalNeeded = 1;
}
else {
signalNeeded = 0;
}
LeaveCriticalSection ( &pSem->cs );
if ( signalNeeded ) {
status = SetEvent ( pSem->unlockSignal );
assert ( status );
}
}
/*
* semMutexTake ()
*/
epicsShareFunc semTakeStatus epicsShareAPI semMutexTake ( semMutexId id )
{
DWORD thisThread = GetCurrentThreadId ();
mutexSem *pSem = ( mutexSem * ) id;
EnterCriticalSection ( &pSem->cs );
while ( pSem->count && pSem->threadId != thisThread ) {
DWORD status;
LeaveCriticalSection ( &pSem->cs );
status = WaitForSingleObject ( pSem->unlockSignal, INFINITE );
if ( status == WAIT_TIMEOUT ) {
return semTakeTimeout;
}
EnterCriticalSection ( &pSem->cs );
}
pSem->threadId = thisThread;
assert ( pSem->count != UINT_MAX );
pSem->count++;
LeaveCriticalSection ( &pSem->cs );
return semTakeOK;
}
/*
* semMutexTakeTimeout ()
*/
epicsShareFunc semTakeStatus epicsShareAPI semMutexTakeTimeout ( semMutexId id, double timeOut )
{
DWORD thisThread = GetCurrentThreadId ();
mutexSem *pSem = ( mutexSem * ) id;
EnterCriticalSection ( &pSem->cs );
while ( pSem->count && pSem->threadId != thisThread ) {
DWORD tmo;
DWORD status;
LeaveCriticalSection ( &pSem->cs );
tmo = ( DWORD ) ( timeOut * mSecPerSecOsdSem );
status = WaitForSingleObject ( pSem->unlockSignal, tmo );
if ( status == WAIT_TIMEOUT ) {
return semTakeTimeout;
}
EnterCriticalSection ( &pSem->cs );
}
pSem->threadId = thisThread;
assert ( pSem->count != UINT_MAX );
pSem->count++;
LeaveCriticalSection ( &pSem->cs );
return semTakeOK;
}
/*
* semMutexTakeNoWait ()
*/
epicsShareFunc semTakeStatus epicsShareAPI semMutexTakeNoWait ( semMutexId id )
{
DWORD thisThread = GetCurrentThreadId ();
mutexSem *pSem = ( mutexSem * ) id;
EnterCriticalSection ( &pSem->cs );
if ( pSem->count && pSem->threadId != thisThread ) {
LeaveCriticalSection ( &pSem->cs );
return semTakeTimeout;
}
pSem->threadId = thisThread;
assert ( pSem->count != UINT_MAX );
pSem->count++;
LeaveCriticalSection ( &pSem->cs );
return semTakeOK;
}
/*
* semMutexShow ()
*/
epicsShareFunc void epicsShareAPI semMutexShow ( semMutexId id, unsigned level )
{
}
#endif