From 77192b3228369fb9fa793912a49572123f3f45e0 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 8 Feb 2011 12:02:08 -0600 Subject: [PATCH 1/2] libCom: Reworked the epicsEvent APIs * Renamed the enum epicsEventWaitStatus to epicsEventStatus * Defined epicsEventWaitStatus as a macro for epicsEventStatus * Renamed epicsEventWaitOk to epicsEventOk * Renamed epicsEventWaitError to epicsEventError * Defined epicsEventWaitOK and epicsEventWaitError as macros * Added epicsEventTrigger(id) which triggers an event and returns OK or an error status if the underlying OS primitives report an error * Added epicsEventMustTrigger(id) which halts on error * Defined epicsEventSignal(id) as a macro for epicsEventMustTrigger(id) * Added a new C++ method epicsEvent::trigger() which throws an epicsEvent::invalidSemaphore in the event of an error * epicsEvent::signal() makes an inline call to epicsEvent::trigger() * epicsEventWait() and epicsEventWaitWithTimeout() now return an error status if the underlying OS primitives report an error * All the epicsEventMust...() routines are now implemented in the common libCom/osi/epicsEvent.cpp source file, and call cantProceed() instead of mis-using assert() * Implemented epicsEventShow() on Posix --- documentation/RELEASE_NOTES.html | 23 +++ src/libCom/osi/epicsEvent.cpp | 76 +++++++--- src/libCom/osi/epicsEvent.h | 52 ++++--- src/libCom/osi/os/RTEMS/osdEvent.c | 41 +++--- src/libCom/osi/os/WIN32/osdEvent.c | 39 ++---- src/libCom/osi/os/posix/osdEvent.c | 200 +++++++++++++-------------- src/libCom/osi/os/vxWorks/osdEvent.c | 24 ++-- src/libCom/osi/os/vxWorks/osdEvent.h | 15 +- 8 files changed, 243 insertions(+), 227 deletions(-) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 08266cc58..1dfe46a3c 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -13,6 +13,29 @@

Changes between 3.14.x and 3.15.1

+

+Reworked the epicsEvent C & C++ APIs

+ +

