This is Unofficial EPICS BASE Doxygen Site
osdEvent.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 /* osi/os/posix/osdEvent.c */
10 
11 /* Author: Marty Kraimer Date: 13AUG1999 */
12 
13 #include <stddef.h>
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdio.h>
18 #include <errno.h>
19 #include <unistd.h>
20 #include <pthread.h>
21 
22 #include "epicsEvent.h"
23 #include "epicsTime.h"
24 #include "errlog.h"
25 
26 struct epicsEventOSD {
27  pthread_mutex_t mutex;
28  pthread_cond_t cond;
29  int isFull;
30 };
31 
32 #define printStatus(status, routine, func) \
33  errlogPrintf("%s: %s failed: %s\n", (func), (routine), strerror(status))
34 
35 #define checkStatus(status, routine, func) \
36  if (status) { \
37  printStatus(status, routine, func); \
38  }
39 
40 #define checkStatusReturn(status, routine, func) \
41  if (status) { \
42  printStatus(status, routine, func); \
43  return epicsEventError; \
44  }
45 
46 
48 {
49  epicsEventId pevent = malloc(sizeof(*pevent));
50 
51  if (pevent) {
52  int status = pthread_mutex_init(&pevent->mutex, 0);
53 
54  pevent->isFull = (init == epicsEventFull);
55  if (status) {
56  printStatus(status, "pthread_mutex_init", "epicsEventCreate");
57  } else {
58  status = pthread_cond_init(&pevent->cond, 0);
59  if (!status)
60  return pevent;
61  printStatus(status, "pthread_cond_init", "epicsEventCreate");
62  status = pthread_mutex_destroy(&pevent->mutex);
63  checkStatus(status, "pthread_mutex_destroy", "epicsEventCreate");
64  }
65  free(pevent);
66  }
67  return NULL;
68 }
69 
70 LIBCOM_API void epicsEventDestroy(epicsEventId pevent)
71 {
72  int status = pthread_mutex_destroy(&pevent->mutex);
73 
74  checkStatus(status, "pthread_mutex_destroy", "epicsEventDestroy");
75  status = pthread_cond_destroy(&pevent->cond);
76  checkStatus(status, "pthread_cond_destroy", "epicsEventDestroy");
77  free(pevent);
78 }
79 
81 {
82  int status = pthread_mutex_lock(&pevent->mutex);
83 
84  checkStatusReturn(status, "pthread_mutex_lock", "epicsEventTrigger");
85  if (!pevent->isFull) {
86  pevent->isFull = 1;
87  status = pthread_cond_signal(&pevent->cond);
88  checkStatus(status, "pthread_cond_signal", "epicsEventTrigger");
89  }
90  status = pthread_mutex_unlock(&pevent->mutex);
91  checkStatusReturn(status, "pthread_mutex_unlock", "epicsEventTrigger");
92  return epicsEventOK;
93 }
94 
96 {
98  int status = pthread_mutex_lock(&pevent->mutex);
99 
100  checkStatusReturn(status, "pthread_mutex_lock", "epicsEventWait");
101  while (!pevent->isFull) {
102  status = pthread_cond_wait(&pevent->cond, &pevent->mutex);
103  if (status) {
104  printStatus(status, "pthread_cond_wait", "epicsEventWait");
105  result = epicsEventError;
106  goto release;
107  }
108  }
109  pevent->isFull = 0;
110  result = epicsEventOK;
111 release:
112  status = pthread_mutex_unlock(&pevent->mutex);
113  checkStatusReturn(status, "pthread_mutex_unlock", "epicsEventWait");
114  return result;
115 }
116 
118  double timeout)
119 {
121  int status = pthread_mutex_lock(&pevent->mutex);
122 
123  checkStatusReturn(status, "pthread_mutex_lock", "epicsEventWaitWithTimeout");
124  if (!pevent->isFull) {
125  struct timespec wakeTime;
126 
127  convertDoubleToWakeTime(timeout, &wakeTime);
128  while (!status && !pevent->isFull) {
129  status = pthread_cond_timedwait(&pevent->cond, &pevent->mutex,
130  &wakeTime);
131  }
132  if (status) {
133  result = (status == ETIMEDOUT) ?
135  goto release;
136  }
137  }
138  pevent->isFull = 0;
139 release:
140  status = pthread_mutex_unlock(&pevent->mutex);
141  checkStatusReturn(status, "pthread_mutex_unlock", "epicsEventWaitWithTimeout");
142  return result;
143 }
144 
146 {
147  return epicsEventWaitWithTimeout(id, 0.0);
148 }
149 
150 LIBCOM_API void epicsEventShow(epicsEventId pevent, unsigned int level)
151 {
152  printf("epicsEvent %p: %s\n", pevent,
153  pevent->isFull ? "full" : "empty");
154  if (level > 0)
155  printf(" pthread_mutex = %p, pthread_cond = %p\n",
156  &pevent->mutex, &pevent->cond);
157 }
double timeout
Definition: pvutils.cpp:25
pvac::PutEvent result
Definition: clientSync.cpp:117
pvd::Status status
LIBCOM_API void convertDoubleToWakeTime(double timeout, struct timespec *wakeTime)
Definition: osdTime.cpp:68
#define printf
Definition: epicsStdio.h:41
pthread_cond_t cond
Definition: osdEvent.c:28
LIBCOM_API epicsEventStatus epicsEventWaitWithTimeout(epicsEventId pevent, double timeout)
Wait an the event or until the specified timeout period is over.
Definition: osdEvent.c:117
#define NULL
Definition: catime.c:38
LIBCOM_API epicsEventStatus epicsEventTrigger(epicsEventId pevent)
Trigger an event i.e. ensures the next or current call to wait completes.
Definition: osdEvent.c:80
#define checkStatusReturn(status, routine, func)
Definition: osdEvent.c:40
#define checkStatus(status, routine, func)
Definition: osdEvent.c:35
LIBCOM_API epicsEventId epicsEventCreate(epicsEventInitialState init)
Create an epicsEvent for use from C code, or return NULL.
Definition: osdEvent.c:47
LIBCOM_API void epicsEventShow(epicsEventId pevent, unsigned int level)
Display information about the semaphore.
Definition: osdEvent.c:150
#define printStatus(status, routine, func)
Definition: osdEvent.c:32
LIBCOM_API epicsEventStatus epicsEventTryWait(epicsEventId id)
Similar to wait() except that if the event is currenly empty the call will return immediately with st...
Definition: osdEvent.c:145
APIs for the epicsEvent binary semaphore.
epicsEventStatus
Return status from several C API routines.
Definition: epicsEvent.h:49
epicsEventInitialState
Possible initial states of a new epicsEvent.
Definition: epicsEvent.h:63
LIBCOM_API epicsEventStatus epicsEventWait(epicsEventId pevent)
Wait for an event.
Definition: osdEvent.c:95
Defined by POSIX Real Time.
Definition: osdTime.h:21
EPICS time-stamps (epicsTimeStamp), epicsTime C++ class and C functions for handling wall-clock times...
pthread_mutex_t mutex
Definition: osdEvent.c:27
LIBCOM_API void epicsEventDestroy(epicsEventId pevent)
Destroy an epicsEvent and any resources it holds.
Definition: osdEvent.c:70