blob: c3b39d8e5f4fd64482bba2354fb835fa49096857 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/******************************************************************************
2*(C) Copyright 2008 Marvell International Ltd.
3* All Rights Reserved
4******************************************************************************/
5/*****************************************************************************
6* Utility Library
7*
8* DESCRIPTION
9* Semaphore wrapper functions. This semaphore implementation allows
10* both shared access (multiple simulatneous readers), or exclusive
11* access (only one writer) at any given moment.
12*
13* Processes/threads wanting exclusive access have priority (a pending
14* process/thread wanting exclusive access blocks all subsequent processes/
15* threads requesting shared access until the process/thread currently having
16* exclusive access is finished).
17*
18* When nesting is enabled, if a given process+thread has the semaphore
19* locked for exclusive access, that process+thread can also simulatneously
20* engage a lock (on the same semaphore) for shared access (although access
21* will not be granted to other processes/threads), and also engage additional
22* exclusive-access locks (again, on the same semphore). These additional
23* locks must of couse be followed by corresponding unlocks before the resource
24* is actually free'ed.
25*
26* Current restriction: If a process/thread has the semaphore locked for shared
27* access, it cannot simultaneously lock the semaphore for exclusive access--all
28* shared-access locks must first be released.
29*
30* EXAMPLE USAGE
31*
32* {
33* utlSemaphore_T semaphore;
34* utlSemaphoreAttributes_T attr;
35*
36* attr = utlSEMAPHORE_ATTR_SHARING_ENABLE |
37* utlSEMAPHORE_ATTR_NESTING_ENABLE;
38* if (utlInitSemaphore(&semaphore, attr) != utlSUCCESS)
39* <handle error here>
40*
41* if (utlAcquireSharedAccess(&semaphore) != utlSUCCESS)
42* <handle error here>
43*
44* <read protected resource here>
45*
46* if (utlReleaseSharedAccess(&semaphore) != utlSUCCESS)
47* <handle error here>
48*
49* if (utlAcquireExclusiveAccess(&semaphore) != utlSUCCESS)
50* <handle error here>
51*
52* <modify protected resource here>
53*
54* if (utlReleaseExclusiveAccess(&semaphore) != utlSUCCESS)
55* <handle error here>
56*
57* }
58*
59*****************************************************************************/
60
61#include <stdio.h>
62#include <string.h>
63#include <pthread.h>
64
65#include "utlTypes.h"
66#include "utlError.h"
67#include "utlMalloc.h"
68#include "utlMutex.h"
69
70#include "utlSemaphore.h"
71#include "utlTrace.h"
72
73
74/*---------------------------------------------------------------------------*
75* FUNCTION
76* utlInitSemaphore(semaphore_p, attributes)
77* INPUT
78* semaphore_p == pointer to a valid utlSemaphore_T structure
79* attributes == semaphore attributes
80* OUTPUT
81* none
82* RETURNS
83* utlSUCCESS for success, utlFAILED for failure
84* DESCRIPTION
85* Initializes a shared-resource semaphore.
86*---------------------------------------------------------------------------*/
87utlReturnCode_T utlInitSemaphore(const utlSemaphore_P semaphore_p,
88 const utlSemaphoreAttributes_T attributes)
89{
90 int pthread_rv;
91 pthread_mutexattr_t attrs;
92 bool enable_sharing;
93 bool enable_nesting;
94
95 utlAssert(semaphore_p != NULL);
96
97 /* already initialized */
98 if (semaphore_p->initialized == true)
99 {
100 return utlSUCCESS;
101 }
102
103 /*--- initialize attributes used by all mutexs ---*/
104 {
105 int value;
106
107 /*--- set defaults ---*/
108 enable_sharing = false;
109 enable_nesting = false;
110
111 /*--- configure mutex type ---*/
112 {
113 if ((pthread_rv = pthread_mutexattr_init(&attrs)) != 0)
114 {
115 utlError(utlInitSemaphore, "Call to %s() failed, %s", "pthread_mutexattr_init", strerror(pthread_rv));
116 return utlFAILED;
117 }
118
119# if defined (__UCLIBC__)
120 value = PTHREAD_MUTEX_ERRORCHECK_NP;
121# else
122 value = PTHREAD_MUTEX_ERRORCHECK; //BIONIC and Musl
123# endif
124
125 if ((pthread_rv = pthread_mutexattr_settype(&attrs, value)) != 0)
126 {
127 utlError(utlInitSemaphore1, "Call to %s() failed, %s", "pthread_mutexattr_settype", strerror(pthread_rv));
128
129 /*--- clean ---*/
130 (void)pthread_mutexattr_destroy(&attrs);
131
132 return utlFAILED;
133 }
134 }
135
136 /*--- configure semaphore sharing flag ---*/
137 if ( attributes & utlSEMAPHORE_ATTR_SHARING_MASK)
138 {
139 switch (attributes & utlSEMAPHORE_ATTR_SHARING_MASK)
140 {
141 case utlSEMAPHORE_ATTR_SHARING_ENABLE: enable_sharing = true; break;
142
143 default:
144 utlError(utlInitSemaphore2, "Invalid %s attribute 0x%lx", "semaphore-sharing", attributes & utlSEMAPHORE_ATTR_SHARING_MASK);
145
146 /*--- clean ---*/
147 (void)pthread_mutexattr_destroy(&attrs);
148
149 return utlFAILED;
150 }
151 }
152
153 /*--- configure semaphore nesting flag ---*/
154 if ( attributes & utlSEMAPHORE_ATTR_NESTING_MASK)
155 {
156 switch (attributes & utlSEMAPHORE_ATTR_NESTING_MASK)
157 {
158 case utlSEMAPHORE_ATTR_NESTING_ENABLE: enable_nesting = true; break;
159
160 default:
161 utlError(utlInitSemaphore3, "Invalid %s attribute 0x%lx", "semaphore-nesting", attributes & utlSEMAPHORE_ATTR_NESTING_MASK);
162
163 /*--- clean ---*/
164 (void)pthread_mutexattr_destroy(&attrs);
165
166 return utlFAILED;
167 }
168 }
169
170#if !defined (BIONIC) /* PHREAD_PROCESS_SHARED not suppored in Bionic */
171 /*--- configure semaphore scope ---*/
172 if ( attributes & utlSEMAPHORE_ATTR_SCOPE_MASK)
173 {
174 switch (attributes & utlSEMAPHORE_ATTR_SCOPE_MASK)
175 {
176 case utlSEMAPHORE_ATTR_SCOPE_PROCESS_PRIVATE: value = PTHREAD_PROCESS_PRIVATE; break;
177 case utlSEMAPHORE_ATTR_SCOPE_PROCESS_SHARED: value = PTHREAD_PROCESS_SHARED; break;
178
179 default:
180 utlError(utlInitSemaphore4, "Invalid %s attribute 0x%lx", "semaphore-scope", attributes & utlSEMAPHORE_ATTR_SCOPE_MASK);
181
182 /*--- clean ---*/
183 (void)pthread_mutexattr_destroy(&attrs);
184
185 return utlFAILED;
186 }
187
188 if ((pthread_rv = pthread_mutexattr_setpshared(&attrs, value)) != 0)
189 {
190 utlError(utlInitSemaphore5, "Call to %s() failed, %s", "pthread_mutexattr_setpshared", strerror(pthread_rv));
191
192 /*--- clean ---*/
193 (void)pthread_mutexattr_destroy(&attrs);
194
195 return utlFAILED;
196 }
197 }
198#endif /* BIONIC */
199 }
200
201 /*-----------------------------------------------------------------------*/
202
203 /*--- if someone else is already initializing this semaphore ---*/
204 if (semaphore_p->initializing == true)
205 {
206 /*--- clean ---*/
207 (void)pthread_mutexattr_destroy(&attrs);
208
209 return utlSUCCESS;
210 }
211
212 /*--- Note: we don't need a strict test-and-set here, since all entities
213 trying to access this semaphore are trying to do the same thing:
214 initialize it */
215 semaphore_p->initializing = true;
216
217 /*--- initialize all mutexs ---*/
218 {
219 if ((pthread_rv = pthread_mutex_init(&(semaphore_p->in_use_mutex), &attrs)) != 0)
220 {
221 utlError(utlInitSemaphore6, "call to %s() failed, %s", "pthread_mutex_init", strerror(pthread_rv));
222
223 /*--- clean ---*/
224 (void)pthread_mutexattr_destroy(&attrs);
225
226 return utlFAILED;
227 }
228 if ((pthread_rv = pthread_mutex_init(&(semaphore_p->block_sharing_mutex), &attrs)) != 0)
229 {
230 utlError(utlInitSemaphore7, "call to %s() failed, %s", "pthread_mutex_init", strerror(pthread_rv));
231
232 /*--- clean ---*/
233 (void)pthread_mutexattr_destroy(&attrs);
234 (void)pthread_mutex_destroy(&(semaphore_p->in_use_mutex));
235
236 return utlFAILED;
237 }
238 if ((pthread_rv = pthread_mutex_init(&(semaphore_p->num_shared_mutex), &attrs)) != 0)
239 {
240 utlError(utlInitSemaphore8, "call to %s() failed, %s", "pthread_mutex_init", strerror(pthread_rv));
241
242 /*--- clean ---*/
243 (void)pthread_mutexattr_destroy(&attrs);
244 (void)pthread_mutex_destroy(&(semaphore_p->block_sharing_mutex));
245 (void)pthread_mutex_destroy(&(semaphore_p->in_use_mutex));
246
247 return utlFAILED;
248 }
249 if ((pthread_rv = pthread_mutex_init(&(semaphore_p->num_exclusive_mutex), &attrs)) != 0)
250 {
251 utlError(utlInitSemaphore9, "call to %s() failed, %s", "pthread_mutex_init", strerror(pthread_rv));
252
253 /*--- clean ---*/
254 (void)pthread_mutexattr_destroy(&attrs);
255 (void)pthread_mutex_destroy(&(semaphore_p->num_shared_mutex));
256 (void)pthread_mutex_destroy(&(semaphore_p->block_sharing_mutex));
257 (void)pthread_mutex_destroy(&(semaphore_p->in_use_mutex));
258
259 return utlFAILED;
260 }
261 }
262
263 semaphore_p->enable_sharing = enable_sharing;
264 semaphore_p->enable_nesting = enable_nesting;
265 semaphore_p->num_shared = 0; /* not locked for shared access */
266 semaphore_p->num_exclusive = 0; /* not locked for exxclusive access */
267 semaphore_p->pid = 0; /* no process has the semaphore locked */
268 semaphore_p->thread = 0; /* no thread has the semaphore locked */
269
270 semaphore_p->initializing = false;
271 semaphore_p->initialized = true;
272
273 /*-----------------------------------------------------------------------*/
274
275 /*--- destroy mutex attributes ---*/
276 if ((pthread_rv = pthread_mutexattr_destroy(&attrs)) != 0)
277 {
278 utlError(utlInitSemaphore10, "Call to %s() failed, %s", "pthread_mutexattr_destroy", strerror(pthread_rv));
279
280 /*--- clean ---*/
281 (void)pthread_mutex_destroy(&(semaphore_p->num_exclusive_mutex));
282 (void)pthread_mutex_destroy(&(semaphore_p->num_shared_mutex));
283 (void)pthread_mutex_destroy(&(semaphore_p->block_sharing_mutex));
284 (void)pthread_mutex_destroy(&(semaphore_p->in_use_mutex));
285
286 return utlFAILED;
287 }
288
289 return utlSUCCESS;
290}
291
292/*---------------------------------------------------------------------------*
293* FUNCTION
294* utlAcquireSharedAccess(semaphore_p)
295* INPUT
296* semaphore_p == pointer to a valid utlSemaphore_T structure
297* OUTPUT
298* none
299* RETURNS
300* utlSUCCESS for success, utlFAILED for failure
301* DESCRIPTION
302* Blocks waiting for shared access to a semaphore-protected resource.
303*---------------------------------------------------------------------------*/
304utlReturnCode_T utlAcquireSharedAccess(const utlSemaphore_P semaphore_p)
305{
306 int pthread_rv;
307 bool exclusively_mine;
308
309 utlAssert(semaphore_p != NULL);
310
311 /*--- if semaphore is still initializing ---*/
312 if (semaphore_p->initializing == true)
313 return utlFAILED;
314
315 utlAssert(semaphore_p->initialized == true);
316
317 /*--- if nesting is enabled ---*/
318 if (semaphore_p->enable_nesting == true)
319 {
320
321 /*--- wait for exclusive access to `pid' and `thread' fields ---*/
322 if ((pthread_rv = pthread_mutex_lock(&(semaphore_p->num_exclusive_mutex))) != 0)
323 {
324 utlError(utlAcquireSharedAccess, "call to %s() failed, %s", "pthread_mutex_lock", strerror(pthread_rv));
325 return utlFAILED;
326 }
327
328 exclusively_mine = (semaphore_p->pid == getpid()) &&
329 (pthread_equal(semaphore_p->thread, pthread_self()) == 1);
330
331 /*--- release exclusive access to `pid' and `thread' fields ---*/
332 if ((pthread_rv = pthread_mutex_unlock(&(semaphore_p->num_exclusive_mutex))) != 0)
333 {
334 utlError(utlAcquireSharedAccess1, "call to %s() failed, %s", "pthread_mutex_unlock", strerror(pthread_rv));
335 return utlFAILED;
336 }
337
338 }
339 else
340 exclusively_mine = false;
341
342 /*--- if nesting is enabled and this process/thread currently has exclusive
343 access, it is allowed to engage shared locks (but access will actually
344 be exclusive to this process/thread until ALL locks are released) */
345 if (exclusively_mine == true)
346 {
347
348 /*--- wait for exclusive access to `num_shared' field ---*/
349 if ((pthread_rv = pthread_mutex_lock(&(semaphore_p->num_shared_mutex))) != 0)
350 {
351 utlError(utlAcquireSharedAccess2, "call to %s() failed, %s", "pthread_mutex_lock", strerror(pthread_rv));
352 return utlFAILED;
353 }
354
355 semaphore_p->num_shared++;
356
357 /*--- release exclusive access to `num_shared' field ---*/
358 if ((pthread_rv = pthread_mutex_unlock(&(semaphore_p->num_shared_mutex))) != 0)
359 {
360 utlError(utlAcquireSharedAccess3, "call to %s() failed, %s", "pthread_mutex_unlock", strerror(pthread_rv));
361 return utlFAILED;
362 }
363
364 return utlSUCCESS;
365 }
366
367 /*--- block if sharing is prohibited ---*/
368 if ((pthread_rv = pthread_mutex_lock(&(semaphore_p->block_sharing_mutex))) != 0)
369 {
370 utlError(utlAcquireSharedAccess4, "call to %s() failed, %s", "pthread_mutex_lock", strerror(pthread_rv));
371 return utlFAILED;
372 }
373
374 /*--- wait for exclusive access to `num_shared' field ---*/
375 if ((pthread_rv = pthread_mutex_lock(&(semaphore_p->num_shared_mutex))) != 0)
376 {
377 utlError(utlAcquireSharedAccess5, "call to %s() failed, %s", "pthread_mutex_lock", strerror(pthread_rv));
378
379 /*--- clean ---*/
380 (void)pthread_mutex_unlock(&(semaphore_p->block_sharing_mutex));
381
382 return utlFAILED;
383 }
384
385 /*--- are we the very first wanting to share this semaphore-protected resource? ---*/
386 if (semaphore_p->num_shared++ == (unsigned int)0)
387 {
388
389 /*--- semaphore-protected resource now being accessed for sharing ---*/
390 if ((pthread_rv = pthread_mutex_lock(&(semaphore_p->in_use_mutex))) != 0)
391 {
392 utlError(utlAcquireSharedAccess6, "call to %s() failed, %s", "pthread_mutex_lock", strerror(pthread_rv));
393
394 /*--- clean ---*/
395 (void)pthread_mutex_unlock(&(semaphore_p->num_shared_mutex));
396 (void)pthread_mutex_unlock(&(semaphore_p->block_sharing_mutex));
397
398 return utlFAILED;
399 }
400 }
401
402 /*--- release exclusive access to `num_shared' field ---*/
403 if ((pthread_rv = pthread_mutex_unlock(&(semaphore_p->num_shared_mutex))) != 0)
404 {
405 utlError(utlAcquireSharedAccess7, "call to %s() failed, %s", "pthread_mutex_unlock", strerror(pthread_rv));
406
407 /*--- clean ---*/
408 (void)pthread_mutex_unlock(&(semaphore_p->block_sharing_mutex));
409
410 return utlFAILED;
411 }
412
413 /*--- if sharing is enabled, allow more shared-locks... ---*/
414 if (semaphore_p->enable_sharing == true)
415 if ((pthread_rv = pthread_mutex_unlock(&(semaphore_p->block_sharing_mutex))) != 0)
416 {
417 utlError(utlAcquireSharedAccess8, "call to %s() failed, %s", "pthread_mutex_unlock", strerror(pthread_rv));
418 return utlFAILED;
419 }
420
421 return utlSUCCESS;
422}
423
424/*---------------------------------------------------------------------------*
425* FUNCTION
426* utlReleaseSharedAccess(semaphore_p)
427* INPUT
428* semaphore_p == pointer to a valid utlSemaphore_T structure
429* OUTPUT
430* none
431* RETURNS
432* utlSUCCESS for success, utlFAILED for failure
433* DESCRIPTION
434* Signals the end of shared access to the semaphore-protected resource.
435*---------------------------------------------------------------------------*/
436utlReturnCode_T utlReleaseSharedAccess(const utlSemaphore_P semaphore_p)
437{
438 int pthread_rv;
439 bool exclusively_mine;
440
441 utlAssert(semaphore_p != NULL);
442
443 /*--- if semaphore is still initializing ---*/
444 if (semaphore_p->initializing == true)
445 return utlFAILED;
446
447 /*--- wait for exclusive access to `pid' and `thread' fields ---*/
448 if ((pthread_rv = pthread_mutex_lock(&(semaphore_p->num_exclusive_mutex))) != 0)
449 {
450 utlError(utlReleaseSharedAccess, "call to %s() failed, %s", "pthread_mutex_lock", strerror(pthread_rv));
451 return utlFAILED;
452 }
453
454 exclusively_mine = (semaphore_p->pid == getpid()) &&
455 (pthread_equal(semaphore_p->thread, pthread_self()) == 1);
456
457 /*--- release exclusive access to `pid' and `thread' fields ---*/
458 if ((pthread_rv = pthread_mutex_unlock(&(semaphore_p->num_exclusive_mutex))) != 0)
459 {
460 utlError(utlReleaseSharedAccess1, "call to %s() failed, %s", "pthread_mutex_unlock", strerror(pthread_rv));
461 return utlFAILED;
462 }
463
464 /*--- if this process/thread currently has exclusive access ---*/
465 if (exclusively_mine == true)
466 {
467
468 /*--- wait for exclusive access to `num_shared' field ---*/
469 if ((pthread_rv = pthread_mutex_lock(&(semaphore_p->num_shared_mutex))) != 0)
470 {
471 utlError(utlReleaseSharedAccess2, "call to %s() failed, %s", "pthread_mutex_lock", strerror(pthread_rv));
472 return utlFAILED;
473 }
474
475 utlAssert(semaphore_p->num_shared > (unsigned int)0);
476 semaphore_p->num_shared--;
477
478 /*--- release exclusive access to `num_shared' field ---*/
479 if ((pthread_rv = pthread_mutex_unlock(&(semaphore_p->num_shared_mutex))) != 0)
480 {
481 utlError(utlReleaseSharedAccess3, "call to %s() failed, %s", "pthread_mutex_unlock", strerror(pthread_rv));
482 return utlFAILED;
483 }
484
485 return utlSUCCESS;
486 }
487
488 /*--- wait for exclusive access to `num_shared' field ---*/
489 if ((pthread_rv = pthread_mutex_lock(&(semaphore_p->num_shared_mutex))) != 0)
490 {
491 utlError(utlReleaseSharedAccess4, "call to %s() failed, %s", "pthread_mutex_lock", strerror(pthread_rv));
492 return utlFAILED;
493 }
494
495 /*--- we the last one out? ---*/
496 utlAssert(semaphore_p->num_shared > (unsigned int)0);
497 if (--(semaphore_p->num_shared) == (unsigned int)0)
498 {
499
500 /*--- semaphore-protected resource now free ---*/
501 if ((pthread_rv = pthread_mutex_unlock(&(semaphore_p->in_use_mutex))) != 0)
502 {
503 utlError(utlReleaseSharedAccess5, "call to %s() failed, %s", "pthread_mutex_unlock", strerror(pthread_rv));
504
505 /*--- clean ---*/
506 (void)pthread_mutex_unlock(&(semaphore_p->num_shared_mutex));
507
508 return utlFAILED;
509 }
510 }
511
512 /*--- release exclusive access to `num_shared' field ---*/
513 if ((pthread_rv = pthread_mutex_unlock(&(semaphore_p->num_shared_mutex))) != 0)
514 {
515 utlError(utlReleaseSharedAccess6, "call to %s() failed, %s", "pthread_mutex_unlock", strerror(pthread_rv));
516 return utlFAILED;
517 }
518
519 return utlSUCCESS;
520}
521
522/*---------------------------------------------------------------------------*
523* FUNCTION
524* utlAcquireExclusiveAccess(semaphore_p)
525* INPUT
526* semaphore_p == pointer to a valid utlSemaphore_T structure
527* OUTPUT
528* none
529* RETURNS
530* utlSUCCESS for success, utlFAILED for failure
531* DESCRIPTION
532* Blocks waiting for exclusive access to a semaphore-protected resource.
533*---------------------------------------------------------------------------*/
534utlReturnCode_T utlAcquireExclusiveAccess(const utlSemaphore_P semaphore_p)
535{
536 int pthread_rv;
537
538 utlAssert(semaphore_p != NULL);
539
540 /*--- if semaphore is still initializing ---*/
541 if (semaphore_p->initializing == true)
542 return utlFAILED;
543
544 if ( (semaphore_p->enable_nesting == true) &&
545 (semaphore_p->pid == getpid()) &&
546 (pthread_equal(semaphore_p->thread, pthread_self()) == 1))
547 {
548 /* Same thread: Do nothing */
549 }
550 else
551 {
552 /*--- semaphore-protected resource now being accessed exclusively by us ---*/
553 if ((pthread_rv = pthread_mutex_lock(&(semaphore_p->in_use_mutex))) != 0)
554 {
555 utlError(utlAcquireExclusiveAccess, "call to %s() failed, %s", "pthread_mutex_lock", strerror(pthread_rv));
556
557 return utlFAILED;
558 }
559 }
560
561 /*--- wait for exclusive access to `num_exclusive', `pid', and `thread' fields ---*/
562 if ((pthread_rv = pthread_mutex_lock(&(semaphore_p->num_exclusive_mutex))) != 0)
563 {
564 utlError(utlAcquireExclusiveAccess1, "call to %s() failed, %s", "pthread_mutex_lock", strerror(pthread_rv));
565 return utlFAILED;
566 }
567
568 semaphore_p->num_exclusive++;
569
570
571 /*--- we the very first writer? ---*/
572 if (semaphore_p->num_exclusive == (unsigned int)1)
573 {
574
575 /*--- record this process/thread as the exclusive owner ---*/
576 semaphore_p->pid = getpid();
577 semaphore_p->thread = pthread_self();
578
579 #if 0
580 /*--- block all subsequent sharing ---*/
581 if ((pthread_rv = pthread_mutex_lock(&(semaphore_p->block_sharing_mutex))) != 0)
582 {
583 utlError("call to %s() failed, %s", "pthread_mutex_lock", strerror(pthread_rv));
584 return utlFAILED;
585 }
586 #endif
587
588 /*--- else if nesting is enabled and this thread already has exclusive access ---*/
589 }
590
591 /*--- clean ---*/
592 (void)pthread_mutex_unlock(&(semaphore_p->num_exclusive_mutex));
593
594 return utlSUCCESS;
595}
596
597/*---------------------------------------------------------------------------*
598* FUNCTION
599* utlReleaseExclusiveAccess(semaphore_p)
600* INPUT
601* semaphore_p == pointer to a valid utlSemaphore_T structure
602* OUTPUT
603* none
604* RETURNS
605* utlSUCCESS for success, utlFAILED for failure
606* DESCRIPTION
607* Signals the end of exclusive access to the semaphore-protected resource.
608*---------------------------------------------------------------------------*/
609utlReturnCode_T utlReleaseExclusiveAccess(const utlSemaphore_P semaphore_p)
610{
611 int pthread_rv;
612
613 utlAssert(semaphore_p != NULL);
614
615 /*--- if semaphore is still initializing ---*/
616 if (semaphore_p->initializing == true)
617 return utlFAILED;
618
619 /*--- wait for exclusive access to `num_exclusive', `pid', and `thread' fields ---*/
620 if ((pthread_rv = pthread_mutex_lock(&(semaphore_p->num_exclusive_mutex))) != 0)
621 {
622 utlError(utlReleaseExclusiveAccess, "call to %s() failed, %s", "pthread_mutex_lock", strerror(pthread_rv));
623 return utlFAILED;
624 }
625
626 /*--- no more writers? ---*/
627 utlAssert(semaphore_p->num_exclusive > (unsigned int)0);
628
629 semaphore_p->num_exclusive--;
630 /*--- clean ---*/
631 (void)pthread_mutex_unlock(&(semaphore_p->num_exclusive_mutex));
632
633
634 if (semaphore_p->num_exclusive == (unsigned int)0)
635 {
636
637 /*--- sanity check ---*/
638 if ( (semaphore_p->pid != getpid()) ||
639 (pthread_equal(semaphore_p->thread, pthread_self()) != 1))
640 {
641 utlError(utlReleaseExclusiveAccess1, "Semaphore 0x%x was not locked for write by this process and thread\n", semaphore_p);
642
643 return utlFAILED;
644 }
645
646 /*--- wait for exclusive access to `num_exclusive', `pid', and `thread' fields ---*/
647 if ((pthread_rv = pthread_mutex_lock(&(semaphore_p->num_exclusive_mutex))) != 0)
648 {
649 utlError(utlReleaseExclusiveAccess2, "call to %s() failed, %s", "pthread_mutex_lock", strerror(pthread_rv));
650 return utlFAILED;
651 }
652
653 /*--- unmark this process/thread as the current owner ---*/
654 semaphore_p->pid = 0;
655 semaphore_p->thread = 0;
656
657 /*--- clean ---*/
658 (void)pthread_mutex_unlock(&(semaphore_p->num_exclusive_mutex));
659
660 /*--- unblock sharing ---*/
661 #if 0
662 if ((pthread_rv = pthread_mutex_unlock(&(semaphore_p->block_sharing_mutex))) != 0)
663 {
664 utlError("call to %s() failed, %s", "pthread_mutex_unlock", strerror(pthread_rv));
665
666 return utlFAILED;
667 }
668 #endif
669
670 /*--- semaphore-protected resource now free ---*/
671 if ((pthread_rv = pthread_mutex_unlock(&(semaphore_p->in_use_mutex))) != 0)
672 {
673 utlError(utlReleaseExclusiveAccess3, "call to %s() failed, %s", "pthread_mutex_unlock", strerror(pthread_rv));
674 return utlFAILED;
675 }
676 }
677
678 return utlSUCCESS;
679}
680
681#if defined(utlDEBUG) || defined(utlTEST)
682
683/*---------------------------------------------------------------------------*
684 * FUNCTION
685 * utlMutexState(mutex_p)
686 * INPUT
687 * mutex_p == pointer to a mutex
688 * OUTPUT
689 * none
690 * RETURNS
691 * a pointer to a character string
692 * DESCRIPTION
693 * Determines if the specified mutex is locked or unlocked.
694 *--------------------------------------------------------------------------*/
695static char *utlMutexState(pthread_mutex_t *mutex_p)
696{
697 int pthread_rv;
698
699 utlAssert(mutex_p != NULL);
700
701 if ((pthread_rv = pthread_mutex_trylock(mutex_p)) != 0)
702 {
703
704 /*--- was mutex locked? ---*/
705 if ((pthread_rv == EBUSY) ||
706 (pthread_rv == EDEADLK))
707 return "Locked";
708
709 /*--- we'll assume if trylock returns failure, that the mutex was not locked ---*/
710 return "unlocked";
711 }
712
713 /*--- pthread_mutex_trylock() leaves the mutex locked, so unlock it ---*/
714 if ((pthread_rv = pthread_mutex_unlock(mutex_p)) != 0)
715 return "unknown";
716
717 return "unlocked";
718}
719
720/*---------------------------------------------------------------------------*
721 * FUNCTION
722 * utlVStringDumpSemaphore(v_string_p, label_p, semaphore_p, prefix_p)
723 * INPUT
724 * v_string_p == pointer to an initialized utlVString_T structure
725 * label_p == pointer to a null-terminated character string, or NULL
726 * semaphore_p == pointer to a semaphore structure
727 * prefix_p == pointer to a prefix string
728 * OUTPUT
729 * *v_string_p == the updated utlVString_T structure
730 * RETURNS
731 * nothing
732 * DESCRIPTION
733 * Dumps the semaphore specified by `semaphore_p' to `v_string_p'.
734 *--------------------------------------------------------------------------*/
735void utlVStringDumpSemaphore(const utlVString_P v_string_p,
736 const char *label_p,
737 const utlSemaphore_P semaphore_p,
738 const char *prefix_p)
739{
740 utlAssert(v_string_p != NULL);
741 utlAssert(semaphore_p != NULL);
742 utlAssert(prefix_p != NULL);
743
744 (void)utlVStringPrintF(v_string_p, "%s:\n", prefix_p);
745
746 if (label_p != NULL)
747 (void)utlVStringPrintF(v_string_p, "%s: name = \"%s\"\n", prefix_p, label_p);
748
749 (void)utlVStringPrintF(v_string_p, "%s: initialized = %s\n", prefix_p, (semaphore_p->initialized == true) ? "yes" : "no");
750
751 if (semaphore_p->initialized == true)
752 {
753
754 (void)utlVStringPrintF(v_string_p, "%s: sharing = %s\n", prefix_p, (semaphore_p->enable_sharing == true) ? "enabled" : "disabled");
755 (void)utlVStringPrintF(v_string_p, "%s: nesting = %s\n", prefix_p, (semaphore_p->enable_nesting == true) ? "enabled" : "disabled");
756 (void)utlVStringPrintF(v_string_p, "%s: in-use mutex = %s\n", prefix_p, utlMutexState(&(semaphore_p->in_use_mutex )));
757 (void)utlVStringPrintF(v_string_p, "%s: block-sharing mutex = %s\n", prefix_p, utlMutexState(&(semaphore_p->block_sharing_mutex)));
758 (void)utlVStringPrintF(v_string_p, "%s: num-shared mutex = %s\n", prefix_p, utlMutexState(&(semaphore_p->num_shared_mutex )));
759 (void)utlVStringPrintF(v_string_p, "%s: num-exclusive mutex = %s\n", prefix_p, utlMutexState(&(semaphore_p->num_exclusive_mutex)));
760 (void)utlVStringPrintF(v_string_p, "%s: num shared = %d\n", prefix_p, semaphore_p->num_shared);
761 (void)utlVStringPrintF(v_string_p, "%s: num exclusive = %d\n", prefix_p, semaphore_p->num_exclusive);
762 (void)utlVStringPrintF(v_string_p, "%s: exclusive PID = 0x%x\n", prefix_p, semaphore_p->pid);
763 (void)utlVStringPrintF(v_string_p, "%s: exclusive thread = 0x%x\n", prefix_p, semaphore_p->thread);
764 }
765}
766
767/*---------------------------------------------------------------------------*
768 * FUNCTION
769 * utlDumpSemaphore(file_p, label_p, semaphore_p)
770 * INPUT
771 * file_p == pointer to an open file
772 * label_p == pointer to a null-terminated character string, or NULL
773 * semaphore_p == pointer to a semphore structure
774 * OUTPUT
775 * none
776 * RETURNS
777 * nothing
778 * DESCRIPTION
779 * Dumps the semaphore specified by `semaphore_p'.
780 *--------------------------------------------------------------------------*/
781/*void utlDumpSemaphore( FILE *file_p,
782 const char *label_p,
783 const utlSemaphore_P semaphore_p)
784 {
785 utlVString_T v_string;
786
787 utlAssert(file_p != NULL);
788 utlAssert(semaphore_p != NULL);
789
790 utlInitVString(&v_string);
791
792 utlVStringDumpSemaphore(&v_string, label_p, semaphore_p, "Semaphore");
793
794 utlVStringPuts(&v_string, file_p);
795
796 utlVStringFree(&v_string);
797 }*/
798
799#endif /* defined(utlDEBUG) || defined(utlTEST) */
800
801#ifdef utlTEST
802/*---------------------------------------------------------------------------*
803* FUNCTION
804* semaphoreTest()
805* INPUT
806* none
807* OUTPUT
808* none
809* RETURNS
810* "true" for pass, "false" for failure
811*---------------------------------------------------------------------------*/
812bool semaphoreTest(void)
813{
814 utlSemaphore_T test_semaphore;
815
816 /*--- semaphore ----------------------------------------------------------*/
817 if (utlInitSemaphore(&test_semaphore, utlSEMAPHORE_ATTR_SHARING_ENABLE |
818 utlSEMAPHORE_ATTR_NESTING_ENABLE) != utlSUCCESS)
819 {
820 (void)fprintf(stderr, "semaphoreTest: utlInitSemaphore() failed\n");
821 return false;
822 }
823
824 /*--- shared ---*/
825 if (utlAcquireSharedAccess(&test_semaphore) != utlSUCCESS)
826 {
827 (void)fprintf(stderr, "semaphoreTest: utlAcquireSharedAccess(1) failed\n");
828 return false;
829 }
830
831 if (utlReleaseSharedAccess(&test_semaphore) != utlSUCCESS)
832 {
833 (void)fprintf(stderr, "semaphoreTest: utlReleaseSharedAccess(1) failed\n");
834 return false;
835 }
836
837 /*--- mult-read ---*/
838 if (utlAcquireSharedAccess(&test_semaphore) != utlSUCCESS)
839 {
840 (void)fprintf(stderr, "semaphoreTest: utlAcquireSharedAccess(2) failed\n");
841 return false;
842 }
843
844 if (utlAcquireSharedAccess(&test_semaphore) != utlSUCCESS)
845 {
846 (void)fprintf(stderr, "semaphoreTest: utlAcquireSharedAccess(3) failed\n");
847 return false;
848 }
849
850 if (utlReleaseSharedAccess(&test_semaphore) != utlSUCCESS)
851 {
852 (void)fprintf(stderr, "semaphoreTest: utlReleaseSharedAccess(2) failed\n");
853 return false;
854 }
855
856 if (utlReleaseSharedAccess(&test_semaphore) != utlSUCCESS)
857 {
858 (void)fprintf(stderr, "semaphoreTest: utlReleaseSharedAccess(3) failed\n");
859 return false;
860 }
861
862 /*--- write ---*/
863 if (utlAcquireExclusiveAccess(&test_semaphore) != utlSUCCESS)
864 {
865 (void)fprintf(stderr, "semaphoreTest: utlAcquireExclusiveAccess(1) failed\n");
866 return false;
867 }
868
869 if (utlReleaseExclusiveAccess(&test_semaphore) != utlSUCCESS)
870 {
871 (void)fprintf(stderr, "semaphoreTest: utlReleaseExclusiveAccess(1) failed\n");
872 return false;
873 }
874
875 /*--- multi-write ---*/
876 if (utlAcquireExclusiveAccess(&test_semaphore) != utlSUCCESS)
877 {
878 (void)fprintf(stderr, "semaphoreTest: utlAcquireExclusiveAccess(2) failed\n");
879 return false;
880 }
881
882 if (utlAcquireExclusiveAccess(&test_semaphore) != utlSUCCESS)
883 {
884 (void)fprintf(stderr, "semaphoreTest: utlAcquireExclusiveAccess(3) failed\n");
885 return false;
886 }
887
888 if (utlReleaseExclusiveAccess(&test_semaphore) != utlSUCCESS)
889 {
890 (void)fprintf(stderr, "semaphoreTest: utlReleaseExclusiveAccess(2) failed\n");
891 return false;
892 }
893
894 if (utlReleaseExclusiveAccess(&test_semaphore) != utlSUCCESS)
895 {
896 (void)fprintf(stderr, "semaphoreTest: utlReleaseExclusiveAccess(3) failed\n");
897 return false;
898 }
899
900 /*--- exclusive (1) ---*/
901 if (utlAcquireExclusiveAccess(&test_semaphore) != utlSUCCESS)
902 {
903 (void)fprintf(stderr, "semaphoreTest: utlAcquireExclusiveAccess(4) failed\n");
904 return false;
905 }
906
907 if (utlAcquireSharedAccess(&test_semaphore) != utlSUCCESS)
908 {
909 (void)fprintf(stderr, "semaphoreTest: utlAcquireSharedAccess(4) failed\n");
910 return false;
911 }
912
913 if (utlReleaseSharedAccess(&test_semaphore) != utlSUCCESS)
914 {
915 (void)fprintf(stderr, "semaphoreTest: utlReleaseSharedAccess(4) failed\n");
916 return false;
917 }
918
919 if (utlReleaseExclusiveAccess(&test_semaphore) != utlSUCCESS)
920 {
921 (void)fprintf(stderr, "semaphoreTest: utlReleaseExclusiveAccess(4) failed\n");
922 return false;
923 }
924
925 /*--- exclusive (2) ---*/
926 if (utlAcquireExclusiveAccess(&test_semaphore) != utlSUCCESS)
927 {
928 (void)fprintf(stderr, "semaphoreTest: utlAcquireExclusiveAccess(5) failed\n");
929 return false;
930 }
931
932 if (utlAcquireSharedAccess(&test_semaphore) != utlSUCCESS)
933 {
934 (void)fprintf(stderr, "semaphoreTest: utlAcquireSharedAccess(5) failed\n");
935 return false;
936 }
937
938 if (utlReleaseExclusiveAccess(&test_semaphore) != utlSUCCESS)
939 {
940 (void)fprintf(stderr, "semaphoreTest: utlReleaseExclusiveAccess(5) failed\n");
941 return false;
942 }
943
944 if (utlReleaseSharedAccess(&test_semaphore) != utlSUCCESS)
945 {
946 (void)fprintf(stderr, "semaphoreTest: utlReleaseSharedAccess(5) failed\n");
947 return false;
948 }
949
950 /*--- exclusive (3) ---*/
951 if (utlAcquireExclusiveAccess(&test_semaphore) != utlSUCCESS)
952 {
953 (void)fprintf(stderr, "semaphoreTest: utlAcquireExclusiveAccess(6) failed\n");
954 return false;
955 }
956
957 if (utlAcquireExclusiveAccess(&test_semaphore) != utlSUCCESS)
958 {
959 (void)fprintf(stderr, "semaphoreTest: utlAcquireExclusiveAccess(7) failed\n");
960 return false;
961 }
962
963 if (utlAcquireSharedAccess(&test_semaphore) != utlSUCCESS)
964 {
965 (void)fprintf(stderr, "semaphoreTest: utlAcquireSharedAccess(6) failed\n");
966 return false;
967 }
968
969 if (utlAcquireSharedAccess(&test_semaphore) != utlSUCCESS)
970 {
971 (void)fprintf(stderr, "semaphoreTest: utlAcquireSharedAccess(7) failed\n");
972 return false;
973 }
974
975 if (utlReleaseExclusiveAccess(&test_semaphore) != utlSUCCESS)
976 {
977 (void)fprintf(stderr, "semaphoreTest: utlReleaseExclusiveAccess(6) failed\n");
978 return false;
979 }
980
981 if (utlReleaseSharedAccess(&test_semaphore) != utlSUCCESS)
982 {
983 (void)fprintf(stderr, "semaphoreTest: utlReleaseSharedAccess(6) failed\n");
984 return false;
985 }
986
987 if (utlReleaseExclusiveAccess(&test_semaphore) != utlSUCCESS)
988 {
989 (void)fprintf(stderr, "semaphoreTest: utlReleaseExclusiveAccess(7) failed\n");
990 return false;
991 }
992
993 if (utlReleaseSharedAccess(&test_semaphore) != utlSUCCESS)
994 {
995 (void)fprintf(stderr, "semaphoreTest: utlReleaseSharedAccess(7) failed\n");
996 return false;
997 }
998
999 /*--- exclusive (4) ---*/
1000 if (utlAcquireExclusiveAccess(&test_semaphore) != utlSUCCESS)
1001 {
1002 (void)fprintf(stderr, "semaphoreTest: utlAcquireExclusiveAccess(8) failed\n");
1003 return false;
1004 }
1005
1006 if (utlAcquireExclusiveAccess(&test_semaphore) != utlSUCCESS)
1007 {
1008 (void)fprintf(stderr, "semaphoreTest: utlAcquireExclusiveAccess(9) failed\n");
1009 return false;
1010 }
1011
1012 if (utlAcquireSharedAccess(&test_semaphore) != utlSUCCESS)
1013 {
1014 (void)fprintf(stderr, "semaphoreTest: utlAcquireSharedAccess(8) failed\n");
1015 return false;
1016 }
1017
1018 if (utlAcquireSharedAccess(&test_semaphore) != utlSUCCESS)
1019 {
1020 (void)fprintf(stderr, "semaphoreTest: utlAcquireSharedAccess(9) failed\n");
1021 return false;
1022 }
1023
1024 if (utlReleaseExclusiveAccess(&test_semaphore) != utlSUCCESS)
1025 {
1026 (void)fprintf(stderr, "semaphoreTest: utlReleaseExclusiveAccess(8) failed\n");
1027 return false;
1028 }
1029
1030 if (utlReleaseSharedAccess(&test_semaphore) != utlSUCCESS)
1031 {
1032 (void)fprintf(stderr, "semaphoreTest: utlReleaseSharedAccess(8) failed\n");
1033 return false;
1034 }
1035
1036 if (utlReleaseExclusiveAccess(&test_semaphore) != utlSUCCESS)
1037 {
1038 (void)fprintf(stderr, "semaphoreTest: utlReleaseExclusiveAccess(9) failed\n");
1039 return false;
1040 }
1041
1042 if (utlReleaseSharedAccess(&test_semaphore) != utlSUCCESS)
1043 {
1044 (void)fprintf(stderr, "semaphoreTest: utlReleaseSharedAccess(9) failed\n");
1045 return false;
1046 }
1047
1048 /*--- exclusive (5) ---*/
1049 if (utlAcquireExclusiveAccess(&test_semaphore) != utlSUCCESS)
1050 {
1051 (void)fprintf(stderr, "semaphoreTest: utlAcquireExclusiveAccess(10) failed\n");
1052 return false;
1053 }
1054
1055 if (utlAcquireSharedAccess(&test_semaphore) != utlSUCCESS)
1056 {
1057 (void)fprintf(stderr, "semaphoreTest: utlAcquireSharedAccess(10) failed\n");
1058 return false;
1059 }
1060
1061 if (utlAcquireExclusiveAccess(&test_semaphore) != utlSUCCESS)
1062 {
1063 (void)fprintf(stderr, "semaphoreTest: utlAcquireExclusiveAccess(11) failed\n");
1064 return false;
1065 }
1066
1067 if (utlAcquireSharedAccess(&test_semaphore) != utlSUCCESS)
1068 {
1069 (void)fprintf(stderr, "semaphoreTest: utlAcquireSharedAccess(11) failed\n");
1070 return false;
1071 }
1072
1073 if (utlReleaseExclusiveAccess(&test_semaphore) != utlSUCCESS)
1074 {
1075 (void)fprintf(stderr, "semaphoreTest: utlReleaseExclusiveAccess(10) failed\n");
1076 return false;
1077 }
1078
1079 if (utlReleaseExclusiveAccess(&test_semaphore) != utlSUCCESS)
1080 {
1081 (void)fprintf(stderr, "semaphoreTest: utlReleaseExclusiveAccess(11) failed\n");
1082 return false;
1083 }
1084
1085 if (utlReleaseSharedAccess(&test_semaphore) != utlSUCCESS)
1086 {
1087 (void)fprintf(stderr, "semaphoreTest: utlReleaseSharedAccess(10) failed\n");
1088 return false;
1089 }
1090
1091 if (utlReleaseSharedAccess(&test_semaphore) != utlSUCCESS)
1092 {
1093 (void)fprintf(stderr, "semaphoreTest: utlReleaseSharedAccess(11) failed\n");
1094 return false;
1095 }
1096
1097
1098 /*--- dump ---*/
1099 //utlDumpSemaphore(stdout, "test semaphore", &test_semaphore);
1100
1101
1102 return true;
1103}
1104#endif /* utlTEST */
1105