implement fast mutex for posix; remove epicsMutexLockWithTimeout

This commit is contained in:
Marty Kraimer
2002-12-04 14:36:41 +00:00
parent 4572c756f3
commit faed748404
7 changed files with 95 additions and 212 deletions

View File

@@ -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 ))
{

View File

@@ -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(

View File

@@ -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

View File

@@ -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 ()
*/

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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) {