diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index b929e4d91..d2d921b35 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -15,6 +15,31 @@ EPICS Base 3.15.0.x releases are not intended for use in production systems.

Changes between 3.14.x and 3.15.0.x

+

+Reworked the epicsEvent C & C++ APIs

+ + +

Enabled histogram record type

@@ -24,7 +49,8 @@ but has now been added along with its associated soft device support. The build system now generates the list of all the record.dbd files in base automatically in src/std/rec/Makefile.

-

Reorganization of src/

+

+Reorganization of src/

Reorganization of subdirectories of src/ to better represent the relation between different parts as described in the following table.

diff --git a/src/libCom/osi/epicsEvent.cpp b/src/libCom/osi/epicsEvent.cpp index 4d3dd4492..04b4a08d0 100644 --- a/src/libCom/osi/epicsEvent.cpp +++ b/src/libCom/osi/epicsEvent.cpp @@ -1,10 +1,9 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found +* EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ @@ -17,6 +16,7 @@ #define epicsExportSharedSymbols #include "epicsEvent.h" #include "epicsStdioRedirect.h" +#include "cantProceed.h" // vxWorks 5.4 gcc fails during compile when I use std::exception using namespace std; @@ -52,49 +52,81 @@ epicsEvent::~epicsEvent () epicsEventDestroy ( this->id ); } -void epicsEvent::signal () +void epicsEvent::trigger () { - epicsEventSignal ( this->id ); + epicsEventStatus status = epicsEventTrigger (this->id); + + if (status != epicsEventOK) { + throw invalidSemaphore (); + } } void epicsEvent::wait () { - epicsEventWaitStatus status; - status = epicsEventWait (this->id); - if (status!=epicsEventWaitOK) { + epicsEventStatus status = epicsEventWait (this->id); + + if (status != epicsEventOK) { throw invalidSemaphore (); } } bool epicsEvent::wait (double timeOut) { - epicsEventWaitStatus status; - status = epicsEventWaitWithTimeout (this->id, timeOut); - if (status==epicsEventWaitOK) { + epicsEventStatus status = epicsEventWaitWithTimeout (this->id, timeOut); + + if (status == epicsEventOK) { return true; - } else if (status==epicsEventWaitTimeout) { + } else if (status == epicsEventWaitTimeout) { return false; - } else { - throw invalidSemaphore (); } - return false; + throw invalidSemaphore (); } bool epicsEvent::tryWait () { - epicsEventWaitStatus status; - status = epicsEventTryWait (this->id); - if (status==epicsEventWaitOK) { + epicsEventStatus status = epicsEventTryWait (this->id); + + if (status == epicsEventOK) { return true; - } else if (status==epicsEventWaitTimeout) { + } else if (status == epicsEventWaitTimeout) { return false; - } else { - throw invalidSemaphore (); } - return false; + throw invalidSemaphore (); } void epicsEvent::show ( unsigned level ) const { epicsEventShow ( this->id, level ); } + + +// epicsEventMust... convenience routines for C code + +extern "C" { + +epicsShareFunc epicsEventId epicsEventMustCreate ( + epicsEventInitialState initialState) +{ + epicsEventId id = epicsEventCreate (initialState); + + if (!id) + cantProceed ("epicsEventMustCreate"); + return id; +} + +epicsShareFunc void epicsEventMustTrigger (epicsEventId id) { + epicsEventStatus status = epicsEventTrigger (id); + + if (status != epicsEventOK) + cantProceed ("epicsEventMustTrigger"); +} + +epicsShareFunc void epicsEventMustWait (epicsEventId id) { + epicsEventStatus status = epicsEventWait (id); + + if (status != epicsEventOK) + cantProceed ("epicsEventMustWait"); +} + +} // extern "C" + diff --git a/src/libCom/osi/epicsEvent.h b/src/libCom/osi/epicsEvent.h index 1bc98a0fd..e77d9a5ce 100644 --- a/src/libCom/osi/epicsEvent.h +++ b/src/libCom/osi/epicsEvent.h @@ -1,25 +1,33 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found +* EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ #ifndef epicsEventh #define epicsEventh -#include "epicsAssert.h" #include "shareLib.h" typedef struct epicsEventOSD *epicsEventId; typedef enum { - epicsEventWaitOK,epicsEventWaitTimeout,epicsEventWaitError -} epicsEventWaitStatus; + epicsEventOK = 0, + epicsEventWaitTimeout, + epicsEventError +} epicsEventStatus; -typedef enum {epicsEventEmpty,epicsEventFull} epicsEventInitialState; +/* Backwards compatibility */ +#define epicsEventWaitStatus epicsEventStatus +#define epicsEventWaitOK epicsEventOK +#define epicsEventWaitError epicsEventError + +typedef enum { + epicsEventEmpty, + epicsEventFull +} epicsEventInitialState; #ifdef __cplusplus @@ -27,42 +35,40 @@ class epicsShareClass epicsEvent { public: epicsEvent ( epicsEventInitialState initial = epicsEventEmpty ); ~epicsEvent (); - void signal (); - void wait (); /* blocks until full */ - bool wait ( double timeOut ); /* false if empty at time out */ - bool tryWait (); /* false if empty */ + void trigger (); + void signal () { this->trigger(); } + void wait (); /* blocks until full */ + bool wait ( double timeOut ); /* false if still empty at time out */ + bool tryWait (); /* false if empty */ void show ( unsigned level ) const; - class invalidSemaphore; /* exception payload */ + class invalidSemaphore; /* exception payload */ private: epicsEvent ( const epicsEvent & ); epicsEvent & operator = ( const epicsEvent & ); epicsEventId id; }; -#endif /*__cplusplus */ - -#ifdef __cplusplus extern "C" { #endif /*__cplusplus */ -epicsShareFunc epicsEventId epicsShareAPI epicsEventCreate( +epicsShareFunc epicsEventId epicsEventCreate( epicsEventInitialState initialState); -epicsShareFunc epicsEventId epicsShareAPI epicsEventMustCreate ( +epicsShareFunc epicsEventId epicsEventMustCreate ( epicsEventInitialState initialState); -epicsShareFunc void epicsShareAPI epicsEventDestroy(epicsEventId id); -epicsShareFunc void epicsShareAPI epicsEventSignal(epicsEventId id); -epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventWait( +epicsShareFunc void epicsEventDestroy(epicsEventId id); +epicsShareFunc epicsEventStatus epicsEventTrigger( epicsEventId id); -#define epicsEventMustWait(ID) { \ - epicsEventWaitStatus status = epicsEventWait(ID); \ - assert(status == epicsEventWaitOK); \ -} -epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventWaitWithTimeout( +epicsShareFunc void epicsEventMustTrigger(epicsEventId id); +#define epicsEventSignal(ID) epicsEventMustTrigger(ID) +epicsShareFunc epicsEventStatus epicsEventWait( + epicsEventId id); +epicsShareFunc void epicsEventMustWait(epicsEventId id); +epicsShareFunc epicsEventStatus epicsEventWaitWithTimeout( epicsEventId id, double timeOut); -epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventTryWait( +epicsShareFunc epicsEventStatus epicsEventTryWait( epicsEventId id); -epicsShareFunc void epicsShareAPI epicsEventShow( +epicsShareFunc void epicsEventShow( epicsEventId id, unsigned int level); #ifdef __cplusplus diff --git a/src/libCom/osi/os/RTEMS/osdEvent.c b/src/libCom/osi/os/RTEMS/osdEvent.c index 12bbc4733..ce21506c7 100644 --- a/src/libCom/osi/os/RTEMS/osdEvent.c +++ b/src/libCom/osi/os/RTEMS/osdEvent.c @@ -1,7 +1,8 @@ /*************************************************************************\ * Copyright (c) 2002 The University of Saskatchewan -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne +* National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* @@ -18,7 +19,6 @@ */ #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1 -#include #include #include #include @@ -84,13 +84,6 @@ epicsEventCreate(epicsEventInitialState initialState) return (epicsEventId)sid; } -epicsEventId epicsEventMustCreate(epicsEventInitialState initialState) -{ - epicsEventId id = epicsEventCreate (initialState); - assert (id); - return id; -} - void epicsEventDestroy(epicsEventId id) { @@ -102,18 +95,20 @@ epicsEventDestroy(epicsEventId id) errlogPrintf ("Can't destroy semaphore: %s\n", rtems_status_text (sc)); } -void -epicsEventSignal(epicsEventId id) +epicsEventStatus +epicsEventTrigger(epicsEventId id) { rtems_id sid = (rtems_id)id; rtems_status_code sc; sc = rtems_semaphore_release (sid); - if (sc != RTEMS_SUCCESSFUL) - errlogPrintf ("Can't release semaphore: %s\n", rtems_status_text (sc)); + if (sc == RTEMS_SUCCESSFUL) + return epicsEventOK; + errlogPrintf ("Can't release semaphore: %s\n", rtems_status_text (sc)); + return epicsEventError; } -epicsEventWaitStatus +epicsEventStatus epicsEventWait(epicsEventId id) { rtems_id sid = (rtems_id)id; @@ -122,11 +117,11 @@ epicsEventWait(epicsEventId id) SEMSTAT(0) sc = rtems_semaphore_obtain (sid, RTEMS_WAIT, RTEMS_NO_TIMEOUT); if (sc != RTEMS_SUCCESSFUL) - return epicsEventWaitError; - return epicsEventWaitOK; + return epicsEventError; + return epicsEventOK; } -epicsEventWaitStatus +epicsEventStatus epicsEventWaitWithTimeout(epicsEventId id, double timeOut) { rtems_id sid = (rtems_id)id; @@ -142,14 +137,14 @@ epicsEventWaitWithTimeout(epicsEventId id, double timeOut) delay++; sc = rtems_semaphore_obtain (sid, RTEMS_WAIT, delay); if (sc == RTEMS_SUCCESSFUL) - return epicsEventWaitOK; + return epicsEventOK; else if (sc == RTEMS_TIMEOUT) return epicsEventWaitTimeout; else - return epicsEventWaitError; + return epicsEventError; } -epicsEventWaitStatus +epicsEventStatus epicsEventTryWait(epicsEventId id) { rtems_id sid = (rtems_id)id; @@ -158,11 +153,11 @@ epicsEventTryWait(epicsEventId id) SEMSTAT(2) sc = rtems_semaphore_obtain (sid, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT); if (sc == RTEMS_SUCCESSFUL) - return epicsEventWaitOK; + return epicsEventOK; else if (sc == RTEMS_UNSATISFIED) return epicsEventWaitTimeout; else - return epicsEventWaitError; + return epicsEventError; } void diff --git a/src/libCom/osi/os/WIN32/osdEvent.c b/src/libCom/osi/os/WIN32/osdEvent.c index f7cafcf3e..a57d43608 100644 --- a/src/libCom/osi/os/WIN32/osdEvent.c +++ b/src/libCom/osi/os/WIN32/osdEvent.c @@ -1,10 +1,9 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found +* EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* osdEvent.c */ @@ -27,7 +26,6 @@ #define epicsExportSharedSymbols #include "shareLib.h" #include "epicsEvent.h" -#include "epicsAssert.h" typedef struct epicsEventOSD { HANDLE handle; @@ -36,7 +34,7 @@ typedef struct epicsEventOSD { /* * epicsEventCreate () */ -epicsShareFunc epicsEventId epicsShareAPI epicsEventCreate ( +epicsShareFunc epicsEventId epicsEventCreate ( epicsEventInitialState initialState ) { epicsEventOSD *pSem; @@ -53,55 +51,44 @@ epicsShareFunc epicsEventId epicsShareAPI epicsEventCreate ( return pSem; } -/* - * epicsEventMustCreate () - */ -epicsShareFunc epicsEventId epicsShareAPI epicsEventMustCreate ( - epicsEventInitialState initialState ) -{ - epicsEventId id = epicsEventCreate ( initialState ); - assert ( id ); - return id; -} - /* * epicsEventDestroy () */ -epicsShareFunc void epicsShareAPI epicsEventDestroy ( epicsEventId pSem ) +epicsShareFunc void epicsEventDestroy ( epicsEventId pSem ) { CloseHandle ( pSem->handle ); free ( pSem ); } /* - * epicsEventSignal () + * epicsEventTrigger () */ -epicsShareFunc void epicsShareAPI epicsEventSignal ( epicsEventId pSem ) +epicsShareFunc epicsEventStatus epicsEventTrigger ( epicsEventId pSem ) { BOOL status; status = SetEvent ( pSem->handle ); - assert ( status ); + return status ? epicsEventOK : epicsEventError; } /* * epicsEventWait () */ -epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventWait ( epicsEventId pSem ) +epicsShareFunc epicsEventStatus epicsEventWait ( epicsEventId pSem ) { DWORD status; status = WaitForSingleObject (pSem->handle, INFINITE); if ( status == WAIT_OBJECT_0 ) { - return epicsEventWaitOK; + return epicsEventOK; } else { - return epicsEventWaitError; + return epicsEventError; } } /* * epicsEventWaitWithTimeout () */ -epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventWaitWithTimeout ( +epicsShareFunc epicsEventStatus epicsEventWaitWithTimeout ( epicsEventId pSem, double timeOut ) { static const unsigned mSecPerSec = 1000; @@ -122,38 +109,38 @@ epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventWaitWithTimeout ( } status = WaitForSingleObject ( pSem->handle, tmo ); if ( status == WAIT_OBJECT_0 ) { - return epicsEventWaitOK; + return epicsEventOK; } else if ( status == WAIT_TIMEOUT ) { return epicsEventWaitTimeout; } else { - return epicsEventWaitError; + return epicsEventError; } } /* * epicsEventTryWait () */ -epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventTryWait ( epicsEventId pSem ) +epicsShareFunc epicsEventStatus epicsEventTryWait ( epicsEventId pSem ) { DWORD status; status = WaitForSingleObject ( pSem->handle, 0 ); if ( status == WAIT_OBJECT_0 ) { - return epicsEventWaitOK; + return epicsEventOK; } else if ( status == WAIT_TIMEOUT ) { return epicsEventWaitTimeout; } else { - return epicsEventWaitError; + return epicsEventError; } } /* * epicsEventShow () */ -epicsShareFunc void epicsShareAPI epicsEventShow ( epicsEventId id, unsigned level ) +epicsShareFunc void epicsEventShow ( epicsEventId id, unsigned level ) { } diff --git a/src/libCom/osi/os/posix/osdEvent.c b/src/libCom/osi/os/posix/osdEvent.c index dd3923c7d..cfd80aa67 100644 --- a/src/libCom/osi/os/posix/osdEvent.c +++ b/src/libCom/osi/os/posix/osdEvent.c @@ -1,5 +1,5 @@ /*************************************************************************\ -* Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. @@ -21,155 +21,142 @@ #define epicsExportSharedSymbols #include "epicsEvent.h" -#include "cantProceed.h" #include "epicsTime.h" #include "errlog.h" -#include "epicsAssert.h" /* Until these can be demonstrated to work leave them undefined*/ #undef _POSIX_THREAD_PROCESS_SHARED #undef _POSIX_THREAD_PRIO_INHERIT -typedef struct epicsEventOSD { - pthread_mutex_t mutex; - pthread_cond_t cond; - int isFull; -}epicsEventOSD; - -#define checkStatus(status,message) \ -if((status)) { \ - errlogPrintf("epicsEvent %s failed: error %s\n",(message),strerror((status)));} +struct epicsEventOSD { + pthread_mutex_t mutex; + pthread_cond_t cond; + int isFull; +}; -#define checkStatusQuit(status,message,method) \ -if(status) { \ - errlogPrintf("epicsEvent %s failed: error %s\n",(message),strerror((status))); \ - cantProceed((method)); \ -} +#define printStatus(status, routine, func) \ + errlogPrintf("%s: %s failed: %s\n", (func), (routine), strerror(status)) -static int mutexLock(pthread_mutex_t *id) -{ - int status; - - while(1) { - status = pthread_mutex_lock(id); - if(status!=EINTR) return status; - errlogPrintf("pthread_mutex_lock returned EINTR. Violates SUSv3\n"); +#define checkStatus(status, routine, func) \ + if (status) { \ + printStatus(status, routine, func); \ } -} -static int condTimedwait(pthread_cond_t *condId, pthread_mutex_t *mutexId, - struct timespec *time) -{ - int status; - while(1) { - status = pthread_cond_timedwait(condId,mutexId,time); - if(status!=EINTR) return status; - errlogPrintf("pthread_cond_timedwait returned EINTR. Violates SUSv3\n"); +#define checkStatusReturn(status, routine, func) \ + if (status) { \ + printStatus(status, routine, func); \ + return epicsEventError; \ } -} -static int condWait(pthread_cond_t *condId, pthread_mutex_t *mutexId) + +epicsShareFunc epicsEventId epicsEventCreate(epicsEventInitialState init) { - int status; - while(1) { - status = pthread_cond_wait(condId,mutexId); - if(status!=EINTR) return status; - errlogPrintf("pthread_cond_wait returned EINTR. Violates SUSv3\n"); + epicsEventId pevent = malloc(sizeof(*pevent)); + + if (pevent) { + int status = pthread_mutex_init(&pevent->mutex, 0); + + pevent->isFull = (init == epicsEventFull); + if (status) { + printStatus(status, "pthread_mutex_init", "epicsEventCreate"); + } else { + status = pthread_cond_init(&pevent->cond, 0); + if (!status) + return pevent; + printStatus(status, "pthread_cond_init", "epicsEventCreate"); + status = pthread_mutex_destroy(&pevent->mutex); + checkStatus(status, "pthread_mutex_destroy", "epicsEventCreate"); + } + free(pevent); } -} - -epicsShareFunc epicsEventId epicsShareAPI epicsEventCreate(epicsEventInitialState initialState) -{ - epicsEventOSD *pevent; - int status; - - pevent = callocMustSucceed(1,sizeof(*pevent),"epicsEventCreate"); - status = pthread_mutex_init(&pevent->mutex,0); - checkStatusQuit(status,"pthread_mutex_init","epicsEventCreate"); - status = pthread_cond_init(&pevent->cond,0); - checkStatusQuit(status,"pthread_cond_init","epicsEventCreate"); - if(initialState==epicsEventFull) pevent->isFull = 1; - return((epicsEventId)pevent); + return NULL; } -epicsShareFunc epicsEventId epicsShareAPI epicsEventMustCreate(epicsEventInitialState initialState) +epicsShareFunc void epicsEventDestroy(epicsEventId pevent) { - epicsEventId id = epicsEventCreate (initialState); - assert (id); - return id; -} + int status = pthread_mutex_destroy(&pevent->mutex); -epicsShareFunc void epicsShareAPI epicsEventDestroy(epicsEventId pevent) -{ - int status; - - status = pthread_mutex_destroy(&pevent->mutex); - checkStatus(status,"pthread_mutex_destroy"); + checkStatus(status, "pthread_mutex_destroy", "epicsEventDestroy"); status = pthread_cond_destroy(&pevent->cond); - checkStatus(status,"pthread_cond_destroy"); + checkStatus(status, "pthread_cond_destroy", "epicsEventDestroy"); free(pevent); } -epicsShareFunc void epicsShareAPI epicsEventSignal(epicsEventId pevent) +epicsShareFunc epicsEventStatus epicsEventTrigger(epicsEventId pevent) { - int status; + int status = pthread_mutex_lock(&pevent->mutex); - status = mutexLock(&pevent->mutex); - checkStatusQuit(status,"pthread_mutex_lock","epicsEventSignal"); - if(!pevent->isFull) { + checkStatusReturn(status, "pthread_mutex_lock", "epicsEventTrigger"); + if (!pevent->isFull) { pevent->isFull = 1; status = pthread_cond_signal(&pevent->cond); - checkStatus(status,"pthread_cond_signal"); + checkStatus(status, "pthread_cond_signal", "epicsEventTrigger"); } status = pthread_mutex_unlock(&pevent->mutex); - checkStatusQuit(status,"pthread_mutex_unlock","epicsEventSignal"); + checkStatusReturn(status, "pthread_mutex_unlock", "epicsEventTrigger"); + return epicsEventOK; } - -epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventWait(epicsEventId pevent) -{ - int status; - if(!pevent) return(epicsEventWaitError); - status = mutexLock(&pevent->mutex); - checkStatusQuit(status,"pthread_mutex_lock","epicsEventWait"); - /*no need for while since caller must be prepared for no work*/ - if(!pevent->isFull) { - status = condWait(&pevent->cond,&pevent->mutex); - checkStatusQuit(status,"pthread_cond_wait","epicsEventWait"); +epicsShareFunc epicsEventStatus epicsEventWait(epicsEventId pevent) +{ + epicsEventStatus result = epicsEventOK; + int status = pthread_mutex_lock(&pevent->mutex); + + checkStatusReturn(status, "pthread_mutex_lock", "epicsEventWait"); + while (!pevent->isFull) { + status = pthread_cond_wait(&pevent->cond, &pevent->mutex); + if (status) { + printStatus(status, "pthread_cond_wait", "epicsEventWait"); + result = epicsEventError; + goto release; + } } pevent->isFull = 0; + result = epicsEventOK; +release: status = pthread_mutex_unlock(&pevent->mutex); - checkStatusQuit(status,"pthread_mutex_unlock","epicsEventWait"); - return(epicsEventWaitOK); + checkStatusReturn(status, "pthread_mutex_unlock", "epicsEventWait"); + return result; } -epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventWaitWithTimeout(epicsEventId pevent, double timeout) +epicsShareFunc epicsEventStatus epicsEventWaitWithTimeout(epicsEventId pevent, + double timeout) { - struct timespec wakeTime; - int status = 0; - int unlockStatus; + epicsEventStatus result = epicsEventOK; + int status = pthread_mutex_lock(&pevent->mutex); - status = mutexLock(&pevent->mutex); - checkStatusQuit(status,"pthread_mutex_lock","epicsEventWaitWithTimeout"); - if(!pevent->isFull) { - convertDoubleToWakeTime(timeout,&wakeTime); - status = condTimedwait( - &pevent->cond,&pevent->mutex,&wakeTime); + checkStatusReturn(status, "pthread_mutex_lock", "epicsEventWaitWithTimeout"); + if (!pevent->isFull) { + struct timespec wakeTime; + + convertDoubleToWakeTime(timeout, &wakeTime); + while (!status && !pevent->isFull) { + status = pthread_cond_timedwait(&pevent->cond, &pevent->mutex, + &wakeTime); + } + if (status) { + result = (status == ETIMEDOUT) ? + epicsEventWaitTimeout : epicsEventError; + goto release; + } } - if(status==0) pevent->isFull = 0; - unlockStatus = pthread_mutex_unlock(&pevent->mutex); - checkStatusQuit(unlockStatus,"pthread_mutex_unlock","epicsEventWaitWithTimeout"); - if(status==0) return(epicsEventWaitOK); - if(status==ETIMEDOUT) return(epicsEventWaitTimeout); - checkStatus(status,"pthread_cond_timedwait"); - return(epicsEventWaitError); + pevent->isFull = 0; +release: + status = pthread_mutex_unlock(&pevent->mutex); + checkStatusReturn(status, "pthread_mutex_unlock", "epicsEventWaitWithTimeout"); + return result; } -epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventTryWait(epicsEventId id) +epicsShareFunc epicsEventStatus epicsEventTryWait(epicsEventId id) { - return(epicsEventWaitWithTimeout(id,0.0)); + return epicsEventWaitWithTimeout(id, 0.0); } -epicsShareFunc void epicsShareAPI epicsEventShow(epicsEventId id,unsigned int level) +epicsShareFunc void epicsEventShow(epicsEventId pevent, unsigned int level) { + printf("epicsEvent %p: %s\n", pevent, + pevent->isFull ? "full" : "empty"); + if (level > 0) + printf(" pthread_mutex = %p, pthread_cond = %p\n", + &pevent->mutex, &pevent->cond); } diff --git a/src/libCom/osi/os/vxWorks/osdEvent.c b/src/libCom/osi/os/vxWorks/osdEvent.c index 692d6f63f..875d4e6f6 100644 --- a/src/libCom/osi/os/vxWorks/osdEvent.c +++ b/src/libCom/osi/os/vxWorks/osdEvent.c @@ -1,10 +1,9 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found +* EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* os/vxWorks/osdEvent.c */ @@ -29,19 +28,12 @@ epicsEventId epicsEventCreate(epicsEventInitialState initialState) (initialState == epicsEventEmpty) ? SEM_EMPTY : SEM_FULL); } -epicsEventId epicsEventMustCreate(epicsEventInitialState initialState) -{ - epicsEventId id = epicsEventCreate(initialState); - assert(id); - return id; -} - void epicsEventDestroy(epicsEventId id) { semDelete((SEM_ID)id); } -epicsEventWaitStatus epicsEventWaitWithTimeout(epicsEventId id, double timeOut) +epicsEventStatus epicsEventWaitWithTimeout(epicsEventId id, double timeOut) { int rate = sysClkRateGet(); int status; @@ -58,22 +50,22 @@ epicsEventWaitStatus epicsEventWaitWithTimeout(epicsEventId id, double timeOut) } status = semTake((SEM_ID)id, ticks); if (status == OK) - return epicsEventWaitOK; + return epicsEventOK; if (errno == S_objLib_OBJ_TIMEOUT || (errno == S_objLib_OBJ_UNAVAILABLE && ticks == 0)) return epicsEventWaitTimeout; - return epicsEventWaitError; + return epicsEventError; } -epicsEventWaitStatus epicsEventTryWait(epicsEventId id) +epicsEventStatus epicsEventTryWait(epicsEventId id) { int status = semTake((SEM_ID)id, NO_WAIT); if (status == OK) - return epicsEventWaitOK; + return epicsEventOK; if (errno == S_objLib_OBJ_UNAVAILABLE) return epicsEventWaitTimeout; - return epicsEventWaitError; + return epicsEventError; } void epicsEventShow(epicsEventId id, unsigned int level) diff --git a/src/libCom/osi/os/vxWorks/osdEvent.h b/src/libCom/osi/os/vxWorks/osdEvent.h index 450f8eac6..b08b4d98f 100644 --- a/src/libCom/osi/os/vxWorks/osdEvent.h +++ b/src/libCom/osi/os/vxWorks/osdEvent.h @@ -1,10 +1,9 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found +* EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* os/vxWorks/osdEvent.h */ @@ -14,12 +13,8 @@ #include #include -/* If the macro is replaced by inline it is necessary to say - static __inline__ - but then a warning message appears everywhere osdEvent.h is included -*/ - -#define epicsEventSignal(ID) semGive((SEM_ID)(ID)) +#define epicsEventTrigger(ID) \ + (semGive((SEM_ID)(ID)) == OK ? epicsEventOK : epicsEventError) #define epicsEventWait(ID) \ -(semTake((SEM_ID)(ID),WAIT_FOREVER)==OK ? epicsEventWaitOK : epicsEventWaitError) + (semTake((SEM_ID)(ID), WAIT_FOREVER) == OK ? epicsEventOK : epicsEventError) diff --git a/src/libCom/test/epicsEventTest.cpp b/src/libCom/test/epicsEventTest.cpp index 31da6208b..b0d79613f 100644 --- a/src/libCom/test/epicsEventTest.cpp +++ b/src/libCom/test/epicsEventTest.cpp @@ -47,8 +47,8 @@ static void consumer(void *arg) testDiag("consumer: starting"); while (!pinfo->quit) { - epicsEventWaitStatus status = epicsEventWait(pinfo->event); - if (status != epicsEventWaitOK) { + epicsEventStatus status = epicsEventWait(pinfo->event); + if (status != epicsEventOK) { testDiag("consumer: epicsEventWait returned %d", status); errors++; } @@ -101,7 +101,7 @@ static void producer(void *arg) } epicsMutexUnlock(pinfo->lockRing); epicsThreadSleep(1.0); - epicsEventSignal(pinfo->event); + epicsEventMustTrigger(pinfo->event); } testOk(errors == 0, "%s: errors = %d", name, errors); } @@ -140,7 +140,7 @@ static void eventWakeupTest(void) epicsMutexUnlock(wp->countMutex); testOk(c == 0, "all threads still sleeping"); for (i = 1 ; i <= SLEEPERCOUNT ; i++) { - epicsEventSignal(wp->event); + epicsEventMustTrigger(wp->event); epicsThreadSleep(0.5); epicsMutexLock(wp->countMutex); c = wp->count; @@ -190,7 +190,7 @@ MAIN(epicsEventTest) epicsEventId event; int status; - testPlan(12+SLEEPERCOUNT); + testPlan(13+SLEEPERCOUNT); event = epicsEventMustCreate(epicsEventEmpty); @@ -206,19 +206,21 @@ MAIN(epicsEventTest) testOk(status == epicsEventWaitTimeout, "epicsEventTryWait(event) = %d", status); - epicsEventSignal(event); + status = epicsEventTrigger(event); + testOk(status == epicsEventOK, + "epicsEventTrigger(event) = %d", status); status = epicsEventWaitWithTimeout(event, 1.0); - testOk(status == epicsEventWaitOK, + testOk(status == epicsEventOK, "epicsEventWaitWithTimeout(event, 1.0) = %d", status); - epicsEventSignal(event); + epicsEventMustTrigger(event); status = epicsEventWaitWithTimeout(event,DBL_MAX); - testOk(status == epicsEventWaitOK, + testOk(status == epicsEventOK, "epicsEventWaitWithTimeout(event, DBL_MAX) = %d", status); - epicsEventSignal(event); + epicsEventMustTrigger(event); status = epicsEventTryWait(event); - testOk(status == epicsEventWaitOK, + testOk(status == epicsEventOK, "epicsEventTryWait(event) = %d", status); info *pinfo = (info *)calloc(1,sizeof(info)); @@ -242,7 +244,7 @@ MAIN(epicsEventTest) pinfo->quit = 1; epicsThreadSleep(2.0); - epicsEventSignal(pinfo->event); + epicsEventMustTrigger(pinfo->event); epicsThreadSleep(1.0); eventWaitTest();