diff --git a/src/libCom/osi/os/posix/osdSem.c b/src/libCom/osi/os/posix/osdSem.c index f2cea340b..c633da711 100644 --- a/src/libCom/osi/os/posix/osdSem.c +++ b/src/libCom/osi/os/posix/osdSem.c @@ -18,14 +18,17 @@ of this distribution. #include #include "osiSem.h" +#include "osiThread.h" #include "cantProceed.h" +#include "tsStamp.h" #include "errlog.h" -typedef struct cond { + +typedef struct binary { + pthread_mutexattr_t attr; pthread_mutex_t mutex; - pthread_cond_t condition; -}cond; +}binary; typedef struct mutex { @@ -36,87 +39,113 @@ typedef struct mutex { int owned; /* TRUE | FALSE */ pthread_t ownerTid; }mutex; - -semId semBinaryCreate(int initialState) + +semBinaryId semBinaryCreate(int initialState) { - cond *pcond; + binary *pbinary; int status; - pcond = callocMustSucceed(1,sizeof(cond),"semBinaryCreate"); - status = pthread_mutex_init(&pcond->mutex,0); + pbinary = callocMustSucceed(1,sizeof(binary),"semBinaryCreate"); + status = pthread_mutexattr_init(&pbinary->attr); + if(status) { + errlogPrintf("pthread_mutexattr_init failed: error %s\n", + strerror(status)); + cantProceed("semBinaryCreate"); + } + status = pthread_mutexattr_setprotocol( + &pbinary->attr,PTHREAD_PROCESS_PRIVATE); +/* For now dont report failure + if(status) { + errlogPrintf("semBinaryCreate pthread_mutexattr_setprotocal " + "failed: error %s\n", + strerror(status)); + } +*/ + status = pthread_mutex_init(&pbinary->mutex,&pbinary->attr); + if(status) { + errlogPrintf("pthread_mutex_init failed: error %s\n", + strerror(status)); + } + status = pthread_mutex_init(&pbinary->mutex,&pbinary->attr); if(status) { errlogPrintf("pthread_mutex_init failed: error %s\n", strerror(status)); cantProceed("semBinaryCreate"); } - status = pthread_cond_init(&pcond->condition,0); - if(status) { - errlogPrintf("pthread_cond_init failed: error %s\n", - strerror(status)); - cantProceed("semBinaryCreate"); - } - return((semId)pcond); + if(initialState==semEmpty) semBinaryTakeNoWait((semBinaryId)pbinary); + return((semBinaryId)pbinary); } -void semBinaryDestroy(semId id) +void semBinaryDestroy(semBinaryId id) { - cond *pcond = (cond *)id; + binary *pbinary = (binary *)id; int status; - status = pthread_mutex_destroy(&pcond->mutex); + status = pthread_mutex_destroy(&pbinary->mutex); if(status) errlogPrintf("pthread_mutex_destroy error %s\n",strerror(status)); - status = pthread_cond_destroy(&pcond->condition); - if(status) errlogPrintf("pthread_cond_destroy error %s\n",strerror(status)); - free(pcond); + status = pthread_mutexattr_destroy(&pbinary->attr); + if(status) errlogPrintf("pthread_mutexattr_destroy error %s\n", + strerror(status)); + free(pbinary); } - -void semBinaryGive(semId id) + +void semBinaryGive(semBinaryId id) { - cond *pcond = (cond *)id; + binary *pbinary = (binary *)id; int status; - status = pthread_cond_signal(&pcond->condition); - if(status) errlogPrintf("pthread_cond_signal error %s\n",strerror(status)); + status = pthread_mutex_unlock(&pbinary->mutex); + if(status) errlogPrintf("pthread_mutex_unlock error %s\n",strerror(status)); } -semTakeStatus semBinaryTake(semId id) +semTakeStatus semBinaryTake(semBinaryId id) { - cond *pcond = (cond *)id; + binary *pbinary = (binary *)id; int status; - status = pthread_cond_wait(&pcond->condition,&pcond->mutex); - if(status) errlogPrintf("pthread_cond_wait error %s\n",strerror(status)); + status = pthread_mutex_lock(&pbinary->mutex); + if(status) errlogPrintf("pthread_mutex_lock error %s\n",strerror(status)); if(status) return(semTakeError); return(semTakeOK); } -semTakeStatus semBinaryTakeTimeout(semId id, double timeOut) +semTakeStatus semBinaryTakeTimeout(semBinaryId id, double timeOut) { - cond *pcond = (cond *)id; - mutex *pmutex = (mutex *)id; - pthread_t tid = pthread_self(); - struct timespec wait; - int status; + binary *pbinary = (binary *)id; + int status; + double waitSoFar=0.0; - wait.tv_sec = timeOut; - wait.tv_nsec = (long)((timeOut - (double)wait.tv_sec) * 1e9); - status = pthread_cond_timedwait( - &pcond->condition,&pcond->mutex,&wait); - if(status==ETIMEDOUT) return(semTakeTimeout); - if(status) errlogPrintf("pthread_cond_wait error %s\n",strerror(status)); - return(0); + while(1) { + status = pthread_mutex_trylock(&pbinary->mutex); + if(!status) return(semTakeOK); + if(status!=EBUSY) { + errlogPrintf("pthread_mutex_lock error %s\n",strerror(status)); + return(semTakeError); + } + threadSleep(1.0); + waitSoFar += 1.0; + if(waitSoFar>=timeOut) break; + } + return(semTakeTimeout); } -semTakeStatus semBinaryTakeNoWait(semId id) +semTakeStatus semBinaryTakeNoWait(semBinaryId id) { - return(semBinaryTakeTimeout(id,0.0)); + binary *pbinary = (binary *)id; + int status; + + status = pthread_mutex_trylock(&pbinary->mutex); + if(!status) return(semTakeOK); + if(status==EBUSY) return(semTakeTimeout); + errlogPrintf("pthread_mutex_lock error %s\n",strerror(status)); + return(semTakeError); } -void semBinaryShow(semId id) +void semBinaryShow(semBinaryId id) { } -semId semMutexCreate(void) { +semMutexId semMutexCreate(void) { mutex *pmutex; int status; @@ -146,10 +175,10 @@ semId semMutexCreate(void) { strerror(status)); cantProceed("semMutexCreate"); } - return((semId)pmutex); + return((semMutexId)pmutex); } -void semMutexDestroy(semId id) +void semMutexDestroy(semMutexId id) { mutex *pmutex = (mutex *)id; int status; @@ -162,12 +191,12 @@ void semMutexDestroy(semId id) if(status) errlogPrintf("pthread_mutexattr_destroy error %s\n",strerror(status)); free(pmutex); } - -void semMutexGive(semId id) + +void semMutexGive(semMutexId id) { mutex *pmutex = (mutex *)id; pthread_mutex_lock(&pmutex->lock); - pmutex->count--; + if(pmutex->count>0) pmutex->count--; if(pmutex->count == 0) { pmutex->owned = 0; pmutex->ownerTid = 0; @@ -175,7 +204,7 @@ void semMutexGive(semId id) } pthread_mutex_unlock(&pmutex->lock); } -semTakeStatus semMutexTake(semId id) +semTakeStatus semMutexTake(semMutexId id) { mutex *pmutex = (mutex *)id; pthread_t tid = pthread_self(); @@ -188,21 +217,31 @@ semTakeStatus semMutexTake(semId id) pmutex->count++; pthread_mutex_unlock(&pmutex->lock); return(0); -} -semTakeStatus semMutexTakeTimeout(semId id, double timeOut) + } +semTakeStatus semMutexTakeTimeout(semMutexId id, double timeOut) { mutex *pmutex = (mutex *)id; pthread_t tid = pthread_self(); struct timespec wait; + struct timespec abstime; + int status; + TS_STAMP stamp; + tsStampGetCurrent(&stamp); + tsStampToTimespec(&abstime, &stamp); wait.tv_sec = timeOut; wait.tv_nsec = (long)((timeOut - (double)wait.tv_sec) * 1e9); - + abstime.tv_sec += wait.tv_sec; + abstime.tv_nsec += wait.tv_nsec; + if(abstime.tv_nsec>1000000000L) { + abstime.tv_nsec -= 1000000000L; + ++abstime.tv_sec; + } pthread_mutex_lock(&pmutex->lock); while(pmutex->owned && !pthread_equal(pmutex->ownerTid,tid)) { int status; status = pthread_cond_timedwait( - &pmutex->waitToBeOwner,&pmutex->lock,&wait); + &pmutex->waitToBeOwner,&pmutex->lock,&abstime); if(!status) break; if(status==ETIMEDOUT) return(semTakeTimeout); return(semTakeError); @@ -213,7 +252,8 @@ semTakeStatus semMutexTakeTimeout(semId id, double timeOut) pthread_mutex_unlock(&pmutex->lock); return(0); } -semTakeStatus semMutexTakeNoWait(semId id) + +semTakeStatus semMutexTakeNoWait(semMutexId id) { mutex *pmutex = (mutex *)id; pthread_t tid = pthread_self(); @@ -229,7 +269,8 @@ semTakeStatus semMutexTakeNoWait(semId id) pthread_mutex_unlock(&pmutex->lock); return(status); } -void semMutexShow(semId id) + +void semMutexShow(semMutexId id) { mutex *pmutex = (mutex *)id; printf("ownerTid %p count %d owned %d\n", diff --git a/src/libCom/osi/os/posix/osdThread.c b/src/libCom/osi/os/posix/osdThread.c index ee62f131e..c3de0db65 100644 --- a/src/libCom/osi/os/posix/osdThread.c +++ b/src/libCom/osi/os/posix/osdThread.c @@ -33,7 +33,7 @@ typedef struct threadInfo { struct sched_param schedParam; THREADFUNC createFunc; void *createArg; - semId suspendSem; + semBinaryId suspendSem; int isSuspended; int maxPriority; int minPriority; @@ -109,6 +109,8 @@ threadId threadCreate(const char *name, pthread_key_create(&getpthreadInfo,0); } pthreadInfo = callocMustSucceed(1,sizeof(threadInfo),"threadCreate"); + pthreadInfo->createFunc = funptr; + pthreadInfo->createArg = parm; status = pthread_attr_init(&pthreadInfo->attr); if(status) { errlogPrintf("pthread_attr_init failed: error %s\n",strerror(status)); @@ -126,8 +128,11 @@ threadId threadCreate(const char *name, errlogPrintf("pthread_attr_setstacksize failed: error %s\n", strerror(status)); } - /* DO WE WANT TO setscope ???? */ - /*pthread_attr_setscope(&pthreadInfo->attr,PTHREAD_SCOPE_SYSTEM);*/ + status = pthread_attr_setscope(&pthreadInfo->attr,PTHREAD_SCOPE_PROCESS); + if(status) { + errlogPrintf("pthread_attr_setscope failed: error %s\n", + strerror(status)); + } pthreadInfo->schedPolicy = SCHED_FIFO; pthreadInfo->maxPriority = sched_get_priority_max(pthreadInfo->schedPolicy); pthreadInfo->minPriority = sched_get_priority_min(pthreadInfo->schedPolicy); @@ -137,7 +142,6 @@ threadId threadCreate(const char *name, if(status) { errlogPrintf("pthread_attr_setschedpolicy failed: error %s\n", strerror(status)); - cantProceed("threadCreate"); } pthreadInfo->schedParam.sched_priority = getOssPriorityValue(pthreadInfo); status = pthread_attr_setschedparam( @@ -145,14 +149,15 @@ threadId threadCreate(const char *name, if(status) { errlogPrintf("pthread_attr_setschedparam failed: error %s\n", strerror(status)); - cantProceed("threadCreate"); } pthreadInfo->suspendSem = semBinaryMustCreate(semFull); status = pthread_create(&pthreadInfo->tid, &pthreadInfo->attr,start_routine,pthreadInfo); if(status) { errlogPrintf("pthread_create failed: error %s\n",strerror(status)); +/* cantProceed("threadCreate"); +*/ } return((threadId)pthreadInfo); } diff --git a/src/libCom/osi/osiSem.h b/src/libCom/osi/osiSem.h index 4e04a9821..4dacc7c77 100644 --- a/src/libCom/osi/osiSem.h +++ b/src/libCom/osi/osiSem.h @@ -9,55 +9,60 @@ extern "C" { #include "shareLib.h" -typedef void *semId; +typedef void *semBinaryId; typedef enum {semTakeOK,semTakeTimeout,semTakeError} semTakeStatus; typedef enum {semEmpty,semFull} semInitialState; -epicsShareFunc semId epicsShareAPI semBinaryCreate(int initialState); -epicsShareFunc INLINE semId epicsShareAPI semBinaryMustCreate (int initialState); -epicsShareFunc void epicsShareAPI semBinaryDestroy(semId id); -epicsShareFunc void epicsShareAPI semBinaryGive(semId id); -epicsShareFunc semTakeStatus epicsShareAPI semBinaryTake(semId id); -epicsShareFunc INLINE void epicsShareAPI semBinaryMustTake (semId id); -epicsShareFunc semTakeStatus epicsShareAPI semBinaryTakeTimeout(semId id, double timeOut); -epicsShareFunc semTakeStatus epicsShareAPI semBinaryTakeNoWait(semId id); -epicsShareFunc void epicsShareAPI semBinaryShow(semId id); +epicsShareFunc semBinaryId epicsShareAPI semBinaryCreate(int initialState); +epicsShareFunc INLINE semBinaryId epicsShareAPI semBinaryMustCreate ( + int initialState); +epicsShareFunc void epicsShareAPI semBinaryDestroy(semBinaryId id); +epicsShareFunc void epicsShareAPI semBinaryGive(semBinaryId id); +epicsShareFunc semTakeStatus epicsShareAPI semBinaryTake(semBinaryId id); +epicsShareFunc INLINE void epicsShareAPI semBinaryMustTake (semBinaryId id); +epicsShareFunc semTakeStatus epicsShareAPI semBinaryTakeTimeout( + semBinaryId id, double timeOut); +epicsShareFunc semTakeStatus epicsShareAPI semBinaryTakeNoWait(semBinaryId id); +epicsShareFunc void epicsShareAPI semBinaryShow(semBinaryId id); -epicsShareFunc semId epicsShareAPI semMutexCreate(void); -epicsShareFunc INLINE semId epicsShareAPI semMutexMustCreate (void); -epicsShareFunc void epicsShareAPI semMutexDestroy(semId id); -epicsShareFunc void epicsShareAPI semMutexGive(semId id); -epicsShareFunc semTakeStatus epicsShareAPI semMutexTake(semId id); -epicsShareFunc INLINE void epicsShareAPI semMutexMustTake(semId id); -epicsShareFunc semTakeStatus epicsShareAPI semMutexTakeTimeout(semId id, double timeOut); -epicsShareFunc semTakeStatus epicsShareAPI semMutexTakeNoWait(semId id); -epicsShareFunc void epicsShareAPI semMutexShow(semId id); +typedef void *semMutexId; +epicsShareFunc semMutexId epicsShareAPI semMutexCreate(void); +epicsShareFunc INLINE semMutexId epicsShareAPI semMutexMustCreate (void); +epicsShareFunc void epicsShareAPI semMutexDestroy(semMutexId id); +epicsShareFunc void epicsShareAPI semMutexGive(semMutexId id); +epicsShareFunc semTakeStatus epicsShareAPI semMutexTake(semMutexId id); +epicsShareFunc INLINE void epicsShareAPI semMutexMustTake(semMutexId id); +epicsShareFunc semTakeStatus epicsShareAPI semMutexTakeTimeout( + semMutexId id, double timeOut); +epicsShareFunc semTakeStatus epicsShareAPI semMutexTakeNoWait(semMutexId id); +epicsShareFunc void epicsShareAPI semMutexShow(semMutexId id); /*NOTES: Mutex semaphores MUST implement recursive locking Mutex semaphores should implement priority inheritance and deletion safe */ -epicsShareFunc INLINE semId epicsShareAPI semBinaryMustCreate (int initialState) +epicsShareFunc INLINE semBinaryId epicsShareAPI semBinaryMustCreate ( + int initialState) { - semId id = semBinaryCreate (initialState); + semBinaryId id = semBinaryCreate (initialState); assert (id); return id; } -epicsShareFunc INLINE void epicsShareAPI semBinaryMustTake (semId id) +epicsShareFunc INLINE void epicsShareAPI semBinaryMustTake (semBinaryId id) { assert (semBinaryTake (id)==semTakeOK); } -epicsShareFunc INLINE semId epicsShareAPI semMutexMustCreate (void) +epicsShareFunc INLINE semMutexId epicsShareAPI semMutexMustCreate (void) { - semId id = semMutexCreate (); + semMutexId id = semMutexCreate (); assert (id); return id; } -epicsShareFunc INLINE void epicsShareAPI semMutexMustTake(semId id) +epicsShareFunc INLINE void epicsShareAPI semMutexMustTake(semMutexId id) { assert (semMutexTake (id)==semTakeOK); }