This is Unofficial EPICS BASE Doxygen Site
osdEvent.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2002 The University of Saskatchewan
3 * Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
4 * National Laboratory.
5 * EPICS BASE is distributed subject to a Software License Agreement found
6 * in file LICENSE that is included with this distribution.
7 \*************************************************************************/
8 /*
9  * RTEMS osdEvent.c
10  * Author: W. Eric Norum
11  * eric@cls.usask.ca
12  * (306) 966-6055
13  */
14 
15 /*
16  * We want to access information which is
17  * normally hidden from application programs.
18  */
19 #define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1
20 
21 #include <stdio.h>
22 #include <rtems.h>
23 #include <rtems/error.h>
24 
25 #include "epicsEvent.h"
26 #include "epicsThread.h"
27 #include "errlog.h"
28 
29 /* #define EPICS_RTEMS_SEMAPHORE_STATS */
30 /*
31  * Some performance tuning instrumentation
32  */
33 #ifdef EPICS_RTEMS_SEMAPHORE_STATS
34 unsigned long semEstat[4];
35 #define SEMSTAT(i) semEstat[i]++;
36 #else
37 #define SEMSTAT(i)
38 #endif
39 
40 /*
41  * Create a simple binary semaphore
42  */
45 {
46  rtems_status_code sc;
47  rtems_id sid;
48  rtems_interrupt_level level;
49  static char c1 = 'a';
50  static char c2 = 'a';
51  static char c3 = 'a';
52 
53  sc = rtems_semaphore_create (rtems_build_name ('B', c3, c2, c1),
54  initialState,
55  RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE |
56  RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL,
57  0,
58  &sid);
59  if (sc != RTEMS_SUCCESSFUL) {
60  errlogPrintf ("Can't create binary semaphore: %s\n", rtems_status_text (sc));
61  return NULL;
62  }
63  rtems_interrupt_disable (level);
64  if (c1 == 'z') {
65  if (c2 == 'z') {
66  if (c3 == 'z') {
67  c3 = 'a';
68  }
69  else {
70  c3++;
71  }
72  c2 = 'a';
73  }
74  else {
75  c2++;
76  }
77  c1 = 'a';
78  }
79  else {
80  c1++;
81  }
82  rtems_interrupt_enable (level);
83  return (epicsEventId)sid;
84 }
85 
86 void
88 {
89  rtems_id sid = (rtems_id)id;
90  rtems_status_code sc;
91 
92  sc = rtems_semaphore_delete (sid);
93  if (sc != RTEMS_SUCCESSFUL)
94  errlogPrintf ("Can't destroy semaphore: %s\n", rtems_status_text (sc));
95 }
96 
99 {
100  rtems_id sid = (rtems_id)id;
101  rtems_status_code sc;
102 
103  sc = rtems_semaphore_release (sid);
104  if (sc == RTEMS_SUCCESSFUL)
105  return epicsEventOK;
106  errlogPrintf ("Can't release semaphore: %s\n", rtems_status_text (sc));
107  return epicsEventError;
108 }
109 
112 {
113  rtems_id sid = (rtems_id)id;
114  rtems_status_code sc;
115 
116  SEMSTAT(0)
117  sc = rtems_semaphore_obtain (sid, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
118  if (sc != RTEMS_SUCCESSFUL)
119  return epicsEventError;
120  return epicsEventOK;
121 }
122 
125 {
126  rtems_id sid = (rtems_id)id;
127  rtems_status_code sc;
128  rtems_interval delay;
129  extern double rtemsTicksPerSecond_double;
130 
131  if (timeOut <= 0.0)
132  return epicsEventTryWait(id);
133  SEMSTAT(1)
134  delay = timeOut * rtemsTicksPerSecond_double;
135  if (delay == 0)
136  delay++;
137  sc = rtems_semaphore_obtain (sid, RTEMS_WAIT, delay);
138  if (sc == RTEMS_SUCCESSFUL)
139  return epicsEventOK;
140  else if (sc == RTEMS_TIMEOUT)
141  return epicsEventWaitTimeout;
142  else
143  return epicsEventError;
144 }
145 
148 {
149  rtems_id sid = (rtems_id)id;
150  rtems_status_code sc;
151 
152  SEMSTAT(2)
153  sc = rtems_semaphore_obtain (sid, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT);
154  if (sc == RTEMS_SUCCESSFUL)
155  return epicsEventOK;
156  else if (sc == RTEMS_UNSATISFIED)
157  return epicsEventWaitTimeout;
158  else
159  return epicsEventError;
160 }
161 
162 void
163 epicsEventShow(epicsEventId id, unsigned int level)
164 {
165 #if __RTEMS_VIOLATE_KERNEL_VISIBILITY__
166  rtems_id sid = (rtems_id)id;
167  Semaphore_Control *the_semaphore;
168  Semaphore_Control semaphore;
169  Objects_Locations location;
170 
171  the_semaphore = _Semaphore_Get (sid, &location);
172  if (location != OBJECTS_LOCAL)
173  return;
174  /*
175  * Yes, there's a race condition here since an interrupt might
176  * change things while the copy is in progress, but the information
177  * is only for display, so it's not that critical.
178  */
179  semaphore = *the_semaphore;
180  _Thread_Enable_dispatch();
181  printf (" %8.8x ", (int)sid);
182  if (_Attributes_Is_counting_semaphore (semaphore.attribute_set)) {
183  printf ("Count: %d", (int)semaphore.Core_control.semaphore.count);
184  }
185  else {
186  if (_CORE_mutex_Is_locked(&semaphore.Core_control.mutex)) {
187  char name[30];
188  epicsThreadGetName ((epicsThreadId)semaphore.Core_control.mutex.holder_id, name, sizeof name);
189  printf ("Held by:%8.8x (%s) Nest count:%d",
190  (unsigned int)semaphore.Core_control.mutex.holder_id,
191  name,
192  (int)semaphore.Core_control.mutex.nest_count);
193  }
194  else {
195  printf ("Not Held");
196  }
197  }
198  printf ("\n");
199 #endif
200 }
#define printf
Definition: epicsStdio.h:41
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 SEMSTAT(i)
Definition: osdEvent.c:37
LIBCOM_API epicsEventId epicsEventCreate(epicsEventInitialState init)
Create an epicsEvent for use from C code, or return NULL.
Definition: osdEvent.c:47
double rtemsTicksPerSecond_double
Definition: osdTime.cpp:143
LIBCOM_API void epicsEventShow(epicsEventId pevent, unsigned int level)
Display information about the semaphore.
Definition: osdEvent.c:150
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
LIBCOM_API void epicsStdCall epicsThreadGetName(epicsThreadId id, char *name, size_t size)
Definition: osdThread.c:857
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
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
C++ and C descriptions for a thread.
LIBCOM_API void epicsEventDestroy(epicsEventId pevent)
Destroy an epicsEvent and any resources it holds.
Definition: osdEvent.c:70