Merge lp:~epics-core/epics-base/spinlocks into lp:~epics-core/epics-base/3.15
- spinlocks
- Merge into 3.15
Status: | Merged |
---|---|
Merged at revision: | 12404 |
Proposed branch: | lp:~epics-core/epics-base/spinlocks |
Merge into: | lp:~epics-core/epics-base/3.15 |
Diff against target: |
595 lines (+506/-3) 10 files modified
configure/os/CONFIG.Common.linuxCommon (+1/-1) configure/os/CONFIG.Common.solaris-sparc (+1/-1) configure/os/CONFIG.Common.solaris-x86 (+1/-1) src/libCom/osi/Makefile (+2/-0) src/libCom/osi/epicsSpin.h (+31/-0) src/libCom/osi/os/default/osdSpin.c (+74/-0) src/libCom/osi/os/posix/osdSpin.c (+154/-0) src/libCom/osi/os/vxWorks/osdSpin.c (+52/-0) src/libCom/test/Makefile (+5/-0) src/libCom/test/epicsSpinTest.c (+185/-0) |
To merge this branch: | bzr merge lp:~epics-core/epics-base/spinlocks |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andrew Johnson | Approve | ||
Review via email: mp+133880@code.launchpad.net |
Commit message
Description of the change
libCom/osi: add epicsSpin with default, posix, and vxWorks implementations
- posix uses pthread_spin_ interface when supported, pthread_mutex_ otherwise
- default uses epicsMutex
- vxWorks (single core) uses intLock()
Tests are based on tests for epicsMutex.
- 12388. By Andrew Johnson
-
Fix vxWorks implementation.
- 12389. By Andrew Johnson
-
Solaris & vxWorks 5.5.x fixes
Remove C++-isms.
Make internal routines static when duplicate names appear
in the epicsMutexTest.cpp code; on vxWorks and RTEMS all
test programs get linked into a single binary. - 12390. By Andrew Johnson
-
Fix for win32 builds.
Andrew Johnson (anj) wrote : | # |
I'm adding an RTEMS implementation (UP, locking interrupts) and some text for the Release Notes while merging this branch. It could use a Windows implementation, but I'm not the best person to write that so for now Windows will fall back to using an epicsMutex.
Preview Diff
1 | === modified file 'configure/os/CONFIG.Common.linuxCommon' |
2 | --- configure/os/CONFIG.Common.linuxCommon 2010-10-05 19:27:37 +0000 |
3 | +++ configure/os/CONFIG.Common.linuxCommon 2012-11-20 23:30:26 +0000 |
4 | @@ -14,7 +14,7 @@ |
5 | |
6 | CODE_CPPFLAGS = -D_REENTRANT |
7 | |
8 | -POSIX_CPPFLAGS = -D_POSIX_C_SOURCE=199506L -D_POSIX_THREADS -D_XOPEN_SOURCE=500 |
9 | +POSIX_CPPFLAGS = -D_POSIX_C_SOURCE=200112L -D_POSIX_THREADS -D_XOPEN_SOURCE=500 |
10 | POSIX_LDLIBS = -lpthread |
11 | |
12 | # -D_BSD_SOURCE for gethostname() in unistd.h as needed by cacChannelIO.cpp. |
13 | |
14 | === modified file 'configure/os/CONFIG.Common.solaris-sparc' |
15 | --- configure/os/CONFIG.Common.solaris-sparc 2010-11-19 22:38:46 +0000 |
16 | +++ configure/os/CONFIG.Common.solaris-sparc 2012-11-20 23:30:26 +0000 |
17 | @@ -20,7 +20,7 @@ |
18 | |
19 | SOLARIS_VERSION = $(subst 5.,,$(shell uname -r)) |
20 | |
21 | -POSIX_CPPFLAGS += -D_POSIX_C_SOURCE=199506L $(POSIX_CPPFLAGS_$(SOLARIS_VERSION)) |
22 | +POSIX_CPPFLAGS += -D_POSIX_C_SOURCE=200112L $(POSIX_CPPFLAGS_$(SOLARIS_VERSION)) |
23 | POSIX_CPPFLAGS += -D_XOPEN_SOURCE=500 |
24 | POSIX_LDLIBS += -lposix4 -lpthread $(POSIX_LDLIBS_$(SOLARIS_VERSION)) |
25 | |
26 | |
27 | === modified file 'configure/os/CONFIG.Common.solaris-x86' |
28 | --- configure/os/CONFIG.Common.solaris-x86 2010-11-19 22:38:46 +0000 |
29 | +++ configure/os/CONFIG.Common.solaris-x86 2012-11-20 23:30:26 +0000 |
30 | @@ -20,7 +20,7 @@ |
31 | |
32 | SOLARIS_VERSION = $(subst 5.,,$(shell uname -r)) |
33 | |
34 | -POSIX_CPPFLAGS += -D_POSIX_C_SOURCE=199506L $(POSIX_CPPFLAGS_$(SOLARIS_VERSION)) |
35 | +POSIX_CPPFLAGS += -D_POSIX_C_SOURCE=200112L $(POSIX_CPPFLAGS_$(SOLARIS_VERSION)) |
36 | POSIX_CPPFLAGS += -D_XOPEN_SOURCE=500 |
37 | POSIX_LDLIBS += -lposix4 -lpthread $(POSIX_LDLIBS_$(SOLARIS_VERSION)) |
38 | |
39 | |
40 | === modified file 'src/libCom/osi/Makefile' |
41 | --- src/libCom/osi/Makefile 2012-06-28 16:12:26 +0000 |
42 | +++ src/libCom/osi/Makefile 2012-11-20 23:30:26 +0000 |
43 | @@ -20,6 +20,7 @@ |
44 | |
45 | INC += epicsMutex.h |
46 | INC += osdMutex.h |
47 | +INC += epicsSpin.h |
48 | INC += epicsEvent.h |
49 | INC += osdEvent.h |
50 | INC += epicsMath.h |
51 | @@ -107,6 +108,7 @@ |
52 | Com_SRCS += osdThreadExtra.c |
53 | Com_SRCS += osdThreadHooks.c |
54 | Com_SRCS += osdMutex.c |
55 | +Com_SRCS += osdSpin.c |
56 | Com_SRCS += osdEvent.c |
57 | Com_SRCS += osdTime.cpp |
58 | Com_SRCS += osdProcess.c |
59 | |
60 | === added file 'src/libCom/osi/epicsSpin.h' |
61 | --- src/libCom/osi/epicsSpin.h 1970-01-01 00:00:00 +0000 |
62 | +++ src/libCom/osi/epicsSpin.h 2012-11-20 23:30:26 +0000 |
63 | @@ -0,0 +1,31 @@ |
64 | +/*************************************************************************\ |
65 | +* Copyright (c) 2012 Helmholtz-Zentrum Berlin |
66 | +* fuer Materialien und Energie GmbH. |
67 | +* Copyright (c) 2012 ITER Organization. |
68 | +* EPICS BASE is distributed subject to a Software License Agreement found |
69 | +* in file LICENSE that is included with this distribution. |
70 | +\*************************************************************************/ |
71 | + |
72 | +#ifndef epicsSpinh |
73 | +#define epicsSpinh |
74 | + |
75 | +#include "shareLib.h" |
76 | + |
77 | +#ifdef __cplusplus |
78 | +extern "C" { |
79 | +#endif |
80 | + |
81 | +typedef struct epicsSpin *epicsSpinId; |
82 | + |
83 | +epicsShareFunc epicsSpinId epicsSpinCreate(); |
84 | +epicsShareFunc void epicsSpinDestroy(epicsSpinId); |
85 | + |
86 | +epicsShareFunc void epicsSpinLock(epicsSpinId); |
87 | +epicsShareFunc int epicsSpinTryLock(epicsSpinId); |
88 | +epicsShareFunc void epicsSpinUnlock(epicsSpinId); |
89 | + |
90 | +#ifdef __cplusplus |
91 | +} |
92 | +#endif |
93 | + |
94 | +#endif /* epicsSpinh */ |
95 | |
96 | === added file 'src/libCom/osi/os/default/osdSpin.c' |
97 | --- src/libCom/osi/os/default/osdSpin.c 1970-01-01 00:00:00 +0000 |
98 | +++ src/libCom/osi/os/default/osdSpin.c 2012-11-20 23:30:26 +0000 |
99 | @@ -0,0 +1,74 @@ |
100 | +/*************************************************************************\ |
101 | +* Copyright (c) 2012 Helmholtz-Zentrum Berlin |
102 | +* fuer Materialien und Energie GmbH. |
103 | +* Copyright (c) 2012 ITER Organization. |
104 | +* EPICS BASE is distributed subject to a Software License Agreement found |
105 | +* in file LICENSE that is included with this distribution. |
106 | +\*************************************************************************/ |
107 | + |
108 | +/* |
109 | + * Author: Ralph Lange <Ralph.Lange@gmx.de> |
110 | + */ |
111 | + |
112 | +#include <stdlib.h> |
113 | + |
114 | +#define epicsExportSharedSymbols |
115 | +#include "errlog.h" |
116 | +#include "epicsMutex.h" |
117 | +#include "epicsSpin.h" |
118 | + |
119 | +/* |
120 | + * Default: EPICS MUTEX IMPLEMENTATION |
121 | + */ |
122 | + |
123 | +typedef struct epicsSpin { |
124 | + epicsMutexId lock; |
125 | +} epicsSpin; |
126 | + |
127 | +epicsSpinId epicsSpinCreate() { |
128 | + epicsSpin *spin; |
129 | + |
130 | + spin = calloc(1, sizeof(*spin)); |
131 | + if (!spin) |
132 | + goto fail; |
133 | + |
134 | + spin->lock = epicsMutexCreate(); |
135 | + if (!spin->lock) |
136 | + goto fail; |
137 | + |
138 | + return spin; |
139 | + |
140 | +fail: |
141 | + free(spin); |
142 | + return NULL; |
143 | +} |
144 | + |
145 | +void epicsSpinDestroy(epicsSpinId spin) { |
146 | + epicsMutexDestroy(spin->lock); |
147 | + free(spin); |
148 | +} |
149 | + |
150 | +void epicsSpinLock(epicsSpinId spin) { |
151 | + epicsMutexLockStatus status; |
152 | + |
153 | + status = epicsMutexLock(spin->lock); |
154 | + if (status != epicsMutexLockOK) { |
155 | + errlogPrintf("epicsSpin epicsMutexLock failed: error %s\n", |
156 | + status == epicsMutexLockTimeout ? "epicsMutexLockTimeout" : "epicsMutexLockError"); |
157 | + } |
158 | +} |
159 | + |
160 | +int epicsSpinTryLock(epicsSpinId spin) { |
161 | + epicsMutexLockStatus status; |
162 | + |
163 | + status = epicsMutexTryLock(spin->lock); |
164 | + if (status == epicsMutexLockOK) return 0; |
165 | + if (status == epicsMutexLockTimeout) return 1; |
166 | + |
167 | + errlogPrintf("epicsSpin epicsMutexTryLock failed: error epicsMutexLockError\n"); |
168 | + return 2; |
169 | +} |
170 | + |
171 | +void epicsSpinUnlock(epicsSpinId spin) { |
172 | + epicsMutexUnlock(spin->lock); |
173 | +} |
174 | |
175 | === added file 'src/libCom/osi/os/posix/osdSpin.c' |
176 | --- src/libCom/osi/os/posix/osdSpin.c 1970-01-01 00:00:00 +0000 |
177 | +++ src/libCom/osi/os/posix/osdSpin.c 2012-11-20 23:30:26 +0000 |
178 | @@ -0,0 +1,154 @@ |
179 | +/*************************************************************************\ |
180 | +* Copyright (c) 2012 Helmholtz-Zentrum Berlin |
181 | +* fuer Materialien und Energie GmbH. |
182 | +* Copyright (c) 2012 ITER Organization. |
183 | +* EPICS BASE is distributed subject to a Software License Agreement found |
184 | +* in file LICENSE that is included with this distribution. |
185 | +\*************************************************************************/ |
186 | + |
187 | +/* |
188 | + * Author: Ralph Lange <Ralph.Lange@gmx.de> |
189 | + */ |
190 | + |
191 | +#include <unistd.h> |
192 | +#include <errno.h> |
193 | +#include <stdlib.h> |
194 | +#include <string.h> |
195 | +#include <pthread.h> |
196 | + |
197 | +#include "errlog.h" |
198 | +#include "epicsSpin.h" |
199 | + |
200 | +#define checkStatus(status,message) \ |
201 | + if ((status)) { \ |
202 | + errlogPrintf("epicsSpin %s failed: error %s\n", \ |
203 | + (message), strerror((status))); \ |
204 | + } |
205 | + |
206 | +#if defined(_POSIX_SPIN_LOCKS) && (_POSIX_SPIN_LOCKS > 1) |
207 | + |
208 | +/* |
209 | + * POSIX SPIN LOCKS IMPLEMENTATION |
210 | + */ |
211 | + |
212 | +typedef struct epicsSpin { |
213 | + pthread_spinlock_t lock; |
214 | +} epicsSpin; |
215 | + |
216 | +epicsSpinId epicsSpinCreate() { |
217 | + epicsSpin *spin; |
218 | + int status; |
219 | + |
220 | + spin = calloc(1, sizeof(*spin)); |
221 | + if (!spin) |
222 | + goto fail; |
223 | + |
224 | + status = pthread_spin_init(&spin->lock, PTHREAD_PROCESS_PRIVATE); |
225 | + checkStatus(status, "pthread_spin_init"); |
226 | + if (status) |
227 | + goto fail; |
228 | + |
229 | + return spin; |
230 | + |
231 | +fail: |
232 | + free(spin); |
233 | + return NULL; |
234 | +} |
235 | + |
236 | +void epicsSpinDestroy(epicsSpinId spin) { |
237 | + int status; |
238 | + |
239 | + status = pthread_spin_destroy(&spin->lock); |
240 | + checkStatus(status, "pthread_spin_destroy"); |
241 | + |
242 | + free(spin); |
243 | +} |
244 | + |
245 | +void epicsSpinLock(epicsSpinId spin) { |
246 | + int status; |
247 | + |
248 | + status = pthread_spin_lock(&spin->lock); |
249 | + checkStatus(status, "pthread_spin_lock"); |
250 | +} |
251 | + |
252 | +int epicsSpinTryLock(epicsSpinId spin) { |
253 | + int status; |
254 | + |
255 | + status = pthread_spin_trylock(&spin->lock); |
256 | + if (status == EBUSY) |
257 | + return 1; |
258 | + checkStatus(status, "pthread_spin_trylock"); |
259 | + return 0; |
260 | +} |
261 | + |
262 | +void epicsSpinUnlock(epicsSpinId spin) { |
263 | + int status; |
264 | + |
265 | + status = pthread_spin_unlock(&spin->lock); |
266 | + checkStatus(status, "pthread_spin_unlock"); |
267 | +} |
268 | + |
269 | +#else /* defined(_POSIX_SPIN_LOCKS) && (_POSIX_SPIN_LOCKS > 1) */ |
270 | + |
271 | +/* |
272 | + * POSIX MUTEX IMPLEMENTATION |
273 | + */ |
274 | + |
275 | +typedef struct epicsSpin { |
276 | + pthread_mutex_t lock; |
277 | +} epicsSpin; |
278 | + |
279 | +epicsSpinId epicsSpinCreate() { |
280 | + epicsSpin *spin; |
281 | + int status; |
282 | + |
283 | + spin = calloc(1, sizeof(*spin)); |
284 | + if (!spin) |
285 | + goto fail; |
286 | + |
287 | + status = pthread_mutex_init(&spin->lock, NULL); |
288 | + checkStatus(status, "pthread_mutex_init"); |
289 | + if (status) |
290 | + goto fail; |
291 | + |
292 | + return spin; |
293 | + |
294 | +fail: |
295 | + free(spin); |
296 | + return NULL; |
297 | +} |
298 | + |
299 | +void epicsSpinDestroy(epicsSpinId spin) { |
300 | + int status; |
301 | + |
302 | + status = pthread_mutex_destroy(&spin->lock); |
303 | + checkStatus(status, "pthread_mutex_destroy"); |
304 | + |
305 | + free(spin); |
306 | +} |
307 | + |
308 | +void epicsSpinLock(epicsSpinId spin) { |
309 | + int status; |
310 | + |
311 | + status = pthread_mutex_lock(&spin->lock); |
312 | + checkStatus(status, "pthread_mutex_lock"); |
313 | +} |
314 | + |
315 | +int epicsSpinTryLock(epicsSpinId spin) { |
316 | + int status; |
317 | + |
318 | + status = pthread_mutex_trylock(&spin->lock); |
319 | + if (status == EBUSY) |
320 | + return 1; |
321 | + checkStatus(status, "pthread_mutex_trylock"); |
322 | + return 0; |
323 | +} |
324 | + |
325 | +void epicsSpinUnlock(epicsSpinId spin) { |
326 | + int status; |
327 | + |
328 | + status = pthread_mutex_unlock(&spin->lock); |
329 | + checkStatus(status, "pthread_mutex_unlock"); |
330 | +} |
331 | + |
332 | +#endif /* defined(_POSIX_SPIN_LOCKS) && (_POSIX_SPIN_LOCKS > 1) */ |
333 | |
334 | === added file 'src/libCom/osi/os/vxWorks/osdSpin.c' |
335 | --- src/libCom/osi/os/vxWorks/osdSpin.c 1970-01-01 00:00:00 +0000 |
336 | +++ src/libCom/osi/os/vxWorks/osdSpin.c 2012-11-20 23:30:26 +0000 |
337 | @@ -0,0 +1,52 @@ |
338 | +/*************************************************************************\ |
339 | +* Copyright (c) 2012 Helmholtz-Zentrum Berlin |
340 | +* fuer Materialien und Energie GmbH. |
341 | +* Copyright (c) 2012 ITER Organization. |
342 | +* EPICS BASE is distributed subject to a Software License Agreement found |
343 | +* in file LICENSE that is included with this distribution. |
344 | +\*************************************************************************/ |
345 | + |
346 | +/* |
347 | + * Author: Ralph Lange <Ralph.Lange@gmx.de> |
348 | + * |
349 | + * based on epicsInterrupt.c (vxWorks implementation) by Marty Kraimer |
350 | + */ |
351 | + |
352 | +/* |
353 | + * vxWorks (single CPU): LOCK INTERRUPT |
354 | + * |
355 | + * CAVEAT: |
356 | + * This implementation will not compile on vxWorks SMP architectures. |
357 | + * These architectures provide spinlocks, which must be used instead. |
358 | + * |
359 | + */ |
360 | + |
361 | +#include <stdlib.h> |
362 | +#include <intLib.h> |
363 | + |
364 | +#include "epicsSpin.h" |
365 | + |
366 | +typedef struct epicsSpin { |
367 | + int key; |
368 | +} epicsSpin; |
369 | + |
370 | +epicsSpinId epicsSpinCreate() { |
371 | + return calloc(1, sizeof(epicsSpin)); |
372 | +} |
373 | + |
374 | +void epicsSpinDestroy(epicsSpinId spin) { |
375 | + free(spin); |
376 | +} |
377 | + |
378 | +void epicsSpinLock(epicsSpinId spin) { |
379 | + spin->key = intLock(); |
380 | +} |
381 | + |
382 | +int epicsSpinTryLock(epicsSpinId spin) { |
383 | + epicsSpinLock(spin); |
384 | + return 0; |
385 | +} |
386 | + |
387 | +void epicsSpinUnlock(epicsSpinId spin) { |
388 | + intUnlock(spin->key); |
389 | +} |
390 | |
391 | === modified file 'src/libCom/test/Makefile' |
392 | --- src/libCom/test/Makefile 2012-07-06 19:23:03 +0000 |
393 | +++ src/libCom/test/Makefile 2012-11-20 23:30:26 +0000 |
394 | @@ -124,6 +124,11 @@ |
395 | testHarness_SRCS += epicsMutexTest.cpp |
396 | TESTS += epicsMutexTest |
397 | |
398 | +TESTPROD_HOST += epicsSpinTest |
399 | +epicsSpinTest_SRCS += epicsSpinTest.c |
400 | +testHarness_SRCS += epicsSpinTest.c |
401 | +TESTS += epicsSpinTest |
402 | + |
403 | TESTPROD_HOST += epicsAtomicTest |
404 | epicsAtomicTest_SRCS += epicsAtomicTest.cpp |
405 | testHarness_SRCS += epicsAtomicTest.cpp |
406 | |
407 | === added file 'src/libCom/test/epicsSpinTest.c' |
408 | --- src/libCom/test/epicsSpinTest.c 1970-01-01 00:00:00 +0000 |
409 | +++ src/libCom/test/epicsSpinTest.c 2012-11-20 23:30:26 +0000 |
410 | @@ -0,0 +1,185 @@ |
411 | +/*************************************************************************\ |
412 | +* Copyright (c) 2012 Helmholtz-Zentrum Berlin |
413 | +* fuer Materialien und Energie GmbH. |
414 | +* Copyright (c) 2012 ITER Organization. |
415 | +* EPICS BASE is distributed subject to a Software License Agreement found |
416 | +* in file LICENSE that is included with this distribution. |
417 | +\*************************************************************************/ |
418 | + |
419 | +/* |
420 | + * Author: Ralph Lange <Ralph.Lange@gmx.de> |
421 | + * |
422 | + * based on epicsMutexTest by Marty Kraimer and Jeff Hill |
423 | + * |
424 | + */ |
425 | + |
426 | +#include <stdlib.h> |
427 | +#include <stddef.h> |
428 | +#include <string.h> |
429 | +#include <stdio.h> |
430 | +#include <errno.h> |
431 | +#include <time.h> |
432 | + |
433 | +#include "epicsTime.h" |
434 | +#include "epicsThread.h" |
435 | +#include "epicsSpin.h" |
436 | +#include "epicsEvent.h" |
437 | +#include "errlog.h" |
438 | +#include "epicsUnitTest.h" |
439 | +#include "testMain.h" |
440 | + |
441 | +typedef struct info { |
442 | + int threadnum; |
443 | + epicsSpinId spin; |
444 | + int quit; |
445 | +} info; |
446 | + |
447 | +void spinThread(void *arg) |
448 | +{ |
449 | + info *pinfo = (info *) arg; |
450 | + testDiag("spinThread %d starting", pinfo->threadnum); |
451 | + while (pinfo->quit--) { |
452 | + epicsSpinLock(pinfo->spin); |
453 | + testPass("spinThread %d epicsSpinLock taken", pinfo->threadnum); |
454 | + epicsThreadSleep(.1); |
455 | + epicsSpinUnlock(pinfo->spin); |
456 | + epicsThreadSleep(.9); |
457 | + } |
458 | + testDiag("spinThread %d exiting", pinfo->threadnum); |
459 | + return; |
460 | +} |
461 | + |
462 | +static void lockPair(struct epicsSpin *spin) |
463 | +{ |
464 | + epicsSpinLock(spin); |
465 | + epicsSpinUnlock(spin); |
466 | +} |
467 | + |
468 | +static void tenLockPairs(struct epicsSpin *spin) |
469 | +{ |
470 | + lockPair(spin); |
471 | + lockPair(spin); |
472 | + lockPair(spin); |
473 | + lockPair(spin); |
474 | + lockPair(spin); |
475 | + lockPair(spin); |
476 | + lockPair(spin); |
477 | + lockPair(spin); |
478 | + lockPair(spin); |
479 | + lockPair(spin); |
480 | +} |
481 | + |
482 | +static void tenLockPairsSquared(struct epicsSpin *spin) |
483 | +{ |
484 | + tenLockPairs(spin); |
485 | + tenLockPairs(spin); |
486 | + tenLockPairs(spin); |
487 | + tenLockPairs(spin); |
488 | + tenLockPairs(spin); |
489 | + tenLockPairs(spin); |
490 | + tenLockPairs(spin); |
491 | + tenLockPairs(spin); |
492 | + tenLockPairs(spin); |
493 | + tenLockPairs(spin); |
494 | +} |
495 | + |
496 | +void epicsSpinPerformance () |
497 | +{ |
498 | + static const unsigned N = 10000; |
499 | + unsigned i; |
500 | + epicsSpinId spin; |
501 | + epicsTimeStamp begin; |
502 | + epicsTimeStamp end; |
503 | + double delay; |
504 | + |
505 | + /* Initialize spinlock */ |
506 | + spin = epicsSpinCreate(); |
507 | + |
508 | + /* test a single lock pair */ |
509 | + epicsTimeGetCurrent(&begin); |
510 | + for ( i = 0; i < N; i++ ) { |
511 | + tenLockPairsSquared(spin); |
512 | + } |
513 | + epicsTimeGetCurrent(&end); |
514 | + |
515 | + delay = epicsTimeDiffInSeconds(&end, &begin); |
516 | + delay /= N * 100u; /* convert to delay per lock pair */ |
517 | + delay *= 1e6; /* convert to micro seconds */ |
518 | + testDiag("lock()*1/unlock()*1 takes %f microseconds", delay); |
519 | +} |
520 | + |
521 | +struct verifyTryLock { |
522 | + epicsSpinId spin; |
523 | + epicsEventId done; |
524 | +}; |
525 | + |
526 | +static void verifyTryLockThread(void *pArg) |
527 | +{ |
528 | + struct verifyTryLock *pVerify = |
529 | + (struct verifyTryLock *) pArg; |
530 | + |
531 | + testOk1(epicsSpinTryLock(pVerify->spin)); |
532 | + epicsEventSignal(pVerify->done); |
533 | +} |
534 | + |
535 | +static void verifyTryLock() |
536 | +{ |
537 | + struct verifyTryLock verify; |
538 | + |
539 | + verify.spin = epicsSpinCreate(); |
540 | + verify.done = epicsEventMustCreate(epicsEventEmpty); |
541 | + |
542 | + testOk1(epicsSpinTryLock(verify.spin) == 0); |
543 | + |
544 | + epicsThreadCreate("verifyTryLockThread", 40, |
545 | + epicsThreadGetStackSize(epicsThreadStackSmall), |
546 | + verifyTryLockThread, &verify); |
547 | + |
548 | + testOk1(epicsEventWait(verify.done) == epicsEventWaitOK); |
549 | + |
550 | + epicsSpinUnlock(verify.spin); |
551 | + epicsSpinDestroy(verify.spin); |
552 | + epicsEventDestroy(verify.done); |
553 | +} |
554 | + |
555 | +MAIN(epicsSpinTest) |
556 | +{ |
557 | + const int nthreads = 3; |
558 | + const int nrounds = 5; |
559 | + unsigned int stackSize; |
560 | + epicsThreadId *id; |
561 | + int i; |
562 | + char **name; |
563 | + void **arg; |
564 | + info **pinfo; |
565 | + epicsSpinId spin; |
566 | + |
567 | + testPlan(3 + nthreads * nrounds); |
568 | + |
569 | + verifyTryLock(); |
570 | + |
571 | + spin = epicsSpinCreate(); |
572 | + |
573 | + id = (epicsThreadId *) calloc(nthreads, sizeof(epicsThreadId)); |
574 | + name = (char **) calloc(nthreads, sizeof(char *)); |
575 | + arg = (void **) calloc(nthreads, sizeof(void *)); |
576 | + pinfo = (info **) calloc(nthreads, sizeof(info *)); |
577 | + stackSize = epicsThreadGetStackSize(epicsThreadStackSmall); |
578 | + for (i = 0; i < nthreads; i++) { |
579 | + name[i] = (char *) calloc(10, sizeof(char)); |
580 | + sprintf(name[i],"task%d",i); |
581 | + pinfo[i] = (info *) calloc(1, sizeof(info)); |
582 | + pinfo[i]->threadnum = i; |
583 | + pinfo[i]->spin = spin; |
584 | + pinfo[i]->quit = nrounds; |
585 | + arg[i] = pinfo[i]; |
586 | + id[i] = epicsThreadCreate(name[i], 40, stackSize, |
587 | + spinThread, |
588 | + arg[i]); |
589 | + } |
590 | + epicsThreadSleep(2.0 + nrounds); |
591 | + |
592 | + epicsSpinPerformance(); |
593 | + |
594 | + return testDone(); |
595 | +} |
Tested on Linux, Darwin, Solaris and Windows (MS and MinGW).