Merge Heinz & Andrew's rtems-osd-event branch into 7.0

This commit is contained in:
Andrew Johnson
2022-01-24 12:44:17 -06:00
11 changed files with 221 additions and 41 deletions
+2 -2
View File
@@ -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;
+8 -4
View File
@@ -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.
+12 -5
View File
@@ -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.
@@ -0,0 +1,116 @@
/*************************************************************************\
* 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 <stdio.h>
#include <malloc.h>
#include <stdint.h>
#include <rtems.h>
#include <rtems/error.h>
#include <rtems/thread.h>
#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;
rtems_interval 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) UINT32_MAX / rate) {
delay = timeout * rate;
if (delay == 0) {
/* 0 < timeout < 1/rate; round up */
delay = 1;
}
}
else {
/* timeout is NaN or too big to represent; wait forever */
delay = RTEMS_NO_TIMEOUT;
}
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)
{
}
@@ -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 */
@@ -20,6 +20,7 @@
#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1
#include <stdio.h>
#include <stdint.h>
#include <rtems.h>
#include <rtems/error.h>
@@ -122,19 +123,27 @@ 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;
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;
+4 -4
View File
@@ -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;
}
+12 -7
View File
@@ -34,20 +34,25 @@ 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 = WAIT_FOREVER;
} else {
ticks = timeOut * rate;
if (ticks <= 0)
}
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;
}
status = semTake((SEM_ID)id, ticks);
if (status == OK)
@@ -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);
}