diff --git a/src/libCom/osi/epicsMutex.cpp b/src/libCom/osi/epicsMutex.cpp index 894ff00d4..b60873ec6 100644 --- a/src/libCom/osi/epicsMutex.cpp +++ b/src/libCom/osi/epicsMutex.cpp @@ -150,22 +150,6 @@ void epicsMutex::lock () } } -bool epicsMutex::lock ( double timeOut ) // X aCC 361 - epicsThrows (( epicsMutex::invalidMutex )) -{ - epicsMutexLockStatus status = epicsMutexLockWithTimeout ( this->id, timeOut ); - if ( status == epicsMutexLockOK ) { - return true; - } - else if ( status == epicsMutexLockTimeout ) { - return false; - } - else { - throw invalidMutex (); - return false; // never here, compiler is happy - } -} - bool epicsMutex::tryLock () // X aCC 361 epicsThrows (( epicsMutex::invalidMutex )) { diff --git a/src/libCom/osi/epicsMutex.h b/src/libCom/osi/epicsMutex.h index f7f3fa8f7..14101f1ca 100644 --- a/src/libCom/osi/epicsMutex.h +++ b/src/libCom/osi/epicsMutex.h @@ -37,8 +37,6 @@ public: epicsThrows (( invalidMutex )); void unlock () epicsThrows (()); - bool lock ( double timeOut ) /* true if successful */ - epicsThrows (( invalidMutex )); bool tryLock () /* true if successful */ epicsThrows (( invalidMutex )); private: @@ -67,8 +65,6 @@ epicsShareFunc void epicsShareAPI epicsMutexUnlock(epicsMutexId id); epicsShareFunc epicsMutexLockStatus epicsShareAPI epicsMutexLock( epicsMutexId id); #define epicsMutexMustLock(ID) assert((epicsMutexLock((ID))==epicsMutexLockOK)) -epicsShareFunc epicsMutexLockStatus epicsShareAPI epicsMutexLockWithTimeout( - epicsMutexId id, double timeOut); epicsShareFunc epicsMutexLockStatus epicsShareAPI epicsMutexTryLock( epicsMutexId id); epicsShareFunc void epicsShareAPI epicsMutexShow( diff --git a/src/libCom/osi/os/RTEMS/osdMutex.c b/src/libCom/osi/os/RTEMS/osdMutex.c index fb644edd2..ff19828dc 100644 --- a/src/libCom/osi/os/RTEMS/osdMutex.c +++ b/src/libCom/osi/os/RTEMS/osdMutex.c @@ -153,51 +153,6 @@ epicsMutexLockStatus epicsMutexLock(epicsMutexId id) #endif } -epicsMutexLockStatus epicsMutexLockWithTimeout( - epicsMutexId id, double timeOut) -{ -#ifdef RTEMS_FAST_MUTEX - Semaphore_Control *the_semaphore = (Semaphore_Control *)id; - ISR_Level level; - boolean wait; - rtems_interval delay; - extern double rtemsTicksPerSecond_double; - - SEMSTAT(1) - if (timeOut <= 0.0) { - wait = FALSE; - delay = 0; - } - else { - wait = TRUE; - delay = timeOut * rtemsTicksPerSecond_double; - if (delay == 0) - delay++; - } - _ISR_Disable( level ); - _CORE_mutex_Seize( - &the_semaphore->Core_control.mutex, - the_semaphore->Object.id, - wait, - delay, - level - ); - if (_Thread_Executing->Wait.return_code == 0) - return epicsMutexLockOK; - else - return epicsMutexLockError; -#else - epicsEventWaitStatus status; - SEMSTAT(1) - status = epicsEventWaitWithTimeout(id,timeOut); - return((status==epicsEventWaitOK - ? epicsMutexLockOK - : (status==epicsEventWaitTimeout) - ? epicsMutexLockTimeout - : epicsMutexLockError)); -#endif -} - epicsMutexLockStatus epicsMutexTryLock(epicsMutexId id) { #ifdef RTEMS_FAST_MUTEX diff --git a/src/libCom/osi/os/WIN32/osdMutex.c b/src/libCom/osi/os/WIN32/osdMutex.c index 66dc25e7d..7a0d80c34 100644 --- a/src/libCom/osi/os/WIN32/osdMutex.c +++ b/src/libCom/osi/os/WIN32/osdMutex.c @@ -154,92 +154,6 @@ epicsShareFunc epicsMutexLockStatus epicsShareAPI return epicsMutexLockOK; } -/* - * epicsMutexLockWithTimeout () - */ -epicsShareFunc epicsMutexLockStatus epicsShareAPI - epicsMutexLockWithTimeout ( epicsMutexId pSem, double timeOut ) -{ - static const unsigned mSecPerSec = 1000u; - - if ( thisIsNT ) { - DWORD begin = GetTickCount (); - - if ( ! TryEnterCriticalSection ( &pSem->os.cs.mutex ) ) { - DWORD delay = 0; - DWORD tmo; - - if ( timeOut <= 0.0 ) { - tmo = 1; - } - else if ( timeOut >= INFINITE / mSecPerSec ) { - tmo = INFINITE - 1; - } - else { - tmo = ( DWORD ) ( ( timeOut * mSecPerSec ) + 0.5 ); - if ( tmo == 0 ) { - tmo = 1; - } - } - - assert ( pSem->os.cs.waitingCount < 0x7FFFFFFF ); - // this causes a cache flush on MP systems - InterlockedIncrement ( &pSem->os.cs.waitingCount ); - - while ( ! TryEnterCriticalSection ( &pSem->os.cs.mutex ) ) { - DWORD current; - - WaitForSingleObject ( pSem->os.cs.unlockSignal, tmo - delay ); - - current = GetTickCount (); - if ( current >= begin ) { - delay = current - begin; - } - else { - delay = ( 0xffffffff - begin ) + current + 1; - } - - if ( delay >= tmo ) { - assert ( pSem->os.cs.waitingCount > 0 ); - // this causes a cache flush on MP systems - InterlockedDecrement ( &pSem->os.cs.waitingCount ); - return epicsMutexLockTimeout; - } - } - - assert ( pSem->os.cs.waitingCount > 0 ); - // this causes a cache flush on MP systems - InterlockedDecrement ( &pSem->os.cs.waitingCount ); - } - } - else { - DWORD tmo; - DWORD status; - if ( timeOut <= 0.0 ) { - tmo = 1u; - } - else if ( timeOut >= INFINITE / mSecPerSec ) { - tmo = INFINITE - 1; - } - else { - tmo = ( DWORD ) ( ( timeOut * mSecPerSec ) + 0.5 ); - if ( tmo == 0 ) { - tmo = 1; - } - } - status = WaitForSingleObject ( pSem->os.mutex, tmo ); - if ( status != WAIT_OBJECT_0 ) { - if ( status == WAIT_TIMEOUT ) { - return epicsMutexLockTimeout; - } - else { - return epicsMutexLockError; - } - } - } - return epicsMutexLockOK; -} - /* * epicsMutexTryLock () */ diff --git a/src/libCom/osi/os/posix/osdMutex.c b/src/libCom/osi/os/posix/osdMutex.c index fc50ef0b7..1930e7f9a 100644 --- a/src/libCom/osi/os/posix/osdMutex.c +++ b/src/libCom/osi/os/posix/osdMutex.c @@ -25,11 +25,104 @@ #include "epicsTime.h" #include "errlog.h" #include "epicsAssert.h" + +#define checkStatus(status,message) \ +if((status)) { \ + errlogPrintf("%s failed: error %s\n",(message),strerror((status)));} + +#define checkStatusQuit(status,message,method) \ +if(status) { \ + errlogPrintf("%s failed: error %s\n",(message),strerror((status))); \ + cantProceed((method)); \ +} /* Until these can be demonstrated to work leave them undefined*/ +/* On solaris 8 _POSIX_THREAD_PRIO_INHERIT fails*/ #undef _POSIX_THREAD_PROCESS_SHARED #undef _POSIX_THREAD_PRIO_INHERIT +/* Two completely different implementations are provided below + * If support is available for PTHREAD_MUTEX_RECURSIVE then + * only pthread_mutex is used. + * If support is not available for PTHREAD_MUTEX_RECURSIVE then + * a much more complicated solution is required + */ + +#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE)>=500 +typedef struct epicsMutexOSD { + pthread_mutexattr_t mutexAttr; + pthread_mutex_t lock; +}epicsMutexOSD; + +epicsMutexId epicsMutexOsdCreate(void) { + epicsMutexOSD *pmutex; + int status; + + pmutex = callocMustSucceed(1,sizeof(*pmutex),"epicsMutexOsdCreate"); + status = pthread_mutexattr_init(&pmutex->mutexAttr); + checkStatusQuit(status,"pthread_mutexattr_init","epicsMutexOsdCreate"); +#if defined _POSIX_THREAD_PRIO_INHERIT + status = pthread_mutexattr_setprotocol( + &pmutex->mutexAttr,PTHREAD_PRIO_INHERIT); + if(errVerbose) checkStatus(status,"pthread_mutexattr_setprotocal"); +#endif /*_POSIX_THREAD_PRIO_INHERIT*/ + status = pthread_mutexattr_settype(&pmutex->mutexAttr,PTHREAD_MUTEX_RECURSIVE); + if(errVerbose) checkStatus(status,"pthread_mutexattr_settype"); + status = pthread_mutex_init(&pmutex->lock,&pmutex->mutexAttr); + checkStatusQuit(status,"pthread_mutex_init","epicsMutexOsdCreate"); + return((epicsMutexId)pmutex); +} + +void epicsMutexOsdDestroy(epicsMutexId pmutex) +{ + int status; + + status = pthread_mutex_destroy(&pmutex->lock); + checkStatus(status,"pthread_mutex_destroy"); + status = pthread_mutexattr_destroy(&pmutex->mutexAttr); + checkStatus(status,"pthread_mutexattr_destroy"); + free(pmutex); +} + +void epicsMutexUnlock(epicsMutexId pmutex) +{ + int status; + + status = pthread_mutex_unlock(&pmutex->lock); + checkStatusQuit(status,"pthread_mutex_unlock","epicsMutexUnlock"); +} + +epicsMutexLockStatus epicsMutexLock(epicsMutexId pmutex) +{ + pthread_t tid = pthread_self(); + int status; + + if(!pmutex || !tid) return(epicsMutexLockError); + status = pthread_mutex_lock(&pmutex->lock); + checkStatusQuit(status,"pthread_mutex_lock","epicsMutexLock"); + return(epicsMutexLockOK); +} + +epicsMutexLockStatus epicsMutexTryLock(epicsMutexId pmutex) +{ + pthread_t tid = pthread_self(); + epicsMutexLockStatus status; + int pthreadStatus; + + pthreadStatus = pthread_mutex_trylock(&pmutex->lock); + if(pthreadStatus!=0) { + if(pthreadStatus==EBUSY) return(epicsMutexLockTimeout); + checkStatusQuit(pthreadStatus,"pthread_mutex_lock","epicsMutexTryLock"); + } + return(epicsMutexLockOK); +} + +void epicsMutexShow(epicsMutexId pmutex,unsigned int level) +{ +} + +#else /*defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE)>=500 */ + typedef struct epicsMutexOSD { pthread_mutexattr_t mutexAttr; pthread_mutex_t lock; @@ -41,17 +134,7 @@ typedef struct epicsMutexOSD { int owned; /* TRUE | FALSE */ pthread_t ownerTid; }epicsMutexOSD; - -#define checkStatus(status,message) \ -if((status)) { \ - errlogPrintf("%s failed: error %s\n",(message),strerror((status)));} -#define checkStatusQuit(status,message,method) \ -if(status) { \ - errlogPrintf("%s failed: error %s\n",(message),strerror((status))); \ - cantProceed((method)); \ -} - epicsMutexId epicsMutexOsdCreate(void) { epicsMutexOSD *pmutex; int status; @@ -117,7 +200,7 @@ void epicsMutexUnlock(epicsMutexId pmutex) status = pthread_mutex_unlock(&pmutex->lock); checkStatusQuit(status,"pthread_mutex_unlock","epicsMutexUnlock"); } - + epicsMutexLockStatus epicsMutexLock(epicsMutexId pmutex) { pthread_t tid = pthread_self(); @@ -135,33 +218,6 @@ epicsMutexLockStatus epicsMutexLock(epicsMutexId pmutex) checkStatusQuit(status,"pthread_mutex_unlock","epicsMutexLock"); return(epicsMutexLockOK); } - -epicsMutexLockStatus epicsMutexLockWithTimeout(epicsMutexId pmutex, double timeout) -{ - pthread_t tid = pthread_self(); - struct timespec wakeTime; - int status,unlockStatus; - - convertDoubleToWakeTime(timeout,&wakeTime); - status = pthread_mutex_lock(&pmutex->lock); - checkStatusQuit(status,"pthread_mutex_lock","epicsMutexLockWithTimeout"); - while(pmutex->owned && !pthread_equal(pmutex->ownerTid,tid)) { - status = pthread_cond_timedwait( - &pmutex->waitToBeOwner,&pmutex->lock,&wakeTime); - if(!status) break; - } - if(status==0) { - pmutex->ownerTid = tid; - pmutex->owned = 1; - pmutex->count++; - } - unlockStatus = pthread_mutex_unlock(&pmutex->lock); - checkStatusQuit(unlockStatus,"pthread_mutex_lock","epicsMutexLockWithTimeout"); - if(status==0) return(epicsMutexLockOK); - if(status==ETIMEDOUT) return(epicsMutexLockTimeout); - checkStatusQuit(status,"pthread_cond_timedwait","epicsMutexLockWithTimeout"); - return(epicsMutexLockError); -} epicsMutexLockStatus epicsMutexTryLock(epicsMutexId pmutex) { @@ -190,3 +246,4 @@ void epicsMutexShow(epicsMutexId pmutex,unsigned int level) printf("ownerTid %p count %d owned %d\n", (void *)pmutex->ownerTid,pmutex->count,pmutex->owned); } +#endif /*defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE)>=500 */ diff --git a/src/libCom/osi/os/vxWorks/osdMutex.c b/src/libCom/osi/os/vxWorks/osdMutex.c index 976e34f97..9f79e9f07 100644 --- a/src/libCom/osi/os/vxWorks/osdMutex.c +++ b/src/libCom/osi/os/vxWorks/osdMutex.c @@ -33,24 +33,6 @@ void epicsMutexOsdDestroy(epicsMutexId id) semDelete((SEM_ID)id); } -epicsMutexLockStatus epicsMutexLockWithTimeout( - epicsMutexId id, double timeOut) -{ - int status; - int ticks; - - if(timeOut<=0.0) { - ticks = 0; - } else { - ticks = timeOut*sysClkRateGet(); - if(ticks<=0) ticks = 1; - } - status = semTake((SEM_ID)id,ticks); - if(status==OK) return(epicsMutexLockOK); - if(errno==S_objLib_OBJ_TIMEOUT) return(epicsMutexLockTimeout); - return(epicsMutexLockError); -} - epicsMutexLockStatus epicsMutexTryLock(epicsMutexId id) { int status; diff --git a/src/libCom/test/epicsMutexTest.cpp b/src/libCom/test/epicsMutexTest.cpp index 3ad8986ed..d3d2fb68d 100644 --- a/src/libCom/test/epicsMutexTest.cpp +++ b/src/libCom/test/epicsMutexTest.cpp @@ -265,9 +265,6 @@ extern "C" void epicsMutexTest(int nthreads,int verbose) printf("calling epicsMutexLock(mutex) time %ld\n",time(&tp)); status = epicsMutexLock(mutex); if(status) printf("status %d\n",status); - printf("calling epicsMutexLockWithTimeout(mutex,2.0) time %ld\n",time(&tp)); - status = epicsMutexLockWithTimeout(mutex,2.0); - if(status) printf("status %d\n",status); printf("calling epicsMutexTryLock(mutex) time %ld\n",time(&tp)); status = epicsMutexTryLock(mutex); if(status) printf("status %d\n",status); @@ -276,8 +273,6 @@ extern "C" void epicsMutexTest(int nthreads,int verbose) epicsMutexUnlock(mutex); printf("calling epicsMutexUnlock() time %ld\n",time(&tp)); epicsMutexUnlock(mutex); - printf("calling epicsMutexUnlock() time %ld\n",time(&tp)); - epicsMutexUnlock(mutex); epicsMutexShow(mutex,1); if(nthreads<=0) {