VirtualBox

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

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

iprt,pdmcritsect: Added RTSemEvent[Set|Add|Remove]Signaller so that we can validate who is signalling an event if we like and, more importantly, detect deadlocks involving event semaphores. More attempts at dealing with the races (and bugs) in the all-other-threads-blocking detection in tstRTLockValidator.cpp, adding RTThreadGetReallySleeping and RTThreadGetNativeState in the process.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 19.1 KB
Line 
1/* $Id: semrw-posix.cpp 25638 2010-01-04 16:08:04Z 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.virtualbox.org. 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_RTLOCKVALIDATORCLASS, RTLOCKVALIDATOR_SUB_CLASS_NONE, "RTSemRW", pThis);
129 RTLockValidatorRecSharedInit(&pThis->ValidatorRead, NIL_RTLOCKVALIDATORCLASS, RTLOCKVALIDATOR_SUB_CLASS_NONE, "RTSemRW", pThis, false /*fSignaller*/);
130 RTLockValidatorRecMakeSiblings(&pThis->ValidatorWrite.Core, &pThis->ValidatorRead.Core);
131#endif
132 *pRWSem = pThis;
133 return VINF_SUCCESS;
134 }
135 }
136
137 rc = RTErrConvertFromErrno(rc);
138 RTMemFree(pThis);
139 }
140 else
141 rc = VERR_NO_MEMORY;
142
143 return rc;
144}
145
146
147RTDECL(int) RTSemRWDestroy(RTSEMRW RWSem)
148{
149 /*
150 * Validate input, nil handle is fine.
151 */
152 struct RTSEMRWINTERNAL *pThis = RWSem;
153 if (pThis == NIL_RTSEMRW)
154 return VINF_SUCCESS;
155 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
156 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
157 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
158 VERR_INVALID_HANDLE);
159 Assert(pThis->Writer == (pthread_t)-1);
160 Assert(!pThis->cReaders);
161 Assert(!pThis->cWrites);
162 Assert(!pThis->cWriterReads);
163
164 /*
165 * Try destroy it.
166 */
167 AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, ~RTSEMRW_MAGIC, RTSEMRW_MAGIC), VERR_INVALID_HANDLE);
168 int rc = pthread_rwlock_destroy(&pThis->RWLock);
169 if (!rc)
170 {
171#ifdef RTSEMRW_STRICT
172 RTLockValidatorRecSharedDelete(&pThis->ValidatorRead);
173 RTLockValidatorRecExclDelete(&pThis->ValidatorWrite);
174#endif
175 RTMemFree(pThis);
176 rc = VINF_SUCCESS;
177 }
178 else
179 {
180 ASMAtomicWriteU32(&pThis->u32Magic, RTSEMRW_MAGIC);
181 AssertMsgFailed(("Failed to destroy read-write sem %p, rc=%d.\n", RWSem, rc));
182 rc = RTErrConvertFromErrno(rc);
183 }
184
185 return rc;
186}
187
188
189DECL_FORCE_INLINE(int) rtSemRWRequestRead(RTSEMRW RWSem, unsigned cMillies, PCRTLOCKVALSRCPOS pSrcPos)
190{
191 /*
192 * Validate input.
193 */
194 struct RTSEMRWINTERNAL *pThis = RWSem;
195 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
196 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
197 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
198 VERR_INVALID_HANDLE);
199
200 /*
201 * Check if it's the writer (implement write+read recursion).
202 */
203 pthread_t Self = pthread_self();
204 pthread_t Writer;
205 ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
206 if (Writer == Self)
207 {
208#ifdef RTSEMRW_STRICT
209 int rc9 = RTLockValidatorRecExclRecursionMixed(&pThis->ValidatorWrite, &pThis->ValidatorRead.Core, pSrcPos);
210 if (RT_FAILURE(rc9))
211 return rc9;
212#endif
213 Assert(pThis->cWriterReads < INT32_MAX);
214 pThis->cWriterReads++;
215 return VINF_SUCCESS;
216 }
217
218 /*
219 * Try lock it.
220 */
221 RTTHREAD hThreadSelf = NIL_RTTHREAD;
222 if (cMillies > 0)
223 {
224#ifdef RTSEMRW_STRICT
225 hThreadSelf = RTThreadSelfAutoAdopt();
226 int rc9 = RTLockValidatorRecSharedCheckOrderAndBlocking(&pThis->ValidatorRead, hThreadSelf, pSrcPos, true,
227 RTTHREADSTATE_RW_READ, true);
228 if (RT_FAILURE(rc9))
229 return rc9;
230#else
231 hThreadSelf = RTThreadSelf();
232 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_RW_READ, true);
233#endif
234 }
235
236 if (cMillies == RT_INDEFINITE_WAIT)
237 {
238 /* take rwlock */
239 int rc = pthread_rwlock_rdlock(&pThis->RWLock);
240 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_READ);
241 if (rc)
242 {
243 AssertMsgFailed(("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));
244 return RTErrConvertFromErrno(rc);
245 }
246 }
247 else
248 {
249#ifdef RT_OS_DARWIN
250 AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));
251 return VERR_NOT_IMPLEMENTED;
252
253#else /* !RT_OS_DARWIN */
254 /*
255 * Get current time and calc end of wait time.
256 */
257 struct timespec ts = {0,0};
258 clock_gettime(CLOCK_REALTIME, &ts);
259 if (cMillies != 0)
260 {
261 ts.tv_nsec += (cMillies % 1000) * 1000000;
262 ts.tv_sec += cMillies / 1000;
263 if (ts.tv_nsec >= 1000000000)
264 {
265 ts.tv_nsec -= 1000000000;
266 ts.tv_sec++;
267 }
268 }
269
270 /* take rwlock */
271 int rc = pthread_rwlock_timedrdlock(&pThis->RWLock, &ts);
272 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_READ);
273 if (rc)
274 {
275 AssertMsg(rc == ETIMEDOUT, ("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));
276 return RTErrConvertFromErrno(rc);
277 }
278#endif /* !RT_OS_DARWIN */
279 }
280
281 ASMAtomicIncU32(&pThis->cReaders);
282#ifdef RTSEMRW_STRICT
283 RTLockValidatorRecSharedAddOwner(&pThis->ValidatorRead, hThreadSelf, pSrcPos);
284#endif
285 return VINF_SUCCESS;
286}
287
288
289RTDECL(int) RTSemRWRequestRead(RTSEMRW RWSem, unsigned cMillies)
290{
291#ifndef RTSEMRW_STRICT
292 return rtSemRWRequestRead(RWSem, cMillies, NULL);
293#else
294 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
295 return rtSemRWRequestRead(RWSem, cMillies, &SrcPos);
296#endif
297}
298
299
300RTDECL(int) RTSemRWRequestReadDebug(RTSEMRW RWSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
301{
302 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
303 return rtSemRWRequestRead(RWSem, cMillies, &SrcPos);
304}
305
306
307RTDECL(int) RTSemRWRequestReadNoResume(RTSEMRW RWSem, unsigned cMillies)
308{
309 /* EINTR isn't returned by the wait functions we're using. */
310#ifndef RTSEMRW_STRICT
311 return rtSemRWRequestRead(RWSem, cMillies, NULL);
312#else
313 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
314 return rtSemRWRequestRead(RWSem, cMillies, &SrcPos);
315#endif
316}
317
318
319RTDECL(int) RTSemRWRequestReadNoResumeDebug(RTSEMRW RWSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
320{
321 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
322 return rtSemRWRequestRead(RWSem, cMillies, &SrcPos);
323}
324
325
326RTDECL(int) RTSemRWReleaseRead(RTSEMRW RWSem)
327{
328 /*
329 * Validate input.
330 */
331 struct RTSEMRWINTERNAL *pThis = RWSem;
332 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
333 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
334 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
335 VERR_INVALID_HANDLE);
336
337 /*
338 * Check if it's the writer.
339 */
340 pthread_t Self = pthread_self();
341 pthread_t Writer;
342 ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
343 if (Writer == Self)
344 {
345 AssertMsgReturn(pThis->cWriterReads > 0, ("pThis=%p\n", pThis), VERR_NOT_OWNER);
346#ifdef RTSEMRW_STRICT
347 int rc9 = RTLockValidatorRecExclUnwindMixed(&pThis->ValidatorWrite, &pThis->ValidatorRead.Core);
348 if (RT_FAILURE(rc9))
349 return rc9;
350#endif
351 pThis->cWriterReads--;
352 return VINF_SUCCESS;
353 }
354
355 /*
356 * Try unlock it.
357 */
358#ifdef RTSEMRW_STRICT
359 int rc9 = RTLockValidatorRecSharedCheckAndRelease(&pThis->ValidatorRead, RTThreadSelf());
360 if (RT_FAILURE(rc9))
361 return rc9;
362#endif
363#ifdef RT_OS_LINUX /* glibc (at least 2.8) may screw up when unlocking a lock we don't own. */
364 if (ASMAtomicReadU32(&pThis->cReaders) == 0)
365 {
366 AssertMsgFailed(("Not owner of %p\n", pThis));
367 return VERR_NOT_OWNER;
368 }
369#endif
370 ASMAtomicDecU32(&pThis->cReaders);
371 int rc = pthread_rwlock_unlock(&pThis->RWLock);
372 if (rc)
373 {
374 ASMAtomicIncU32(&pThis->cReaders);
375 AssertMsgFailed(("Failed read unlock read-write sem %p, rc=%d.\n", RWSem, rc));
376 return RTErrConvertFromErrno(rc);
377 }
378 return VINF_SUCCESS;
379}
380
381
382DECL_FORCE_INLINE(int) rtSemRWRequestWrite(RTSEMRW RWSem, unsigned cMillies, PCRTLOCKVALSRCPOS pSrcPos)
383{
384 /*
385 * Validate input.
386 */
387 struct RTSEMRWINTERNAL *pThis = RWSem;
388 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
389 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
390 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
391 VERR_INVALID_HANDLE);
392
393 /*
394 * Recursion?
395 */
396 pthread_t Self = pthread_self();
397 pthread_t Writer;
398 ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
399 if (Writer == Self)
400 {
401#ifdef RTSEMRW_STRICT
402 int rc9 = RTLockValidatorRecExclRecursion(&pThis->ValidatorWrite, pSrcPos);
403 if (RT_FAILURE(rc9))
404 return rc9;
405#endif
406 Assert(pThis->cWrites < INT32_MAX);
407 pThis->cWrites++;
408 return VINF_SUCCESS;
409 }
410
411 /*
412 * Try lock it.
413 */
414 RTTHREAD hThreadSelf = NIL_RTTHREAD;
415 if (cMillies)
416 {
417#ifdef RTSEMRW_STRICT
418 hThreadSelf = RTThreadSelfAutoAdopt();
419 int rc9 = RTLockValidatorRecExclCheckOrderAndBlocking(&pThis->ValidatorWrite, hThreadSelf, pSrcPos, true,
420 RTTHREADSTATE_RW_WRITE, true);
421 if (RT_FAILURE(rc9))
422 return rc9;
423#else
424 hThreadSelf = RTThreadSelf();
425 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_RW_WRITE, true);
426#endif
427 }
428
429 if (cMillies == RT_INDEFINITE_WAIT)
430 {
431 /* take rwlock */
432 int rc = pthread_rwlock_wrlock(&pThis->RWLock);
433 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE);
434 if (rc)
435 {
436 AssertMsgFailed(("Failed write lock read-write sem %p, rc=%d.\n", RWSem, rc));
437 return RTErrConvertFromErrno(rc);
438 }
439 }
440 else
441 {
442#ifdef RT_OS_DARWIN
443 AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));
444 return VERR_NOT_IMPLEMENTED;
445#else /* !RT_OS_DARWIN */
446 /*
447 * Get current time and calc end of wait time.
448 */
449 struct timespec ts = {0,0};
450 clock_gettime(CLOCK_REALTIME, &ts);
451 if (cMillies != 0)
452 {
453 ts.tv_nsec += (cMillies % 1000) * 1000000;
454 ts.tv_sec += cMillies / 1000;
455 if (ts.tv_nsec >= 1000000000)
456 {
457 ts.tv_nsec -= 1000000000;
458 ts.tv_sec++;
459 }
460 }
461
462 /* take rwlock */
463 int rc = pthread_rwlock_timedwrlock(&pThis->RWLock, &ts);
464 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE);
465 if (rc)
466 {
467 AssertMsg(rc == ETIMEDOUT, ("Failed read lock read-write sem %p, rc=%d.\n", RWSem, rc));
468 return RTErrConvertFromErrno(rc);
469 }
470#endif /* !RT_OS_DARWIN */
471 }
472
473 ATOMIC_SET_PTHREAD_T(&pThis->Writer, Self);
474 pThis->cWrites = 1;
475 Assert(!pThis->cReaders);
476#ifdef RTSEMRW_STRICT
477 RTLockValidatorRecExclSetOwner(&pThis->ValidatorWrite, hThreadSelf, pSrcPos, true);
478#endif
479 return VINF_SUCCESS;
480}
481
482
483RTDECL(int) RTSemRWRequestWrite(RTSEMRW RWSem, unsigned cMillies)
484{
485#ifndef RTSEMRW_STRICT
486 return rtSemRWRequestWrite(RWSem, cMillies, NULL);
487#else
488 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
489 return rtSemRWRequestWrite(RWSem, cMillies, &SrcPos);
490#endif
491}
492
493
494RTDECL(int) RTSemRWRequestWriteDebug(RTSEMRW RWSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
495{
496 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
497 return rtSemRWRequestWrite(RWSem, cMillies, &SrcPos);
498}
499
500
501RTDECL(int) RTSemRWRequestWriteNoResume(RTSEMRW RWSem, unsigned cMillies)
502{
503 /* EINTR isn't returned by the wait functions we're using. */
504#ifndef RTSEMRW_STRICT
505 return rtSemRWRequestWrite(RWSem, cMillies, NULL);
506#else
507 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
508 return rtSemRWRequestWrite(RWSem, cMillies, &SrcPos);
509#endif
510}
511
512
513RTDECL(int) RTSemRWRequestWriteNoResumeDebug(RTSEMRW RWSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
514{
515 /* EINTR isn't returned by the wait functions we're using. */
516 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
517 return rtSemRWRequestWrite(RWSem, cMillies, &SrcPos);
518}
519
520
521RTDECL(int) RTSemRWReleaseWrite(RTSEMRW RWSem)
522{
523 /*
524 * Validate input.
525 */
526 struct RTSEMRWINTERNAL *pThis = RWSem;
527 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
528 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
529 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
530 VERR_INVALID_HANDLE);
531
532 /*
533 * Verify ownership and implement recursion.
534 */
535 pthread_t Self = pthread_self();
536 pthread_t Writer;
537 ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
538 AssertMsgReturn(Writer == Self, ("pThis=%p\n", pThis), VERR_NOT_OWNER);
539 AssertReturn(pThis->cWriterReads == 0 || pThis->cWrites > 1, VERR_WRONG_ORDER);
540
541 if (pThis->cWrites > 1)
542 {
543#ifdef RTSEMRW_STRICT
544 int rc9 = RTLockValidatorRecExclUnwind(&pThis->ValidatorWrite);
545 if (RT_FAILURE(rc9))
546 return rc9;
547#endif
548 pThis->cWrites--;
549 return VINF_SUCCESS;
550 }
551 pThis->cWrites--;
552
553 /*
554 * Try unlock it.
555 */
556#ifdef RTSEMRW_STRICT
557 int rc9 = RTLockValidatorRecExclReleaseOwner(&pThis->ValidatorWrite, true);
558 if (RT_FAILURE(rc9))
559 return rc9;
560#endif
561
562 ATOMIC_SET_PTHREAD_T(&pThis->Writer, (pthread_t)-1);
563 int rc = pthread_rwlock_unlock(&pThis->RWLock);
564 if (rc)
565 {
566 AssertMsgFailed(("Failed write unlock read-write sem %p, rc=%d.\n", RWSem, rc));
567 return RTErrConvertFromErrno(rc);
568 }
569
570 return VINF_SUCCESS;
571}
572
573
574RTDECL(bool) RTSemRWIsWriteOwner(RTSEMRW RWSem)
575{
576 /*
577 * Validate input.
578 */
579 struct RTSEMRWINTERNAL *pThis = RWSem;
580 AssertPtrReturn(pThis, false);
581 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
582 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
583 false);
584
585 /*
586 * Check ownership.
587 */
588 pthread_t Self = pthread_self();
589 pthread_t Writer;
590 ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
591 return Writer == Self;
592}
593
594
595RTDECL(uint32_t) RTSemRWGetWriteRecursion(RTSEMRW RWSem)
596{
597 /*
598 * Validate input.
599 */
600 struct RTSEMRWINTERNAL *pThis = RWSem;
601 AssertPtrReturn(pThis, 0);
602 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
603 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
604 0);
605
606 /*
607 * Return the requested data.
608 */
609 return pThis->cWrites;
610}
611
612
613RTDECL(uint32_t) RTSemRWGetWriterReadRecursion(RTSEMRW RWSem)
614{
615 /*
616 * Validate input.
617 */
618 struct RTSEMRWINTERNAL *pThis = RWSem;
619 AssertPtrReturn(pThis, 0);
620 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
621 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
622 0);
623
624 /*
625 * Return the requested data.
626 */
627 return pThis->cWriterReads;
628}
629
630
631RTDECL(uint32_t) RTSemRWGetReadCount(RTSEMRW RWSem)
632{
633 /*
634 * Validate input.
635 */
636 struct RTSEMRWINTERNAL *pThis = RWSem;
637 AssertPtrReturn(pThis, 0);
638 AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
639 ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
640 0);
641
642 /*
643 * Return the requested data.
644 */
645 return pThis->cReaders;
646}
647
Note: See TracBrowser for help on using the repository browser.

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