Moved src/RTEMS/base directory

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..41816858a 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,22 +35,20 @@ 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 */ @@ -51,16 +57,16 @@ epicsShareFunc epicsEventId epicsShareAPI epicsEventCreate( epicsShareFunc epicsEventId epicsShareAPI epicsEventMustCreate ( epicsEventInitialState initialState); epicsShareFunc void epicsShareAPI epicsEventDestroy(epicsEventId id); -epicsShareFunc void epicsShareAPI epicsEventSignal(epicsEventId id); -epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventWait( +epicsShareFunc epicsEventStatus epicsShareAPI epicsEventTrigger( epicsEventId id); -#define epicsEventMustWait(ID) { \ - epicsEventWaitStatus status = epicsEventWait(ID); \ - assert(status == epicsEventWaitOK); \ -} -epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventWaitWithTimeout( +epicsShareFunc void epicsShareAPI epicsEventMustTrigger(epicsEventId id); +#define epicsEventSignal(ID) epicsEventMustTrigger(ID) +epicsShareFunc epicsEventStatus epicsShareAPI epicsEventWait( + epicsEventId id); +epicsShareFunc void epicsShareAPI epicsEventMustWait(epicsEventId id); +epicsShareFunc epicsEventStatus epicsShareAPI epicsEventWaitWithTimeout( epicsEventId id, double timeOut); -epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventTryWait( +epicsShareFunc epicsEventStatus epicsShareAPI epicsEventTryWait( epicsEventId id); epicsShareFunc void epicsShareAPI epicsEventShow( epicsEventId id, unsigned int level); 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..d017104ca 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; @@ -53,17 +51,6 @@ epicsShareFunc epicsEventId epicsShareAPI epicsEventCreate ( return pSem; } -/* - * epicsEventMustCreate () - */ -epicsShareFunc epicsEventId epicsShareAPI epicsEventMustCreate ( - epicsEventInitialState initialState ) -{ - epicsEventId id = epicsEventCreate ( initialState ); - assert ( id ); - return id; -} - /* * epicsEventDestroy () */ @@ -76,32 +63,32 @@ epicsShareFunc void epicsShareAPI epicsEventDestroy ( epicsEventId pSem ) /* * epicsEventSignal () */ -epicsShareFunc void epicsShareAPI epicsEventSignal ( epicsEventId pSem ) +epicsShareFunc epicsEventStatus epicsShareAPI epicsEventTrigger ( epicsEventId pSem ) { BOOL status; status = SetEvent ( pSem->handle ); - assert ( status ); + return status ? epicsEventError : epicsEventOK; } /* * epicsEventWait () */ -epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventWait ( epicsEventId pSem ) +epicsShareFunc epicsEventStatus epicsShareAPI 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 epicsShareAPI epicsEventWaitWithTimeout ( epicsEventId pSem, double timeOut ) { static const unsigned mSecPerSec = 1000; @@ -122,32 +109,32 @@ 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 epicsShareAPI 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; } } diff --git a/src/libCom/osi/os/posix/osdEvent.c b/src/libCom/osi/os/posix/osdEvent.c index dd3923c7d..9c1a5a88b 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,141 @@ #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"); } - -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) From 072b449bb1ad8258bea1255258699796a57ecf88 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 8 Feb 2011 14:17:47 -0600 Subject: [PATCH 2/2] libCom: Fixed epicsEvent issues on Win32 and cygwin. * Removed all epicsShareAPI decorations * Return value from Win32 epicsEventTrigger() inverted * Return OK from posix epicsEventTrigger() omitted. --- documentation/RELEASE_NOTES.html | 1 + src/libCom/osi/epicsEvent.h | 20 ++++++++++---------- src/libCom/osi/os/WIN32/osdEvent.c | 18 +++++++++--------- src/libCom/osi/os/posix/osdEvent.c | 1 + 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 1dfe46a3c..1832c8485 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -35,6 +35,7 @@ Reworked the epicsEvent C & C++ APIs libCom/osi/epicsEvent.cpp source file, and call cantProceed() instead of mis-using assert()
  • Implemented epicsEventShow() on Posix
  • +
  • Win32: Removed all epicsShareAPI decorations
  • diff --git a/src/libCom/osi/epicsEvent.h b/src/libCom/osi/epicsEvent.h index 41816858a..e77d9a5ce 100644 --- a/src/libCom/osi/epicsEvent.h +++ b/src/libCom/osi/epicsEvent.h @@ -52,23 +52,23 @@ private: 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 epicsEventStatus epicsShareAPI epicsEventTrigger( +epicsShareFunc void epicsEventDestroy(epicsEventId id); +epicsShareFunc epicsEventStatus epicsEventTrigger( epicsEventId id); -epicsShareFunc void epicsShareAPI epicsEventMustTrigger(epicsEventId id); +epicsShareFunc void epicsEventMustTrigger(epicsEventId id); #define epicsEventSignal(ID) epicsEventMustTrigger(ID) -epicsShareFunc epicsEventStatus epicsShareAPI epicsEventWait( +epicsShareFunc epicsEventStatus epicsEventWait( epicsEventId id); -epicsShareFunc void epicsShareAPI epicsEventMustWait(epicsEventId id); -epicsShareFunc epicsEventStatus epicsShareAPI epicsEventWaitWithTimeout( +epicsShareFunc void epicsEventMustWait(epicsEventId id); +epicsShareFunc epicsEventStatus epicsEventWaitWithTimeout( epicsEventId id, double timeOut); -epicsShareFunc epicsEventStatus 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/WIN32/osdEvent.c b/src/libCom/osi/os/WIN32/osdEvent.c index d017104ca..a57d43608 100644 --- a/src/libCom/osi/os/WIN32/osdEvent.c +++ b/src/libCom/osi/os/WIN32/osdEvent.c @@ -34,7 +34,7 @@ typedef struct epicsEventOSD { /* * epicsEventCreate () */ -epicsShareFunc epicsEventId epicsShareAPI epicsEventCreate ( +epicsShareFunc epicsEventId epicsEventCreate ( epicsEventInitialState initialState ) { epicsEventOSD *pSem; @@ -54,26 +54,26 @@ epicsShareFunc epicsEventId epicsShareAPI epicsEventCreate ( /* * epicsEventDestroy () */ -epicsShareFunc void epicsShareAPI epicsEventDestroy ( epicsEventId pSem ) +epicsShareFunc void epicsEventDestroy ( epicsEventId pSem ) { CloseHandle ( pSem->handle ); free ( pSem ); } /* - * epicsEventSignal () + * epicsEventTrigger () */ -epicsShareFunc epicsEventStatus epicsShareAPI epicsEventTrigger ( epicsEventId pSem ) +epicsShareFunc epicsEventStatus epicsEventTrigger ( epicsEventId pSem ) { BOOL status; status = SetEvent ( pSem->handle ); - return status ? epicsEventError : epicsEventOK; + return status ? epicsEventOK : epicsEventError; } /* * epicsEventWait () */ -epicsShareFunc epicsEventStatus epicsShareAPI epicsEventWait ( epicsEventId pSem ) +epicsShareFunc epicsEventStatus epicsEventWait ( epicsEventId pSem ) { DWORD status; status = WaitForSingleObject (pSem->handle, INFINITE); @@ -88,7 +88,7 @@ epicsShareFunc epicsEventStatus epicsShareAPI epicsEventWait ( epicsEventId pSem /* * epicsEventWaitWithTimeout () */ -epicsShareFunc epicsEventStatus epicsShareAPI epicsEventWaitWithTimeout ( +epicsShareFunc epicsEventStatus epicsEventWaitWithTimeout ( epicsEventId pSem, double timeOut ) { static const unsigned mSecPerSec = 1000; @@ -122,7 +122,7 @@ epicsShareFunc epicsEventStatus epicsShareAPI epicsEventWaitWithTimeout ( /* * epicsEventTryWait () */ -epicsShareFunc epicsEventStatus epicsShareAPI epicsEventTryWait ( epicsEventId pSem ) +epicsShareFunc epicsEventStatus epicsEventTryWait ( epicsEventId pSem ) { DWORD status; @@ -141,6 +141,6 @@ epicsShareFunc epicsEventStatus epicsShareAPI epicsEventTryWait ( epicsEventId p /* * 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 9c1a5a88b..cfd80aa67 100644 --- a/src/libCom/osi/os/posix/osdEvent.c +++ b/src/libCom/osi/os/posix/osdEvent.c @@ -94,6 +94,7 @@ epicsShareFunc epicsEventStatus epicsEventTrigger(epicsEventId pevent) } status = pthread_mutex_unlock(&pevent->mutex); checkStatusReturn(status, "pthread_mutex_unlock", "epicsEventTrigger"); + return epicsEventOK; } epicsShareFunc epicsEventStatus epicsEventWait(epicsEventId pevent)