This is Unofficial EPICS BASE Doxygen Site
syncgrp.cpp
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2002 The University of Chicago, 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 /*
10  * Author: Jeffrey O. Hill
11  * hill@luke.lanl.gov
12  * (505) 665 1831
13  */
14 
15 #define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
16 
17 #include "iocinf.h"
18 #include "oldAccess.h"
19 #include "syncGroup.h"
20 
21 /*
22  * ca_sg_create()
23  */
24 extern "C" int epicsStdCall ca_sg_create ( CA_SYNC_GID * pgid )
25 {
26  ca_client_context * pcac;
27  int caStatus;
28  CASG * pcasg;
29 
30  caStatus = fetchClientContext ( &pcac );
31  if ( caStatus != ECA_NORMAL ) {
32  return caStatus;
33  }
34 
35  try {
36  epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
37  pcasg = new ( pcac->casgFreeList ) CASG ( guard, *pcac );
38  *pgid = pcasg->getId ();
39  return ECA_NORMAL;
40  }
41  catch ( std::bad_alloc & ) {
42  return ECA_ALLOCMEM;
43  }
44  catch ( ... ) {
45  return ECA_INTERNAL;
46  }
47 }
48 
50  ca_client_context & cac, const CA_SYNC_GID gid )
51 {
52  int caStatus;
53  CASG * pcasg = cac.lookupCASG ( guard, gid );
54  if ( pcasg ) {
55  pcasg->destructor ( cbGuard, guard );
56  cac.casgFreeList.release ( pcasg );
57  caStatus = ECA_NORMAL;
58  }
59  else {
60  caStatus = ECA_BADSYNCGRP;
61  }
62  return caStatus;
63 }
64 
65 /*
66  * ca_sg_delete()
67  */
68 extern "C" int epicsStdCall ca_sg_delete ( const CA_SYNC_GID gid )
69 {
70  ca_client_context * pcac;
71  int caStatus = fetchClientContext ( & pcac );
72  if ( caStatus == ECA_NORMAL ) {
73  if ( pcac->pCallbackGuard.get() &&
74  pcac->createdByThread == epicsThreadGetIdSelf () ) {
75  epicsGuard < epicsMutex > guard ( pcac->mutex );
76  caStatus = ca_sync_group_destroy ( *pcac->pCallbackGuard.get(),
77  guard, *pcac, gid );
78  }
79  else {
80  //
81  // we will definately stall out here if all of the
82  // following are true
83  //
84  // o user creates non-preemtive mode client library context
85  // o user doesnt periodically call a ca function
86  // o user calls this function from an auxiillary thread
87  //
88  CallbackGuard cbGuard ( pcac->cbMutex );
89  epicsGuard < epicsMutex > guard ( pcac->mutex );
90  caStatus = ca_sync_group_destroy ( cbGuard, guard, *pcac, gid );
91  }
92  }
93  return caStatus;
94 }
95 
97 {
98  if ( client.pCallbackGuard.get() &&
99  client.createdByThread == epicsThreadGetIdSelf () ) {
100  epicsGuard < epicsMutex > guard ( client.mutex );
101  sg.reset ( *client.pCallbackGuard.get(), guard );
102  }
103  else {
104  //
105  // we will definately stall out here if all of the
106  // following are true
107  //
108  // o user creates non-preemtive mode client library context
109  // o user doesnt periodically call a ca function
110  // o user calls this function from an auxiillary thread
111  //
112  CallbackGuard cbGuard ( client.cbMutex );
113  epicsGuard < epicsMutex > guard ( client.mutex );
114  sg.reset ( cbGuard, guard );
115  }
116 }
117 
118 //
119 // ca_sg_block ()
120 //
121 // !!!! This routine is only visible in the old interface - or in a new ST interface.
122 // !!!! In the old interface we restrict thread attach so that calls from threads
123 // !!!! other than the initializing thread are not allowed if preemptive callback
124 // !!!! is disabled. This prevents the preemptive callback lock from being released
125 // !!!! by other threads than the one that locked it.
126 //
127 extern "C" int epicsStdCall ca_sg_block (
128  const CA_SYNC_GID gid, ca_real timeout )
129 {
130  ca_client_context *pcac;
131  int status = fetchClientContext ( &pcac );
132  if ( status == ECA_NORMAL ) {
133  CASG * pcasg;
134  {
135  epicsGuard < epicsMutex > guard ( pcac->mutex );
136  pcasg = pcac->lookupCASG ( guard, gid );
137  if ( pcasg ) {
138  status = pcasg->block (
139  pcac->pCallbackGuard.get (), guard, timeout );
140  }
141  else {
142  status = ECA_BADSYNCGRP;
143  }
144  }
145  if ( pcasg ) {
146  sync_group_reset ( *pcac, *pcasg );
147  }
148  }
149  return status;
150 }
151 
152 /*
153  * ca_sg_reset
154  */
155 extern "C" int epicsStdCall ca_sg_reset ( const CA_SYNC_GID gid )
156 {
157  ca_client_context *pcac;
158  int caStatus = fetchClientContext (&pcac);
159  if ( caStatus == ECA_NORMAL ) {
160  CASG * pcasg;
161  {
162  epicsGuard < epicsMutex > guard ( pcac->mutex );
163  pcasg = pcac->lookupCASG ( guard, gid );
164  }
165  if ( pcasg ) {
166  sync_group_reset ( *pcac, *pcasg );
167  caStatus = ECA_NORMAL;
168  }
169  else {
170  caStatus = ECA_BADSYNCGRP;
171  }
172  }
173  return caStatus;
174 }
175 
176 /*
177  * ca_sg_stat
178  */
179 extern "C" int epicsStdCall ca_sg_stat ( const CA_SYNC_GID gid )
180 {
181  ca_client_context * pcac;
182  int caStatus = fetchClientContext ( &pcac );
183  if ( caStatus != ECA_NORMAL ) {
184  return caStatus;
185  }
186 
187  epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
188 
189  CASG * pcasg = pcac->lookupCASG ( guard, gid );
190  if ( ! pcasg ) {
191  ::printf ( "Bad Sync Group Id\n");
192  return ECA_BADSYNCGRP;
193  }
194  pcasg->show ( guard, 1000u );
195 
196  return ECA_NORMAL;
197 }
198 
199 /*
200  * ca_sg_test
201  */
202 extern "C" int epicsStdCall ca_sg_test ( const CA_SYNC_GID gid )
203 {
204  ca_client_context * pcac;
205  int caStatus = fetchClientContext ( &pcac );
206  if ( caStatus == ECA_NORMAL ) {
207  epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
208  CASG * pcasg = pcac->lookupCASG ( guard, gid );
209  if ( pcasg ) {
210  bool isComplete;
211  if ( pcac->pCallbackGuard.get() &&
212  pcac->createdByThread == epicsThreadGetIdSelf () ) {
213  epicsGuard < epicsMutex > guard ( pcac->mutex );
214  isComplete = pcasg->ioComplete ( *pcac->pCallbackGuard.get(), guard );
215  }
216  else {
217  //
218  // we will definately stall out here if all of the
219  // following are true
220  //
221  // o user creates non-preemtive mode client library context
222  // o user doesnt periodically call a ca function
223  // o user calls this function from an auxiillary thread
224  //
225  CallbackGuard cbGuard ( pcac->cbMutex );
226  epicsGuard < epicsMutex > guard ( pcac->mutex );
227  isComplete = pcasg->ioComplete ( cbGuard, guard );
228  }
229  if ( isComplete ) {
230  caStatus = ECA_IODONE;
231  }
232  else{
233  caStatus = ECA_IOINPROGRESS;
234  }
235  }
236  else {
237  caStatus = ECA_BADSYNCGRP;
238  }
239  }
240  return caStatus;
241 }
242 
243 /*
244  * ca_sg_array_put()
245  */
246 extern "C" int epicsStdCall ca_sg_array_put ( const CA_SYNC_GID gid, chtype type,
247  arrayElementCount count, chid pChan, const void *pValue )
248 {
249  ca_client_context *pcac;
250 
251  int caStatus = fetchClientContext ( &pcac );
252  if ( caStatus != ECA_NORMAL ) {
253  return caStatus;
254  }
255 
256  epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
257  CASG * const pcasg = pcac->lookupCASG ( guard, gid );
258  if ( ! pcasg ) {
259  return ECA_BADSYNCGRP;
260  }
261 
262  try {
263  pcasg->put ( guard, pChan, type,
264  static_cast < unsigned > ( count ), pValue );
265  return ECA_NORMAL;
266  }
267  catch ( cacChannel::badString & )
268  {
269  return ECA_BADSTR;
270  }
271  catch ( cacChannel::badType & )
272  {
273  return ECA_BADTYPE;
274  }
275  catch ( cacChannel::outOfBounds & )
276  {
277  return ECA_BADCOUNT;
278  }
279  catch ( cacChannel::noWriteAccess & )
280  {
281  return ECA_NOWTACCESS;
282  }
283  catch ( cacChannel::notConnected & )
284  {
285  return ECA_DISCONN;
286  }
288  {
289  return ECA_UNAVAILINSERV;
290  }
291  catch ( cacChannel::requestTimedOut & )
292  {
293  return ECA_TIMEOUT;
294  }
295  catch ( std::bad_alloc & )
296  {
297  return ECA_ALLOCMEM;
298  }
299  catch ( ... )
300  {
301  return ECA_INTERNAL;
302  }
303 }
304 
305 /*
306  * ca_sg_array_get()
307  */
308 extern "C" int epicsStdCall ca_sg_array_get ( const CA_SYNC_GID gid, chtype type,
309  arrayElementCount count, chid pChan, void *pValue )
310 {
311  ca_client_context *pcac;
312 
313  int caStatus = fetchClientContext ( &pcac );
314  if ( caStatus != ECA_NORMAL ) {
315  return caStatus;
316  }
317 
318  epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
319  CASG * const pcasg = pcac->lookupCASG ( guard, gid );
320  if ( ! pcasg ) {
321  return ECA_BADSYNCGRP;
322  }
323 
324  try {
325  pcasg->get ( guard, pChan, type,
326  static_cast < unsigned > ( count ), pValue );
327  return ECA_NORMAL;
328  }
329  catch ( cacChannel::badString & )
330  {
331  return ECA_BADSTR;
332  }
333  catch ( cacChannel::badType & )
334  {
335  return ECA_BADTYPE;
336  }
337  catch ( cacChannel::outOfBounds & )
338  {
339  return ECA_BADCOUNT;
340  }
341  catch ( cacChannel::noReadAccess & )
342  {
343  return ECA_NORDACCESS;
344  }
345  catch ( cacChannel::notConnected & )
346  {
347  return ECA_DISCONN;
348  }
350  {
351  return ECA_UNAVAILINSERV;
352  }
353  catch ( std::bad_alloc & )
354  {
355  return ECA_ALLOCMEM;
356  }
357  catch ( ... )
358  {
359  return ECA_INTERNAL;
360  }
361 }
int epicsStdCall ca_sg_array_get(const CA_SYNC_GID gid, chtype type, arrayElementCount count, chid pChan, void *pValue)
Definition: syncgrp.cpp:308
double timeout
Definition: pvutils.cpp:25
int epicsStdCall ca_sg_test(const CA_SYNC_GID gid)
Definition: syncgrp.cpp:202
Definition: cac.h:97
pvd::Status status
#define ECA_INTERNAL
Definition: caerr.h:94
void reset(CallbackGuard &, epicsGuard< epicsMutex > &)
Definition: CASG.cpp:131
#define ECA_IOINPROGRESS
Definition: caerr.h:120
void destructor(CallbackGuard &, epicsGuard< epicsMutex > &guard)
Definition: CASG.cpp:37
#define printf
Definition: epicsStdio.h:41
unsigned CA_SYNC_GID
Definition: cadef.h:113
pvd::StructureConstPtr type
#define ECA_BADCOUNT
Definition: caerr.h:99
#define ECA_IODONE
Definition: caerr.h:119
epicsMutex & mutexRef() const
#define ECA_DISCONN
Definition: caerr.h:101
int epicsStdCall ca_sg_stat(const CA_SYNC_GID gid)
Definition: syncgrp.cpp:179
int epicsStdCall ca_sg_reset(const CA_SYNC_GID gid)
Definition: syncgrp.cpp:155
double ca_real
Definition: cadef.h:49
#define ECA_NORMAL
Definition: caerr.h:77
int ca_sync_group_destroy(CallbackGuard &cbGuard, epicsGuard< epicsMutex > &guard, ca_client_context &cac, const CA_SYNC_GID gid)
Definition: syncgrp.cpp:49
Definition: server.h:76
int block(epicsGuard< epicsMutex > *pcbGuard, epicsGuard< epicsMutex > &guard, double timeout)
Definition: CASG.cpp:62
int epicsStdCall ca_sg_create(CA_SYNC_GID *pgid)
Definition: syncgrp.cpp:24
int fetchClientContext(ca_client_context **ppcac)
Definition: access.cpp:137
#define ECA_BADSYNCGRP
Definition: caerr.h:121
#define ECA_NOWTACCESS
Definition: caerr.h:124
int epicsStdCall ca_sg_block(const CA_SYNC_GID gid, ca_real timeout)
Definition: syncgrp.cpp:127
unsigned long arrayElementCount
Definition: cacIO.h:57
long chtype
Definition: cadef.h:47
#define ECA_NORDACCESS
Definition: caerr.h:123
CASG * lookupCASG(epicsGuard< epicsMutex > &, unsigned id)
int epicsStdCall ca_sg_delete(const CA_SYNC_GID gid)
Definition: syncgrp.cpp:68
void release(void *p)
Definition: tsFreeList.h:176
#define ECA_BADSTR
Definition: caerr.h:100
#define ECA_TIMEOUT
Definition: caerr.h:87
void sync_group_reset(ca_client_context &client, CASG &sg)
Definition: syncgrp.cpp:96
#define ECA_BADTYPE
Definition: caerr.h:91
int epicsStdCall ca_sg_array_put(const CA_SYNC_GID gid, chtype type, arrayElementCount count, chid pChan, const void *pValue)
Definition: syncgrp.cpp:246
#define ECA_UNAVAILINSERV
Definition: caerr.h:131
#define ECA_ALLOCMEM
Definition: caerr.h:83
LIBCOM_API epicsThreadId epicsStdCall epicsThreadGetIdSelf(void)
Definition: osdThread.c:810