This is Unofficial EPICS BASE Doxygen Site
osdSpin.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2012 Helmholtz-Zentrum Berlin
3 * fuer Materialien und Energie GmbH.
4 * Copyright (c) 2012 ITER Organization.
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 /*
10  * Author: Ralph Lange <Ralph.Lange@gmx.de>
11  */
12 
13 #include <unistd.h>
14 #include <errno.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <pthread.h>
18 
19 #include "errlog.h"
20 #include "cantProceed.h"
21 #include "epicsSpin.h"
22 
23 /* POSIX spinlocks may be subject to priority inversion
24  * and so can't be guaranteed safe in situations where
25  * threads have different priorities, and thread
26  * preemption can't be disabled.
27  */
28 #if defined(DONT_USE_POSIX_THREAD_PRIORITY_SCHEDULING)
29 #if defined(_POSIX_SPIN_LOCKS) && (_POSIX_SPIN_LOCKS > 0)
30 # define USE_PSPIN
31 #endif
32 #endif
33 
34 #define checkStatus(status,message) \
35  if ((status)) { \
36  errlogPrintf("epicsSpin %s failed: error %s\n", \
37  (message), strerror((status))); \
38  }
39 
40 #ifdef USE_PSPIN
41 
42 /*
43  * POSIX SPIN LOCKS IMPLEMENTATION
44  */
45 
46 typedef struct epicsSpin {
47  pthread_spinlock_t lock;
48 } epicsSpin;
49 
51  epicsSpin *spin;
52  int status;
53 
54  spin = calloc(1, sizeof(*spin));
55  if (!spin)
56  goto fail;
57 
58  status = pthread_spin_init(&spin->lock, PTHREAD_PROCESS_PRIVATE);
59  checkStatus(status, "pthread_spin_init");
60  if (status)
61  goto fail;
62 
63  return spin;
64 
65 fail:
66  free(spin);
67  return NULL;
68 }
69 
70 void epicsSpinDestroy(epicsSpinId spin) {
71  int status;
72 
73  status = pthread_spin_destroy(&spin->lock);
74  checkStatus(status, "pthread_spin_destroy");
75 
76  free(spin);
77 }
78 
79 void epicsSpinLock(epicsSpinId spin) {
80  int status;
81 
82  status = pthread_spin_lock(&spin->lock);
83  checkStatus(status, "pthread_spin_lock");
84  if (status)
86 }
87 
88 int epicsSpinTryLock(epicsSpinId spin) {
89  int status;
90 
91  status = pthread_spin_trylock(&spin->lock);
92  if (status == EBUSY)
93  return 1;
94  checkStatus(status, "pthread_spin_trylock");
95  return status;
96 }
97 
98 void epicsSpinUnlock(epicsSpinId spin) {
99  int status;
100 
101  status = pthread_spin_unlock(&spin->lock);
102  checkStatus(status, "pthread_spin_unlock");
103 }
104 
105 #else /* USE_PSPIN */
106 
107 /*
108  * POSIX MUTEX IMPLEMENTATION
109  */
110 
111 typedef struct epicsSpin {
112  pthread_mutex_t lock;
113 } epicsSpin;
114 
116  epicsSpin *spin;
117  int status;
118 
119  spin = calloc(1, sizeof(*spin));
120  if (!spin)
121  goto fail;
122 
123  status = pthread_mutex_init(&spin->lock, NULL);
124  checkStatus(status, "pthread_mutex_init");
125  if (status)
126  goto fail;
127 
128  return spin;
129 
130 fail:
131  free(spin);
132  return NULL;
133 }
134 
136  int status;
137 
138  status = pthread_mutex_destroy(&spin->lock);
139  checkStatus(status, "pthread_mutex_destroy");
140 
141  free(spin);
142 }
143 
145  int status;
146 
147  status = pthread_mutex_lock(&spin->lock);
148  checkStatus(status, "pthread_mutex_lock");
149  if (status)
150  cantProceed(NULL);
151 }
152 
154  int status;
155 
156  status = pthread_mutex_trylock(&spin->lock);
157  if (status == EBUSY)
158  return 1;
159  checkStatus(status, "pthread_mutex_trylock");
160  return status;
161 }
162 
164  int status;
165 
166  status = pthread_mutex_unlock(&spin->lock);
167  checkStatus(status, "pthread_mutex_unlock");
168 }
169 
170 #endif /* USE_PSPIN */
171 
172 
174 {
176  if(!ret)
177  cantProceed("epicsSpinMustCreate: epicsSpinCreate failed.");
178  return ret;
179 }
pvd::Status status
#define NULL
Definition: catime.c:38
void epicsSpinLock(epicsSpinId spin)
Definition: osdSpin.c:59
pthread_mutex_t lock
Definition: osdSpin.c:112
int epicsSpinTryLock(epicsSpinId spin)
Definition: osdSpin.c:70
void epicsSpinDestroy(epicsSpinId spin)
Definition: osdSpin.c:54
void epicsSpinUnlock(epicsSpinId spin)
Definition: osdSpin.c:81
LIBCOM_API void cantProceed(const char *msg,...)
Definition: cantProceed.c:54
Routines for code that can&#39;t continue or return after an error.
epicsSpinId epicsSpinMustCreate(void)
Definition: osdSpin.c:46
#define checkStatus(status, message)
Definition: osdSpin.c:34
epicsSpinId epicsSpinCreate(void)
Definition: osdSpin.c:28
struct epicsSpin epicsSpin
epicsMutexId lock
Definition: osdSpin.c:25