From 6063de9a8bc0bc5209a4e3024c44bde08a7f35ec Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 12 Oct 2021 12:37:57 -0500 Subject: [PATCH 1/6] Added Heinz new osdEvent.c to RTEMS-posix --- .../libcom/src/osi/os/RTEMS-posix/osdEvent.c | 111 ++++++++++++++++++ .../libcom/src/osi/os/RTEMS-posix/osdEvent.h | 8 ++ 2 files changed, 119 insertions(+) create mode 100644 modules/libcom/src/osi/os/RTEMS-posix/osdEvent.c create mode 100644 modules/libcom/src/osi/os/RTEMS-posix/osdEvent.h diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdEvent.c b/modules/libcom/src/osi/os/RTEMS-posix/osdEvent.c new file mode 100644 index 000000000..54dfccfff --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdEvent.c @@ -0,0 +1,111 @@ +/*************************************************************************\ +* Copyright (c) 2021 Fritz Haber Institute, Berlin +* SPDX-License-Identifier: EPICS +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * RTEMS osdEvent.c + * Author: H. Junkes + * junkes@fhi.mpg.de + */ + +#include +#include +#include +#include +#include + +#include + +#include "libComAPI.h" +#include "epicsEvent.h" + +typedef struct epicsEventOSD { + rtems_binary_semaphore rbs; +} epicsEventOSD; + +/* + * Create a simple binary semaphore + */ +LIBCOM_API epicsEventId +epicsEventCreate(epicsEventInitialState initialState) +{ + epicsEventOSD *pSem = malloc (sizeof(*pSem)); + + if (pSem) { + rtems_binary_semaphore_init(&pSem->rbs, NULL); + if (initialState) + rtems_binary_semaphore_post(&pSem->rbs); + } + return pSem; +} + +LIBCOM_API void +epicsEventDestroy(epicsEventId pSem) +{ + rtems_binary_semaphore_destroy(&pSem->rbs); +} + +LIBCOM_API epicsEventStatus +epicsEventTrigger(epicsEventId pSem) +{ + rtems_binary_semaphore_post(&pSem->rbs); + return epicsEventOK; +} + +LIBCOM_API epicsEventStatus +epicsEventWait(epicsEventId pSem) +{ + rtems_binary_semaphore_wait(&pSem->rbs); + return epicsEventOK; +} + +LIBCOM_API epicsEventStatus +epicsEventWaitWithTimeout(epicsEventId pSem, double timeOut) +{ + int sc; + rtems_interval delay; + int rate = rtems_clock_get_ticks_per_second(); + + if (!rate) + return epicsEventError; + + if (timeOut <= 0.0) { + sc = rtems_binary_semaphore_try_wait(&pSem->rbs); + if (!sc) + return epicsEventOK; + else + return epicsEventWaitTimeout; + } + else if (timeOut >= (double) INT_MAX / rate) { + delay = 0; + } + else { + delay = timeOut * rate; + } + + sc = rtems_binary_semaphore_wait_timed_ticks(&pSem->rbs, delay); + if (!sc) + return epicsEventOK; + else if (sc == ETIMEDOUT) + return epicsEventWaitTimeout; + else + return epicsEventError; +} + +LIBCOM_API epicsEventStatus +epicsEventTryWait(epicsEventId pSem) +{ + int sc = rtems_binary_semaphore_try_wait(&pSem->rbs); + + if (!sc) + return epicsEventOK; + else + return epicsEventWaitTimeout; +} + +LIBCOM_API void +epicsEventShow(epicsEventId pSem, unsigned int level) +{ +} diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdEvent.h b/modules/libcom/src/osi/os/RTEMS-posix/osdEvent.h new file mode 100644 index 000000000..6778c4662 --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdEvent.h @@ -0,0 +1,8 @@ +/*************************************************************************\ +* Copyright (c) 2021 Fritz Haber Institute, Berlin +* SPDX-License-Identifier: EPICS +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* No definitions are needed for this implementation */ From 34baa485bc5defca6ba47e7f65353f2b53f6f2ad Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 4 Jan 2022 13:05:21 -0600 Subject: [PATCH 2/6] Fix timeout values in epicsEventWaitWithTimeout() isnan(timeOut) => wait forever 0 < timeOut < 1/rate => 1 tick --- modules/libcom/src/osi/os/vxWorks/osdEvent.c | 13 ++++-- .../src/osi/os/vxWorks/osdMessageQueue.cpp | 40 ++++++++++++++----- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/modules/libcom/src/osi/os/vxWorks/osdEvent.c b/modules/libcom/src/osi/os/vxWorks/osdEvent.c index 27b271e51..dc139432c 100644 --- a/modules/libcom/src/osi/os/vxWorks/osdEvent.c +++ b/modules/libcom/src/osi/os/vxWorks/osdEvent.c @@ -42,12 +42,17 @@ epicsEventStatus epicsEventWaitWithTimeout(epicsEventId id, double timeOut) if (timeOut <= 0.0) { ticks = 0; - } else if (timeOut >= (double) INT_MAX / rate) { - ticks = WAIT_FOREVER; - } else { + } + else if (timeOut < (double) INT_MAX / rate) { ticks = timeOut * rate; - if (ticks <= 0) + if (ticks == 0) { + /* 0 < timeOut < 1/rate; round up */ ticks = 1; + } + } + else { + /* timeOut is NaN or too big to represent in ticks */ + ticks = WAIT_FOREVER; } status = semTake((SEM_ID)id, ticks); if (status == OK) diff --git a/modules/libcom/src/osi/os/vxWorks/osdMessageQueue.cpp b/modules/libcom/src/osi/os/vxWorks/osdMessageQueue.cpp index bf27daf1b..d06952209 100644 --- a/modules/libcom/src/osi/os/vxWorks/osdMessageQueue.cpp +++ b/modules/libcom/src/osi/os/vxWorks/osdMessageQueue.cpp @@ -21,18 +21,28 @@ extern "C" int sysClkRateGet(void); LIBCOM_API int epicsStdCall epicsMessageQueueSendWithTimeout( epicsMessageQueueId id, void *message, - unsigned int messageSize, + unsigned int size, double timeout) { int ticks; + int rate = sysClkRateGet(); - if (timeout<=0.0) { + if (timeout <= 0.0) { ticks = 0; - } else { - ticks = (int)(timeout*sysClkRateGet()); - if(ticks<=0) ticks = 1; } - return msgQSend((MSG_Q_ID)id, (char *)message, messageSize, ticks, MSG_PRI_NORMAL); + else if (timeOut < (double) INT_MAX / rate) { + ticks = timeout * rate; + if (ticks == 0) { + /* 0 < timeOut < 1/rate; round up */ + ticks = 1; + } + } + else { + /* timeOut is NaN or too big to represent in ticks */ + ticks = WAIT_FOREVER; + } + + return msgQSend((MSG_Q_ID)id, (char *)message, size, ticks, MSG_PRI_NORMAL); } LIBCOM_API int epicsStdCall epicsMessageQueueReceiveWithTimeout( @@ -42,12 +52,22 @@ LIBCOM_API int epicsStdCall epicsMessageQueueReceiveWithTimeout( double timeout) { int ticks; + int rate = sysClkRateGet(); - if (timeout<=0.0) { + if (timeout <= 0.0) { ticks = 0; - } else { - ticks = (int)(timeout*sysClkRateGet()); - if(ticks<=0) ticks = 1; } + else if (timeOut < (double) INT_MAX / rate) { + ticks = timeout * rate; + if (ticks == 0) { + /* 0 < timeOut < 1/rate, round up */ + ticks = 1; + } + } + else { + /* timeOut is NaN or too big to represent in ticks */ + ticks = WAIT_FOREVER; + } + return msgQReceive((MSG_Q_ID)id, (char *)message, size, ticks); } From d1094ee787bbcbe202227ffd9e5618f0ae5f7d2f Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 4 Jan 2022 13:07:30 -0600 Subject: [PATCH 3/6] Fix timeout values in epicsEventWaitWithTimeout() isnan(timeOut) => wait forever 0 < timeOut < 1/rate => 1 tick rtems_interval is a typedef for uint32_t --- modules/libcom/src/osi/os/RTEMS-posix/osdEvent.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdEvent.c b/modules/libcom/src/osi/os/RTEMS-posix/osdEvent.c index 54dfccfff..abd9a8e9a 100644 --- a/modules/libcom/src/osi/os/RTEMS-posix/osdEvent.c +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdEvent.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include @@ -66,7 +66,7 @@ epicsEventWaitWithTimeout(epicsEventId pSem, double timeOut) { int sc; rtems_interval delay; - int rate = rtems_clock_get_ticks_per_second(); + rtems_interval rate = rtems_clock_get_ticks_per_second(); if (!rate) return epicsEventError; @@ -78,11 +78,16 @@ epicsEventWaitWithTimeout(epicsEventId pSem, double timeOut) else return epicsEventWaitTimeout; } - else if (timeOut >= (double) INT_MAX / rate) { - delay = 0; + else if (timeOut < (double) UINT32_MAX / rate) { + delay = timeOut * rate; + if (delay == 0) { + /* 0 < timeOut < 1/rate; round up */ + delay = 1; + } } else { - delay = timeOut * rate; + /* timeOut is NaN or too big to represent; wait forever */ + delay = RTEMS_NO_TIMEOUT; } sc = rtems_binary_semaphore_wait_timed_ticks(&pSem->rbs, delay); From e4a81bb361558769817d55c162c301735131b6b4 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 4 Jan 2022 17:16:59 -0600 Subject: [PATCH 4/6] Document zero and NaN timeout values Rename parameter timeOut => timeout everywhere --- modules/ca/src/client/cadef.h | 8 ++++---- modules/libcom/src/osi/epicsEvent.cpp | 4 ++-- modules/libcom/src/osi/epicsEvent.h | 12 ++++++++---- modules/libcom/src/osi/epicsMessageQueue.h | 17 ++++++++++++----- .../libcom/src/osi/os/RTEMS-posix/osdEvent.c | 12 ++++++------ .../libcom/src/osi/os/RTEMS-score/osdEvent.c | 6 +++--- modules/libcom/src/osi/os/WIN32/osdEvent.c | 8 ++++---- modules/libcom/src/osi/os/vxWorks/osdEvent.c | 12 ++++++------ .../src/osi/os/vxWorks/osdMessageQueue.cpp | 12 ++++++------ 9 files changed, 51 insertions(+), 40 deletions(-) diff --git a/modules/ca/src/client/cadef.h b/modules/ca/src/client/cadef.h index fc94dfb6c..12861c384 100644 --- a/modules/ca/src/client/cadef.h +++ b/modules/ca/src/client/cadef.h @@ -559,19 +559,19 @@ LIBCA_API chid epicsStdCall ca_evid_to_chid ( evid id ); /* * ca_pend_event() * - * timeOut R wait for this delay in seconds + * timeout R wait for this delay in seconds */ -LIBCA_API int epicsStdCall ca_pend_event (ca_real timeOut); +LIBCA_API int epicsStdCall ca_pend_event (ca_real timeout); #define ca_poll() ca_pend_event(1e-12) /* * ca_pend_io() * - * timeOut R wait for this delay in seconds but return early + * timeout R wait for this delay in seconds but return early * if all get requests (or search requests with null * connection handler pointer have completed) */ -LIBCA_API int epicsStdCall ca_pend_io (ca_real timeOut); +LIBCA_API int epicsStdCall ca_pend_io (ca_real timeout); /* calls ca_pend_io() if early is true otherwise ca_pend_event() is called */ LIBCA_API int epicsStdCall ca_pend (ca_real timeout, int early); diff --git a/modules/libcom/src/osi/epicsEvent.cpp b/modules/libcom/src/osi/epicsEvent.cpp index d8b2533eb..1797366f4 100644 --- a/modules/libcom/src/osi/epicsEvent.cpp +++ b/modules/libcom/src/osi/epicsEvent.cpp @@ -70,9 +70,9 @@ void epicsEvent::wait () } } -bool epicsEvent::wait (double timeOut) +bool epicsEvent::wait (double timeout) { - epicsEventStatus status = epicsEventWaitWithTimeout (this->id, timeOut); + epicsEventStatus status = epicsEventWaitWithTimeout (this->id, timeout); if (status == epicsEventOK) { return true; diff --git a/modules/libcom/src/osi/epicsEvent.h b/modules/libcom/src/osi/epicsEvent.h index 8cc16fe61..4fd2d338a 100644 --- a/modules/libcom/src/osi/epicsEvent.h +++ b/modules/libcom/src/osi/epicsEvent.h @@ -99,10 +99,12 @@ public: **/ void wait (); /**\brief Wait for the event or until the specified timeout. - * \param timeOut The timeout delay in seconds. + * \param timeout The timeout delay in seconds. A timeout of zero is + * equivalent to calling tryWait(); NaN or any value too large to be + * represented to the target OS is equivalent to no timeout. * \return True if the event was triggered, False if it timed out. **/ - bool wait ( double timeOut ); + bool wait ( double timeout ); /**\brief Similar to wait() except that if the event is currently empty the * call will return immediately. * \return True if the event was full (triggered), False if empty. @@ -190,11 +192,13 @@ LIBCOM_API void epicsEventMustWait(epicsEventId id); /**\brief Wait an the event or until the specified timeout period is over. * \note Blocks until full or timeout. * \param id The event identifier. - * \param timeOut The timeout delay in seconds. + * \param timeout The timeout delay in seconds. A timeout of zero is + * equivalent to calling epicsEventTryWait(); NaN or any value too large + * to be represented to the target OS is equivalent to no timeout. * \return Status indicator. **/ LIBCOM_API epicsEventStatus epicsEventWaitWithTimeout( - epicsEventId id, double timeOut); + epicsEventId id, double timeout); /**\brief Similar to wait() except that if the event is currently empty the * call will return immediately with status \c epicsEventWaitTimeout. diff --git a/modules/libcom/src/osi/epicsMessageQueue.h b/modules/libcom/src/osi/epicsMessageQueue.h index 8240c7a5c..946195067 100644 --- a/modules/libcom/src/osi/epicsMessageQueue.h +++ b/modules/libcom/src/osi/epicsMessageQueue.h @@ -84,6 +84,9 @@ public: /** * \brief Send a message or timeout. + * \param timeout The timeout delay in seconds. A timeout of zero is + * equivalent to calling trySend(); NaN or any value too large to be + * represented to the target OS is equivalent to no timeout. * \returns 0 if the message was sent to a receiver or queued for * future delivery. * \returns -1 if the timeout was reached before the @@ -124,12 +127,16 @@ public: int receive ( void *message, unsigned int size ); /** - * \brief Wait for a message to be queued. - * Wait up to \p timeout seconds for a message to be sent if the queue - * is empty, then move the first message to the specified location. + * \brief Wait for and fetch the next message. + * \param timeout The timeout delay in seconds. A timeout of zero is + * equivalent to calling tryReceive(); NaN or any value too large to + * be represented to the target OS is equivalent to no timeout. * - * If the received message is larger than the specified - * messageBufferSize it may either return -1, or truncate the + * Waits up to \p timeout seconds for a message to arrive if the queue + * is empty, then moves the first message to the specified location. + * + * If the received message is larger than the specified message size + * the implementation may either return -1, or truncate the * message. It is most efficient if the messageBufferSize is equal * to the maximumMessageSize with which the message queue was * created. diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdEvent.c b/modules/libcom/src/osi/os/RTEMS-posix/osdEvent.c index abd9a8e9a..8c2c81e3e 100644 --- a/modules/libcom/src/osi/os/RTEMS-posix/osdEvent.c +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdEvent.c @@ -62,7 +62,7 @@ epicsEventWait(epicsEventId pSem) } LIBCOM_API epicsEventStatus -epicsEventWaitWithTimeout(epicsEventId pSem, double timeOut) +epicsEventWaitWithTimeout(epicsEventId pSem, double timeout) { int sc; rtems_interval delay; @@ -71,22 +71,22 @@ epicsEventWaitWithTimeout(epicsEventId pSem, double timeOut) if (!rate) return epicsEventError; - if (timeOut <= 0.0) { + if (timeout <= 0.0) { sc = rtems_binary_semaphore_try_wait(&pSem->rbs); if (!sc) return epicsEventOK; else return epicsEventWaitTimeout; } - else if (timeOut < (double) UINT32_MAX / rate) { - delay = timeOut * rate; + else if (timeout < (double) UINT32_MAX / rate) { + delay = timeout * rate; if (delay == 0) { - /* 0 < timeOut < 1/rate; round up */ + /* 0 < timeout < 1/rate; round up */ delay = 1; } } else { - /* timeOut is NaN or too big to represent; wait forever */ + /* timeout is NaN or too big to represent; wait forever */ delay = RTEMS_NO_TIMEOUT; } diff --git a/modules/libcom/src/osi/os/RTEMS-score/osdEvent.c b/modules/libcom/src/osi/os/RTEMS-score/osdEvent.c index 7cad7b9b8..d81538c7f 100644 --- a/modules/libcom/src/osi/os/RTEMS-score/osdEvent.c +++ b/modules/libcom/src/osi/os/RTEMS-score/osdEvent.c @@ -122,17 +122,17 @@ epicsEventWait(epicsEventId id) } epicsEventStatus -epicsEventWaitWithTimeout(epicsEventId id, double timeOut) +epicsEventWaitWithTimeout(epicsEventId id, double timeout) { rtems_id sid = (rtems_id)id; rtems_status_code sc; rtems_interval delay; extern double rtemsTicksPerSecond_double; - if (timeOut <= 0.0) + if (timeout <= 0.0) return epicsEventTryWait(id); SEMSTAT(1) - delay = timeOut * rtemsTicksPerSecond_double; + delay = timeout * rtemsTicksPerSecond_double; if (delay == 0) delay++; sc = rtems_semaphore_obtain (sid, RTEMS_WAIT, delay); diff --git a/modules/libcom/src/osi/os/WIN32/osdEvent.c b/modules/libcom/src/osi/os/WIN32/osdEvent.c index 62117cb16..6eb64d4ca 100644 --- a/modules/libcom/src/osi/os/WIN32/osdEvent.c +++ b/modules/libcom/src/osi/os/WIN32/osdEvent.c @@ -90,7 +90,7 @@ LIBCOM_API epicsEventStatus epicsEventWait ( epicsEventId pSem ) * epicsEventWaitWithTimeout () */ LIBCOM_API epicsEventStatus epicsEventWaitWithTimeout ( - epicsEventId pSem, double timeOut ) + epicsEventId pSem, double timeout ) { /* waitable timers use 100 nanosecond intervals, like FILETIME */ static const unsigned ivalPerSec = 10000000u; /* number of 100ns intervals per second */ @@ -101,17 +101,17 @@ LIBCOM_API epicsEventStatus epicsEventWaitWithTimeout ( HANDLE timer; LONGLONG nIvals; /* number of intervals */ - if ( timeOut <= 0.0 ) { + if ( timeout <= 0.0 ) { tmo.QuadPart = 0u; } - else if ( timeOut >= INFINITE / mSecPerSec ) { + else if ( timeout >= INFINITE / mSecPerSec ) { /* we need to apply a maximum wait time to stop an overflow. We choose (INFINITE - 1) milliseconds, to be compatible with previous WaitForSingleObject() implementation */ nIvals = (LONGLONG)(INFINITE - 1) * (ivalPerSec / mSecPerSec); tmo.QuadPart = -nIvals; /* negative value means a relative time offset for timer */ } else { - nIvals = (LONGLONG)(timeOut * ivalPerSec + 0.999999); + nIvals = (LONGLONG)(timeout * ivalPerSec + 0.999999); tmo.QuadPart = -nIvals; } diff --git a/modules/libcom/src/osi/os/vxWorks/osdEvent.c b/modules/libcom/src/osi/os/vxWorks/osdEvent.c index dc139432c..38c4d1806 100644 --- a/modules/libcom/src/osi/os/vxWorks/osdEvent.c +++ b/modules/libcom/src/osi/os/vxWorks/osdEvent.c @@ -34,24 +34,24 @@ void epicsEventDestroy(epicsEventId id) semDelete((SEM_ID)id); } -epicsEventStatus epicsEventWaitWithTimeout(epicsEventId id, double timeOut) +epicsEventStatus epicsEventWaitWithTimeout(epicsEventId id, double timeout) { int rate = sysClkRateGet(); int status; int ticks; - if (timeOut <= 0.0) { + if (timeout <= 0.0) { ticks = 0; } - else if (timeOut < (double) INT_MAX / rate) { - ticks = timeOut * rate; + else if (timeout < (double) INT_MAX / rate) { + ticks = timeout * rate; if (ticks == 0) { - /* 0 < timeOut < 1/rate; round up */ + /* 0 < timeout < 1/rate; round up */ ticks = 1; } } else { - /* timeOut is NaN or too big to represent in ticks */ + /* timeout is NaN or too big to represent in ticks */ ticks = WAIT_FOREVER; } status = semTake((SEM_ID)id, ticks); diff --git a/modules/libcom/src/osi/os/vxWorks/osdMessageQueue.cpp b/modules/libcom/src/osi/os/vxWorks/osdMessageQueue.cpp index d06952209..fe3ef1563 100644 --- a/modules/libcom/src/osi/os/vxWorks/osdMessageQueue.cpp +++ b/modules/libcom/src/osi/os/vxWorks/osdMessageQueue.cpp @@ -30,15 +30,15 @@ LIBCOM_API int epicsStdCall epicsMessageQueueSendWithTimeout( if (timeout <= 0.0) { ticks = 0; } - else if (timeOut < (double) INT_MAX / rate) { + else if (timeout < (double) INT_MAX / rate) { ticks = timeout * rate; if (ticks == 0) { - /* 0 < timeOut < 1/rate; round up */ + /* 0 < timeout < 1/rate; round up */ ticks = 1; } } else { - /* timeOut is NaN or too big to represent in ticks */ + /* timeout is NaN or too big to represent in ticks */ ticks = WAIT_FOREVER; } @@ -57,15 +57,15 @@ LIBCOM_API int epicsStdCall epicsMessageQueueReceiveWithTimeout( if (timeout <= 0.0) { ticks = 0; } - else if (timeOut < (double) INT_MAX / rate) { + else if (timeout < (double) INT_MAX / rate) { ticks = timeout * rate; if (ticks == 0) { - /* 0 < timeOut < 1/rate, round up */ + /* 0 < timeout < 1/rate, round up */ ticks = 1; } } else { - /* timeOut is NaN or too big to represent in ticks */ + /* timeout is NaN or too big to represent in ticks */ ticks = WAIT_FOREVER; } From 1655d68ec4ff044de069e986060d6bed2bff8ce1 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 5 Jan 2022 12:04:02 -0600 Subject: [PATCH 5/6] Fix for NaN/overflow timeout in RTEMS-score osdEvent --- modules/libcom/src/osi/os/RTEMS-score/osdEvent.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/modules/libcom/src/osi/os/RTEMS-score/osdEvent.c b/modules/libcom/src/osi/os/RTEMS-score/osdEvent.c index d81538c7f..277e7882f 100644 --- a/modules/libcom/src/osi/os/RTEMS-score/osdEvent.c +++ b/modules/libcom/src/osi/os/RTEMS-score/osdEvent.c @@ -20,6 +20,7 @@ #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1 #include +#include #include #include @@ -132,9 +133,17 @@ epicsEventWaitWithTimeout(epicsEventId id, double timeout) if (timeout <= 0.0) return epicsEventTryWait(id); SEMSTAT(1) - delay = timeout * rtemsTicksPerSecond_double; - if (delay == 0) - delay++; + if (timeout < (double) UINT32_MAX / rtemsTicksPerSecond_double) { + delay = timeout * rtemsTicksPerSecond_double; + if (delay == 0) { + /* 0 < timeout < 1/rtemsTicksPerSecond, round up */ + delay++; + } + } + else { + /* timeout is NaN or too big to represent in ticks */ + delay = RTEMS_NO_TIMEOUT; + } sc = rtems_semaphore_obtain (sid, RTEMS_WAIT, delay); if (sc == RTEMS_SUCCESSFUL) return epicsEventOK; From 36f11fba954a11221a802299f7a3ef244fd8aee6 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 24 Jan 2022 12:43:36 -0600 Subject: [PATCH 6/6] Release Notes update for epicsEvent --- documentation/RELEASE_NOTES.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/documentation/RELEASE_NOTES.md b/documentation/RELEASE_NOTES.md index 0005240ed..f526aa132 100644 --- a/documentation/RELEASE_NOTES.md +++ b/documentation/RELEASE_NOTES.md @@ -16,6 +16,17 @@ should also be read to understand what has changed since earlier releases. +### Fix embedded implementations of `epicsEvent` + +[GH:202](https://github.com/epics-base/epics-base/issues/202) and +[GH:206](https://github.com/epics-base/epics-base/pull/206) + +Heinz Junkes provided a new implementation of the `epicsEvent` API suitable for +RTEMS Posix targets (RTEMS 5.1 and later). In review a few issues related to +overflow of timeout values surfaced in this and other embedded implementations, +and these were also been fixed in this Pull Request. The API documentation for +this and some other routines has also been updated. + ## EPICS Release 7.0.6.1