VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/posix/semrw-posix.cpp@ 25704

Last change on this file since 25704 was 25704, checked in by vboxsync, 15 years ago

iprt,pdmcritsect: More flexible lock naming, added RTCritSectSetSubClass and made some RTCritSectInitEx.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 19.3 KB
Line 
1/* $Id: semrw-posix.cpp 25704 2010-01-10 20:12:30Z vboxsync $ */
2/** @file
3 * IPRT - Read-Write Semaphore, POSIX.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31/*******************************************************************************
32* Header Files *
33*******************************************************************************/
34#include <iprt/semaphore.h>
35#include "internal/iprt.h"
36
37#include <iprt/asm.h>
38#include <iprt/assert.h>
39#include <iprt/err.h>
40#include <iprt/lockvalidator.h>
41#include <iprt/mem.h>
42#include <iprt/thread.h>
43
44#include <errno.h>
45#include <pthread.h>
46#include <unistd.h>
47#include <sys/time.h>
48
49#include "internal/magics.h"
50#include "internal/strict.h"
51
52
53/*******************************************************************************
54* Defined Constants And Macros *
55*******************************************************************************/
56/** @todo move this to r3/posix/something.h. */
57#ifdef RT_OS_SOLARIS
58# define ATOMIC_GET_PTHREAD_T(pvVar, pThread) ASMAtomicReadSize(pvVar, pThread)
59# define ATOMIC_SET_PTHREAD_T(pvVar, pThread) ASMAtomicWriteSize(pvVar, pThread)
60#else
61AssertCompileSize(pthread_t, sizeof(void *));
62# define ATOMIC_GET_PTHREAD_T(pvVar, pThread) do { *(pThread) = (pthread_t)ASMAtomicReadPtr((void *volatile *)pvVar); } while (0)
63# define ATOMIC_SET_PTHREAD_T(pvVar, pThread) ASMAtomicWritePtr((void *volatile *)pvVar, (void *)pThread)
64#endif
65
66
67/*******************************************************************************
68* Structures and Typedefs *
69*******************************************************************************/
70/** Posix internal representation of a read-write semaphore. */
71struct RTSEMRWINTERNAL
72{
73 /** The usual magic. (RTSEMRW_MAGIC) */
74 uint32_t u32Magic;
75 /** The number of readers.
76 * (For preventing screwing up the lock on linux). */
77 uint32_t volatile cReaders;
78 /** Number of write recursions. */
79 uint32_t cWrites;
80 /** Number of read recursions by the writer. */
81 uint32_t cWriterReads;
82 /** The write owner of the lock. */
83 volatile pthread_t Writer;
84 /** pthread rwlock. */
85 pthread_rwlock_t RWLock;
86#ifdef RTSEMRW_STRICT
87 /** The validator record for the writer. */
88 RTLOCKVALRECEXCL ValidatorWrite;
89 /** The validator record for the readers. */
90 RTLOCKVALRECSHRD ValidatorRead;
91#endif
92};
93
94
95/* No debug wrapping here. */
96#undef RTSemRWRequestRead
97#undef RTSemRWRequestReadNoResume
98#undef RTSemRWRequestWrite
99#undef RTSemRWRequestWriteNoResume
100
101
102RTDECL(int) RTSemRWCreate(PRTSEMRW pRWSem)
103{
104 int rc;
105
106 /*
107 * Allocate handle.
108 */
109 struct RTSEMRWINTERNAL *pThis = (struct RTSEMRWINTERNAL *)RTMemAlloc(sizeof(struct RTSEMRWINTERNAL));
110 if (pThis)
111 {
112 /*
113 * Create the rwlock.
114 */
115 pthread_rwlockattr_t Attr;
116 rc = pthread_rwlockattr_init(&Attr);
117 if (!rc)
118 {
119 rc = pthread_rwlock_init(&pThis->RWLock, &Attr);
120 if (!rc)
121 {
122 pThis->u32Magic = RTSEMRW_MAGIC;
123 pThis->cReaders = 0;
124 pThis->cWrites = 0;
125 pThis->cWriterReads = 0;
126 pThis->Writer = (pthread_t)-1;
127#ifdef RTSEMRW_STRICT
128 RTLockValidatorRecExclInit(&pThis->ValidatorWrite, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, pThis,
129 true /*fEnabled*/, "RTSemRW");
130 RTLockValidatorRecSharedInit(&pThis->ValidatorRead, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, pThis,
131 false /*fSignaller*/, true /*fEnabled*/, "RTSemEvent");
132 RTLockValidatorRecMakeSiblings(&pThis->ValidatorWrite.Core, &pThis->ValidatorRead.Core);
133#endif
134 *pRWSem = pThis;
135 return VINF_SUCCESS;
136 }
137 }
138
139 rc = RTErrConvertFromErrno(rc);
140 RTMemFree(pThis);
141 }
142 else
143 rc = VERR_NO_MEMORY;
144
145 return rc;
146}
147
148
149RTDECL(int) RTSemRWDestroy(RTSEMRW RWSem)
150{
151 /*
152 * Validate input, nil handle is fine.
153 */
154 struct RTSEMRWINTERNAL *pThis = RWSem;
155 if (pThis == NIL_RTSEMRW)
156 return VINF_SUCCESS;
157 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
158 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
159 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
160 VERR_INVALID_HANDLE);
161 Assert(pThis->Writer == (pthread_t)-1);
162 Assert(!pThis->cReaders);
163 Assert(!pThis->cWrites);
164 Assert(!pThis->cWriterReads);
165
166 /*
167 * Try destroy it.
168 */
169 AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, ~RTSEMRW_MAGIC, RTSEMRW_MAGIC), VERR_INVALID_HANDLE);
170 int rc = pthread_rwlock_destroy(&pThis->RWLock);
171 if (!rc)
172 {
173#ifdef RTSEMRW_STRICT
174 RTLockValidatorRecSharedDelete(&pThis->ValidatorRead);
175 RTLockValidatorRecExclDelete(&pThis->ValidatorWrite);
176#endif
177 RTMemFree(pThis);
178 rc = VINF_SUCCESS;
179 }
180 else
181 {
182 ASMAtomicWriteU32(&pThis->u32Magic, RTSEMRW_MAGIC);
183 AssertMsgFailed(("Failed to destroy read-write sem %p, rc=%d.\n", RWSem, rc));
184 rc = RTErrConvertFromErrno(rc);
185 }
186
187 return rc;
188}
189
190
191DECL_FORCE_INLINE(int) rtSemRWRequestRead(RTSEMRW RWSem, unsigned cMillies, PCRTLOCKVALSRCPOS pSrcPos)
192{
193 /*
194 * Validate input.
195 */
196 struct RTSEMRWINTERNAL *pThis = RWSem;
197 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
198 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
199 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
200 VERR_INVALID_HANDLE);
201
202 /*
203 * Check if it's the writer (implement write+read recursion).
204 */
205 pthread_t Self = pthread_self();
206 pthread_t Writer;
207 ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
208 if (Writer == Self)
209 {
210#ifdef RTSEMRW_STRICT
211 int rc9 = RTLockValidatorRecExclRecursionMixed(&pThis->ValidatorWrite, &pThis->ValidatorRead.Core, pSrcPos);
212 if (RT_FAILURE(rc9))
213 return rc9;
214#endif
215 Assert(pThis->cWriterReads < INT32_MAX);
216 pThis->cWriterReads++;
217 return VINF_SUCCESS;
218 }
219
220 /*
221 * Try lock it.
222 */
223 RTTHREAD hThreadSelf = NIL_RTTHREAD;
224 if (cMillies > 0)
225 {
226#ifdef RTSEMRW_STRICT
227 hThreadSelf = RTThreadSelfAutoAdopt();
228 int rc9 = RTLockValidatorRecSharedCheckOrderAndBlocking(&pThis->ValidatorRead, hThreadSelf, pSrcPos, true,
229 cMillies, RTTHREADSTATE_RW_READ, true);
230 if (RT_FAILURE(rc9))
231 return rc9;
232#else
233 hThreadSelf = RTThreadSelf();
234 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_RW_READ, true);
235#endif
236 }
237
238 if (cMillies == RT_INDEFINITE_WAIT)
239 {
240 /* take rwlock */
241 int rc = pthread_rwlock_rdlock(&pThis->RWLock);
242 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_READ);
243 if (rc)
244 {
245 AssertMsgFailed(("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));
246 return RTErrConvertFromErrno(rc);
247 }
248 }
249 else
250 {
251#ifdef RT_OS_DARWIN
252 AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));
253 return VERR_NOT_IMPLEMENTED;
254
255#else /* !RT_OS_DARWIN */
256 /*
257 * Get current time and calc end of wait time.
258 */
259 struct timespec ts = {0,0};
260 clock_gettime(CLOCK_REALTIME, &ts);
261 if (cMillies != 0)
262 {
263 ts.tv_nsec += (cMillies % 1000) * 1000000;
264 ts.tv_sec += cMillies / 1000;
265 if (ts.tv_nsec >= 1000000000)
266 {
267 ts.tv_nsec -= 1000000000;
268 ts.tv_sec++;
269 }
270 }
271
272 /* take rwlock */
273 int rc = pthread_rwlock_timedrdlock(&pThis->RWLock, &ts);
274 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_READ);
275 if (rc)
276 {
277 AssertMsg(rc == ETIMEDOUT, ("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));
278 return RTErrConvertFromErrno(rc);
279 }
280#endif /* !RT_OS_DARWIN */
281 }
282
283 ASMAtomicIncU32(&pThis->cReaders);
284#ifdef RTSEMRW_STRICT
285 RTLockValidatorRecSharedAddOwner(&pThis->ValidatorRead, hThreadSelf, pSrcPos);
286#endif
287 return VINF_SUCCESS;
288}
289
290
291RTDECL(int) RTSemRWRequestRead(RTSEMRW RWSem, unsigned cMillies)
292{
293#ifndef RTSEMRW_STRICT
294 return rtSemRWRequestRead(RWSem, cMillies, NULL);
295#else
296 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
297 return rtSemRWRequestRead(RWSem, cMillies, &SrcPos);
298#endif
299}
300
301
302RTDECL(int) RTSemRWRequestReadDebug(RTSEMRW RWSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
303{
304 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
305 return rtSemRWRequestRead(RWSem, cMillies, &SrcPos);
306}
307
308
309RTDECL(int) RTSemRWRequestReadNoResume(RTSEMRW RWSem, unsigned cMillies)
310{
311 /* EINTR isn't returned by the wait functions we're using. */
312#ifndef RTSEMRW_STRICT
313 return rtSemRWRequestRead(RWSem, cMillies, NULL);
314#else
315 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
316 return rtSemRWRequestRead(RWSem, cMillies, &SrcPos);
317#endif
318}
319
320
321RTDECL(int) RTSemRWRequestReadNoResumeDebug(RTSEMRW RWSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
322{
323 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
324 return rtSemRWRequestRead(RWSem, cMillies, &SrcPos);
325}
326
327
328RTDECL(int) RTSemRWReleaseRead(RTSEMRW RWSem)
329{
330 /*
331 * Validate input.
332 */
333 struct RTSEMRWINTERNAL *pThis = RWSem;
334 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
335 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
336 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
337 VERR_INVALID_HANDLE);
338
339 /*
340 * Check if it's the writer.
341 */
342 pthread_t Self = pthread_self();
343 pthread_t Writer;
344 ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
345 if (Writer == Self)
346 {
347 AssertMsgReturn(pThis->cWriterReads > 0, ("pThis=%p\n", pThis), VERR_NOT_OWNER);
348#ifdef RTSEMRW_STRICT
349 int rc9 = RTLockValidatorRecExclUnwindMixed(&pThis->ValidatorWrite, &pThis->ValidatorRead.Core);
350 if (RT_FAILURE(rc9))
351 return rc9;
352#endif
353 pThis->cWriterReads--;
354 return VINF_SUCCESS;
355 }
356
357 /*
358 * Try unlock it.
359 */
360#ifdef RTSEMRW_STRICT
361 int rc9 = RTLockValidatorRecSharedCheckAndRelease(&pThis->ValidatorRead, RTThreadSelf());
362 if (RT_FAILURE(rc9))
363 return rc9;
364#endif
365#ifdef RT_OS_LINUX /* glibc (at least 2.8) may screw up when unlocking a lock we don't own. */
366 if (ASMAtomicReadU32(&pThis->cReaders) == 0)
367 {
368 AssertMsgFailed(("Not owner of %p\n", pThis));
369 return VERR_NOT_OWNER;
370 }
371#endif
372 ASMAtomicDecU32(&pThis->cReaders);
373 int rc = pthread_rwlock_unlock(&pThis->RWLock);
374 if (rc)
375 {
376 ASMAtomicIncU32(&pThis->cReaders);
377 AssertMsgFailed(("Failed read unlock read-write sem %p, rc=%d.\n", RWSem, rc));
378 return RTErrConvertFromErrno(rc);
379 }
380 return VINF_SUCCESS;
381}
382
383
384DECL_FORCE_INLINE(int) rtSemRWRequestWrite(RTSEMRW RWSem, unsigned cMillies, PCRTLOCKVALSRCPOS pSrcPos)
385{
386 /*
387 * Validate input.
388 */
389 struct RTSEMRWINTERNAL *pThis = RWSem;
390 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
391 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
392 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
393 VERR_INVALID_HANDLE);
394
395 /*
396 * Recursion?
397 */
398 pthread_t Self = pthread_self();
399 pthread_t Writer;
400 ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
401 if (Writer == Self)
402 {
403#ifdef RTSEMRW_STRICT
404 int rc9 = RTLockValidatorRecExclRecursion(&pThis->ValidatorWrite, pSrcPos);
405 if (RT_FAILURE(rc9))
406 return rc9;
407#endif
408 Assert(pThis->cWrites < INT32_MAX);
409 pThis->cWrites++;
410 return VINF_SUCCESS;
411 }
412
413 /*
414 * Try lock it.
415 */
416 RTTHREAD hThreadSelf = NIL_RTTHREAD;
417 if (cMillies)
418 {
419#ifdef RTSEMRW_STRICT
420 hThreadSelf = RTThreadSelfAutoAdopt();
421 int rc9 = RTLockValidatorRecExclCheckOrderAndBlocking(&pThis->ValidatorWrite, hThreadSelf, pSrcPos, true,
422 cMillies, RTTHREADSTATE_RW_WRITE, true);
423 if (RT_FAILURE(rc9))
424 return rc9;
425#else
426 hThreadSelf = RTThreadSelf();
427 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_RW_WRITE, true);
428#endif
429 }
430
431 if (cMillies == RT_INDEFINITE_WAIT)
432 {
433 /* take rwlock */
434 int rc = pthread_rwlock_wrlock(&pThis->RWLock);
435 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE);
436 if (rc)
437 {
438 AssertMsgFailed(("Failed write lock read-write sem %p, rc=%d.\n", RWSem, rc));
439 return RTErrConvertFromErrno(rc);
440 }
441 }
442 else
443 {
444#ifdef RT_OS_DARWIN
445 AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));
446 return VERR_NOT_IMPLEMENTED;
447#else /* !RT_OS_DARWIN */
448 /*
449 * Get current time and calc end of wait time.
450 */
451 struct timespec ts = {0,0};
452 clock_gettime(CLOCK_REALTIME, &ts);
453 if (cMillies != 0)
454 {
455 ts.tv_nsec += (cMillies % 1000) * 1000000;
456 ts.tv_sec += cMillies / 1000;
457 if (ts.tv_nsec >= 1000000000)
458 {
459 ts.tv_nsec -= 1000000000;
460 ts.tv_sec++;
461 }
462 }
463
464 /* take rwlock */
465 int rc = pthread_rwlock_timedwrlock(&pThis->RWLock, &ts);
466 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE);
467 if (rc)
468 {
469 AssertMsg(rc == ETIMEDOUT, ("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));
470 return RTErrConvertFromErrno(rc);
471 }
472#endif /* !RT_OS_DARWIN */
473 }
474
475 ATOMIC_SET_PTHREAD_T(&pThis->Writer, Self);
476 pThis->cWrites = 1;
477 Assert(!pThis->cReaders);
478#ifdef RTSEMRW_STRICT
479 RTLockValidatorRecExclSetOwner(&pThis->ValidatorWrite, hThreadSelf, pSrcPos, true);
480#endif
481 return VINF_SUCCESS;
482}
483
484
485RTDECL(int) RTSemRWRequestWrite(RTSEMRW RWSem, unsigned cMillies)
486{
487#ifndef RTSEMRW_STRICT
488 return rtSemRWRequestWrite(RWSem, cMillies, NULL);
489#else
490 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
491 return rtSemRWRequestWrite(RWSem, cMillies, &SrcPos);
492#endif
493}
494
495
496RTDECL(int) RTSemRWRequestWriteDebug(RTSEMRW RWSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
497{
498 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
499 return rtSemRWRequestWrite(RWSem, cMillies, &SrcPos);
500}
501
502
503RTDECL(int) RTSemRWRequestWriteNoResume(RTSEMRW RWSem, unsigned cMillies)
504{
505 /* EINTR isn't returned by the wait functions we're using. */
506#ifndef RTSEMRW_STRICT
507 return rtSemRWRequestWrite(RWSem, cMillies, NULL);
508#else
509 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
510 return rtSemRWRequestWrite(RWSem, cMillies, &SrcPos);
511#endif
512}
513
514
515RTDECL(int) RTSemRWRequestWriteNoResumeDebug(RTSEMRW RWSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
516{
517 /* EINTR isn't returned by the wait functions we're using. */
518 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
519 return rtSemRWRequestWrite(RWSem, cMillies, &SrcPos);
520}
521
522
523RTDECL(int) RTSemRWReleaseWrite(RTSEMRW RWSem)
524{
525 /*
526 * Validate input.
527 */
528 struct RTSEMRWINTERNAL *pThis = RWSem;
529 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
530 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
531 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
532 VERR_INVALID_HANDLE);
533
534 /*
535 * Verify ownership and implement recursion.
536 */
537 pthread_t Self = pthread_self();
538 pthread_t Writer;
539 ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
540 AssertMsgReturn(Writer == Self, ("pThis=%p\n", pThis), VERR_NOT_OWNER);
541 AssertReturn(pThis->cWriterReads == 0 || pThis->cWrites > 1, VERR_WRONG_ORDER);
542
543 if (pThis->cWrites > 1)
544 {
545#ifdef RTSEMRW_STRICT
546 int rc9 = RTLockValidatorRecExclUnwind(&pThis->ValidatorWrite);
547 if (RT_FAILURE(rc9))
548 return rc9;
549#endif
550 pThis->cWrites--;
551 return VINF_SUCCESS;
552 }
553 pThis->cWrites--;
554
555 /*
556 * Try unlock it.
557 */
558#ifdef RTSEMRW_STRICT
559 int rc9 = RTLockValidatorRecExclReleaseOwner(&pThis->ValidatorWrite, true);
560 if (RT_FAILURE(rc9))
561 return rc9;
562#endif
563
564 ATOMIC_SET_PTHREAD_T(&pThis->Writer, (pthread_t)-1);
565 int rc = pthread_rwlock_unlock(&pThis->RWLock);
566 if (rc)
567 {
568 AssertMsgFailed(("Failed write unlock read-write sem %p, rc=%d.\n", RWSem, rc));
569 return RTErrConvertFromErrno(rc);
570 }
571
572 return VINF_SUCCESS;
573}
574
575
576RTDECL(bool) RTSemRWIsWriteOwner(RTSEMRW RWSem)
577{
578 /*
579 * Validate input.
580 */
581 struct RTSEMRWINTERNAL *pThis = RWSem;
582 AssertPtrReturn(pThis, false);
583 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
584 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
585 false);
586
587 /*
588 * Check ownership.
589 */
590 pthread_t Self = pthread_self();
591 pthread_t Writer;
592 ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
593 return Writer == Self;
594}
595
596
597RTDECL(uint32_t) RTSemRWGetWriteRecursion(RTSEMRW RWSem)
598{
599 /*
600 * Validate input.
601 */
602 struct RTSEMRWINTERNAL *pThis = RWSem;
603 AssertPtrReturn(pThis, 0);
604 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
605 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
606 0);
607
608 /*
609 * Return the requested data.
610 */
611 return pThis->cWrites;
612}
613
614
615RTDECL(uint32_t) RTSemRWGetWriterReadRecursion(RTSEMRW RWSem)
616{
617 /*
618 * Validate input.
619 */
620 struct RTSEMRWINTERNAL *pThis = RWSem;
621 AssertPtrReturn(pThis, 0);
622 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
623 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
624 0);
625
626 /*
627 * Return the requested data.
628 */
629 return pThis->cWriterReads;
630}
631
632
633RTDECL(uint32_t) RTSemRWGetReadCount(RTSEMRW RWSem)
634{
635 /*
636 * Validate input.
637 */
638 struct RTSEMRWINTERNAL *pThis = RWSem;
639 AssertPtrReturn(pThis, 0);
640 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
641 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
642 0);
643
644 /*
645 * Return the requested data.
646 */
647 return pThis->cReaders;
648}
649
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette