latest version of osiSem and osiThread
This commit is contained in:
@@ -18,14 +18,17 @@ of this distribution.
|
||||
#include <pthread.h>
|
||||
|
||||
#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",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user