VirtualBox

source: vbox/trunk/src/VBox/Runtime/generic/critsect-generic.cpp@ 106020

Last change on this file since 106020 was 106020, checked in by vboxsync, 3 months ago

IPRT: Added RTCritSectInitNamed and RTCritSectRwInitNamed to simplify naming critical sections w/o sabotaging automatic lock order validation.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 18.9 KB
Line 
1/* $Id: critsect-generic.cpp 106020 2024-09-12 09:23:00Z vboxsync $ */
2/** @file
3 * IPRT - Critical Section, Generic.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define RTCRITSECT_WITHOUT_REMAPPING
42#include <iprt/critsect.h>
43#include "internal/iprt.h"
44
45#include <iprt/semaphore.h>
46#include <iprt/thread.h>
47#include <iprt/assert.h>
48#include <iprt/asm.h>
49#include <iprt/err.h>
50#include "internal/thread.h"
51#include "internal/strict.h"
52
53/* Two issues here, (1) the tracepoint generator uses IPRT, and (2) only one .d
54 file per module. */
55#ifdef IPRT_WITH_DTRACE
56# include IPRT_DTRACE_INCLUDE
57# ifdef IPRT_DTRACE_PREFIX
58# define IPRT_CRITSECT_ENTERED RT_CONCAT(IPRT_DTRACE_PREFIX,IPRT_CRITSECT_ENTERED)
59# define IPRT_CRITSECT_LEAVING RT_CONCAT(IPRT_DTRACE_PREFIX,IPRT_CRITSECT_LEAVING)
60# define IPRT_CRITSECT_BUSY RT_CONCAT(IPRT_DTRACE_PREFIX,IPRT_CRITSECT_BUSY)
61# define IPRT_CRITSECT_WAITING RT_CONCAT(IPRT_DTRACE_PREFIX,IPRT_CRITSECT_WAITING)
62# endif
63#else
64# define IPRT_CRITSECT_ENTERED(a_pvCritSect, a_pszName, a_cLockers, a_cNestings) do {} while (0)
65# define IPRT_CRITSECT_LEAVING(a_pvCritSect, a_pszName, a_cLockers, a_cNestings) do {} while (0)
66# define IPRT_CRITSECT_BUSY( a_pvCritSect, a_pszName, a_cLockers, a_pvNativeOwnerThread) do {} while (0)
67# define IPRT_CRITSECT_WAITING(a_pvCritSect, a_pszName, a_cLockers, a_pvNativeOwnerThread) do {} while (0)
68#endif
69
70
71
72RTDECL(int) RTCritSectInit(PRTCRITSECT pCritSect)
73{
74 return RTCritSectInitEx(pCritSect, 0, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, "RTCritSect");
75}
76RT_EXPORT_SYMBOL(RTCritSectInit);
77
78
79RTDECL(int) RTCritSectInitNamed(PRTCRITSECT pCritSect, const char *pszName)
80{
81 return RTCritSectInitEx(pCritSect, 0, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, "%s", pszName);
82}
83RT_EXPORT_SYMBOL(RTCritSectInitNamed);
84
85
86RTDECL(int) RTCritSectInitEx(PRTCRITSECT pCritSect, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass,
87 const char *pszNameFmt, ...)
88{
89 AssertReturn(!(fFlags & ~(RTCRITSECT_FLAGS_NO_NESTING | RTCRITSECT_FLAGS_NO_LOCK_VAL | RTCRITSECT_FLAGS_BOOTSTRAP_HACK | RTCRITSECT_FLAGS_NOP)),
90 VERR_INVALID_PARAMETER);
91 RT_NOREF_PV(hClass); RT_NOREF_PV(uSubClass); RT_NOREF_PV(pszNameFmt);
92
93 /*
94 * Initialize the structure and
95 */
96 pCritSect->u32Magic = RTCRITSECT_MAGIC;
97#ifdef IN_RING0
98 pCritSect->fFlags = fFlags | RTCRITSECT_FLAGS_RING0;
99#else
100 pCritSect->fFlags = fFlags & ~RTCRITSECT_FLAGS_RING0;
101#endif
102 pCritSect->cNestings = 0;
103 pCritSect->cLockers = -1;
104 pCritSect->NativeThreadOwner = NIL_RTNATIVETHREAD;
105 pCritSect->pValidatorRec = NULL;
106 int rc = VINF_SUCCESS;
107#ifdef RTCRITSECT_STRICT
108 if (!(fFlags & (RTCRITSECT_FLAGS_BOOTSTRAP_HACK | RTCRITSECT_FLAGS_NOP)))
109 {
110 if (!pszNameFmt)
111 {
112 static uint32_t volatile s_iCritSectAnon = 0;
113 rc = RTLockValidatorRecExclCreate(&pCritSect->pValidatorRec, hClass, uSubClass, pCritSect,
114 !(fFlags & RTCRITSECT_FLAGS_NO_LOCK_VAL),
115 "RTCritSect-%u", ASMAtomicIncU32(&s_iCritSectAnon) - 1);
116 }
117 else
118 {
119 va_list va;
120 va_start(va, pszNameFmt);
121 rc = RTLockValidatorRecExclCreateV(&pCritSect->pValidatorRec, hClass, uSubClass, pCritSect,
122 !(fFlags & RTCRITSECT_FLAGS_NO_LOCK_VAL), pszNameFmt, va);
123 va_end(va);
124 }
125 }
126#endif
127 if (RT_SUCCESS(rc))
128 {
129#ifdef IN_RING0
130 rc = RTSemEventCreate(&pCritSect->EventSem);
131
132#else
133 rc = RTSemEventCreateEx(&pCritSect->EventSem,
134 fFlags & RTCRITSECT_FLAGS_BOOTSTRAP_HACK
135 ? RTSEMEVENT_FLAGS_NO_LOCK_VAL | RTSEMEVENT_FLAGS_BOOTSTRAP_HACK
136 : RTSEMEVENT_FLAGS_NO_LOCK_VAL,
137 NIL_RTLOCKVALCLASS,
138 NULL);
139#endif
140 if (RT_SUCCESS(rc))
141 return VINF_SUCCESS;
142#ifdef RTCRITSECT_STRICT
143 RTLockValidatorRecExclDestroy(&pCritSect->pValidatorRec);
144#endif
145 }
146
147 AssertRC(rc);
148 pCritSect->EventSem = NULL;
149 pCritSect->u32Magic = (uint32_t)rc;
150 return rc;
151}
152RT_EXPORT_SYMBOL(RTCritSectInitEx);
153
154
155RTDECL(uint32_t) RTCritSectSetSubClass(PRTCRITSECT pCritSect, uint32_t uSubClass)
156{
157# ifdef RTCRITSECT_STRICT
158 AssertPtrReturn(pCritSect, RTLOCKVAL_SUB_CLASS_INVALID);
159 AssertReturn(pCritSect->u32Magic == RTCRITSECT_MAGIC, RTLOCKVAL_SUB_CLASS_INVALID);
160 AssertReturn(!(pCritSect->fFlags & RTCRITSECT_FLAGS_NOP), RTLOCKVAL_SUB_CLASS_INVALID);
161 return RTLockValidatorRecExclSetSubClass(pCritSect->pValidatorRec, uSubClass);
162# else
163 RT_NOREF_PV(pCritSect); RT_NOREF_PV(uSubClass);
164 return RTLOCKVAL_SUB_CLASS_INVALID;
165# endif
166}
167
168
169DECL_FORCE_INLINE(int) rtCritSectTryEnter(PRTCRITSECT pCritSect, PCRTLOCKVALSRCPOS pSrcPos)
170{
171 Assert(pCritSect);
172 Assert(pCritSect->u32Magic == RTCRITSECT_MAGIC);
173 /*AssertReturn(pCritSect->u32Magic == RTCRITSECT_MAGIC, VERR_SEM_DESTROYED);*/
174#ifdef IN_RING0
175 Assert(pCritSect->fFlags & RTCRITSECT_FLAGS_RING0);
176#else
177 Assert(!(pCritSect->fFlags & RTCRITSECT_FLAGS_RING0));
178#endif
179 RT_NOREF_PV(pSrcPos);
180
181 /*
182 * Return straight away if NOP.
183 */
184 if (pCritSect->fFlags & RTCRITSECT_FLAGS_NOP)
185 return VINF_SUCCESS;
186
187 /*
188 * Try take the lock. (cLockers is -1 if it's free)
189 */
190 RTNATIVETHREAD NativeThreadSelf = RTThreadNativeSelf();
191 if (!ASMAtomicCmpXchgS32(&pCritSect->cLockers, 0, -1))
192 {
193 /*
194 * Somebody is owning it (or will be soon). Perhaps it's us?
195 */
196 if (pCritSect->NativeThreadOwner == NativeThreadSelf)
197 {
198 if (!(pCritSect->fFlags & RTCRITSECT_FLAGS_NO_NESTING))
199 {
200#ifdef RTCRITSECT_STRICT
201 int rc9 = RTLockValidatorRecExclRecursion(pCritSect->pValidatorRec, pSrcPos);
202 if (RT_FAILURE(rc9))
203 return rc9;
204#endif
205 int32_t cLockers = ASMAtomicIncS32(&pCritSect->cLockers); NOREF(cLockers);
206 pCritSect->cNestings++;
207 IPRT_CRITSECT_ENTERED(pCritSect, NULL, cLockers, pCritSect->cNestings);
208 return VINF_SUCCESS;
209 }
210 AssertMsgFailed(("Nested entry of critsect %p\n", pCritSect));
211 return VERR_SEM_NESTED;
212 }
213 IPRT_CRITSECT_BUSY(pCritSect, NULL, pCritSect->cLockers, (void *)pCritSect->NativeThreadOwner);
214 return VERR_SEM_BUSY;
215 }
216
217 /*
218 * First time
219 */
220 pCritSect->cNestings = 1;
221 ASMAtomicWriteHandle(&pCritSect->NativeThreadOwner, NativeThreadSelf);
222#ifdef RTCRITSECT_STRICT
223 RTLockValidatorRecExclSetOwner(pCritSect->pValidatorRec, NIL_RTTHREAD, pSrcPos, true);
224#endif
225 IPRT_CRITSECT_ENTERED(pCritSect, NULL, 0, 1);
226
227 return VINF_SUCCESS;
228}
229
230
231RTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect)
232{
233#ifndef RTCRTISECT_STRICT
234 return rtCritSectTryEnter(pCritSect, NULL);
235#else
236 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
237 return rtCritSectTryEnter(pCritSect, &SrcPos);
238#endif
239}
240RT_EXPORT_SYMBOL(RTCritSectTryEnter);
241
242
243RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
244{
245 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
246 return rtCritSectTryEnter(pCritSect, &SrcPos);
247}
248RT_EXPORT_SYMBOL(RTCritSectTryEnterDebug);
249
250
251DECL_FORCE_INLINE(int) rtCritSectEnter(PRTCRITSECT pCritSect, PCRTLOCKVALSRCPOS pSrcPos)
252{
253 AssertPtr(pCritSect);
254 AssertReturn(pCritSect->u32Magic == RTCRITSECT_MAGIC, VERR_SEM_DESTROYED);
255#ifdef IN_RING0
256 Assert(pCritSect->fFlags & RTCRITSECT_FLAGS_RING0);
257#else
258 Assert(!(pCritSect->fFlags & RTCRITSECT_FLAGS_RING0));
259#endif
260 RT_NOREF_PV(pSrcPos);
261
262 /*
263 * Return straight away if NOP.
264 */
265 if (pCritSect->fFlags & RTCRITSECT_FLAGS_NOP)
266 return VINF_SUCCESS;
267
268 /*
269 * How is calling and is the order right?
270 */
271 RTNATIVETHREAD NativeThreadSelf = RTThreadNativeSelf();
272#ifdef RTCRITSECT_STRICT
273 RTTHREAD hThreadSelf = pCritSect->pValidatorRec
274 ? RTThreadSelfAutoAdopt()
275 : RTThreadSelf();
276 int rc9;
277 if (pCritSect->pValidatorRec) /* (bootstap) */
278 {
279 rc9 = RTLockValidatorRecExclCheckOrder(pCritSect->pValidatorRec, hThreadSelf, pSrcPos, RT_INDEFINITE_WAIT);
280 if (RT_FAILURE(rc9))
281 return rc9;
282 }
283#endif
284
285 /*
286 * Increment the waiter counter.
287 * This becomes 0 when the section is free.
288 */
289 int32_t cLockers = ASMAtomicIncS32(&pCritSect->cLockers);
290 if (cLockers > 0)
291 {
292 /*
293 * Nested?
294 */
295 if (pCritSect->NativeThreadOwner == NativeThreadSelf)
296 {
297 if (!(pCritSect->fFlags & RTCRITSECT_FLAGS_NO_NESTING))
298 {
299#ifdef RTCRITSECT_STRICT
300 rc9 = RTLockValidatorRecExclRecursion(pCritSect->pValidatorRec, pSrcPos);
301 if (RT_FAILURE(rc9))
302 {
303 ASMAtomicDecS32(&pCritSect->cLockers);
304 return rc9;
305 }
306#endif
307 pCritSect->cNestings++;
308 IPRT_CRITSECT_ENTERED(pCritSect, NULL, cLockers, pCritSect->cNestings);
309 return VINF_SUCCESS;
310 }
311
312 AssertBreakpoint(); /* don't do normal assertion here, the logger uses this code too. */
313 ASMAtomicDecS32(&pCritSect->cLockers);
314 return VERR_SEM_NESTED;
315 }
316
317 /*
318 * Wait for the current owner to release it.
319 */
320 IPRT_CRITSECT_WAITING(pCritSect, NULL, cLockers, (void *)pCritSect->NativeThreadOwner);
321#if !defined(RTCRITSECT_STRICT) && defined(IN_RING3)
322 RTTHREAD hThreadSelf = RTThreadSelf();
323#endif
324 for (;;)
325 {
326#ifdef RTCRITSECT_STRICT
327 rc9 = RTLockValidatorRecExclCheckBlocking(pCritSect->pValidatorRec, hThreadSelf, pSrcPos,
328 !(pCritSect->fFlags & RTCRITSECT_FLAGS_NO_NESTING),
329 RT_INDEFINITE_WAIT, RTTHREADSTATE_CRITSECT, false);
330 if (RT_FAILURE(rc9))
331 {
332 ASMAtomicDecS32(&pCritSect->cLockers);
333 return rc9;
334 }
335#elif defined(IN_RING3)
336 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_CRITSECT, false);
337#endif
338 int rc = RTSemEventWait(pCritSect->EventSem, RT_INDEFINITE_WAIT);
339#ifdef IN_RING3
340 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_CRITSECT);
341#endif
342
343 if (pCritSect->u32Magic != RTCRITSECT_MAGIC)
344 return VERR_SEM_DESTROYED;
345 if (rc == VINF_SUCCESS)
346 break;
347 AssertMsg(rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED, ("rc=%Rrc\n", rc));
348 }
349 AssertMsg(pCritSect->NativeThreadOwner == NIL_RTNATIVETHREAD, ("pCritSect->NativeThreadOwner=%p\n", pCritSect->NativeThreadOwner));
350 }
351
352 /*
353 * First time
354 */
355 pCritSect->cNestings = 1;
356 ASMAtomicWriteHandle(&pCritSect->NativeThreadOwner, NativeThreadSelf);
357#ifdef RTCRITSECT_STRICT
358 RTLockValidatorRecExclSetOwner(pCritSect->pValidatorRec, hThreadSelf, pSrcPos, true);
359#endif
360 IPRT_CRITSECT_ENTERED(pCritSect, NULL, 0, 1);
361
362 return VINF_SUCCESS;
363}
364
365
366RTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect)
367{
368#ifndef RTCRITSECT_STRICT
369 return rtCritSectEnter(pCritSect, NULL);
370#else
371 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
372 return rtCritSectEnter(pCritSect, &SrcPos);
373#endif
374}
375RT_EXPORT_SYMBOL(RTCritSectEnter);
376
377
378RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
379{
380 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
381 return rtCritSectEnter(pCritSect, &SrcPos);
382}
383RT_EXPORT_SYMBOL(RTCritSectEnterDebug);
384
385
386RTDECL(int) RTCritSectLeave(PRTCRITSECT pCritSect)
387{
388 /*
389 * Assert sanity and check for NOP.
390 */
391 Assert(pCritSect);
392 Assert(pCritSect->u32Magic == RTCRITSECT_MAGIC);
393#ifdef IN_RING0
394 Assert(pCritSect->fFlags & RTCRITSECT_FLAGS_RING0);
395#else
396 Assert(!(pCritSect->fFlags & RTCRITSECT_FLAGS_RING0));
397#endif
398 if (pCritSect->fFlags & RTCRITSECT_FLAGS_NOP)
399 return VINF_SUCCESS;
400
401 /*
402 * Assert ownership and so on.
403 */
404 Assert(pCritSect->cNestings > 0);
405 Assert(pCritSect->cLockers >= 0);
406 Assert(pCritSect->NativeThreadOwner == RTThreadNativeSelf());
407
408#ifdef RTCRITSECT_STRICT
409 int rc9 = RTLockValidatorRecExclReleaseOwner(pCritSect->pValidatorRec, pCritSect->cNestings == 1);
410 if (RT_FAILURE(rc9))
411 return rc9;
412#endif
413
414 /*
415 * Decrement nestings, if <= 0 when we'll release the critsec.
416 */
417 uint32_t cNestings = --pCritSect->cNestings;
418 IPRT_CRITSECT_LEAVING(pCritSect, NULL, ASMAtomicUoReadS32(&pCritSect->cLockers) - 1, cNestings);
419 if (cNestings > 0)
420 ASMAtomicDecS32(&pCritSect->cLockers);
421 else
422 {
423 /*
424 * Set owner to zero.
425 * Decrement waiters, if >= 0 then we have to wake one of them up.
426 */
427 ASMAtomicWriteHandle(&pCritSect->NativeThreadOwner, NIL_RTNATIVETHREAD);
428 if (ASMAtomicDecS32(&pCritSect->cLockers) >= 0)
429 {
430 int rc = RTSemEventSignal(pCritSect->EventSem);
431 AssertReleaseMsgRC(rc, ("RTSemEventSignal -> %Rrc\n", rc));
432 }
433 }
434 return VINF_SUCCESS;
435}
436RT_EXPORT_SYMBOL(RTCritSectLeave);
437
438
439
440#ifdef IN_RING3
441
442static int rtCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects, PCRTLOCKVALSRCPOS pSrcPos)
443{
444 Assert(cCritSects > 0);
445 AssertPtr(papCritSects);
446
447 /*
448 * Try get them all.
449 */
450 int rc = VERR_INVALID_PARAMETER;
451 size_t i;
452 for (i = 0; i < cCritSects; i++)
453 {
454 rc = rtCritSectTryEnter(papCritSects[i], pSrcPos);
455 if (RT_FAILURE(rc))
456 break;
457 }
458 if (RT_SUCCESS(rc))
459 return rc;
460
461 /*
462 * The retry loop.
463 */
464 for (unsigned cTries = 0; ; cTries++)
465 {
466 /*
467 * We've failed, release any locks we might have gotten. ('i' is the lock that failed btw.)
468 */
469 size_t j = i;
470 while (j-- > 0)
471 {
472 int rc2 = RTCritSectLeave(papCritSects[j]);
473 AssertRC(rc2);
474 }
475 if (rc != VERR_SEM_BUSY)
476 return rc;
477
478 /*
479 * Try prevent any theoretical synchronous races with other threads.
480 */
481 Assert(cTries < 1000000);
482 if (cTries > 10000)
483 RTThreadSleep(cTries % 3);
484
485 /*
486 * Wait on the one we failed to get.
487 */
488 rc = rtCritSectEnter(papCritSects[i], pSrcPos);
489 if (RT_FAILURE(rc))
490 return rc;
491
492 /*
493 * Try take the others.
494 */
495 for (j = 0; j < cCritSects; j++)
496 {
497 if (j != i)
498 {
499 rc = rtCritSectTryEnter(papCritSects[j], pSrcPos);
500 if (RT_FAILURE(rc))
501 break;
502 }
503 }
504 if (RT_SUCCESS(rc))
505 return rc;
506
507 /*
508 * We failed.
509 */
510 if (i > j)
511 {
512 int rc2 = RTCritSectLeave(papCritSects[i]);
513 AssertRC(rc2);
514 }
515 i = j;
516 }
517}
518
519
520RTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects)
521{
522#ifndef RTCRITSECT_STRICT
523 return rtCritSectEnterMultiple(cCritSects, papCritSects, NULL);
524#else
525 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
526 return rtCritSectEnterMultiple(cCritSects, papCritSects, &SrcPos);
527#endif
528}
529RT_EXPORT_SYMBOL(RTCritSectEnterMultiple);
530
531
532RTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTHCUINTPTR uId, RT_SRC_POS_DECL)
533{
534 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
535 return rtCritSectEnterMultiple(cCritSects, papCritSects, &SrcPos);
536}
537RT_EXPORT_SYMBOL(RTCritSectEnterMultipleDebug);
538
539
540
541RTDECL(int) RTCritSectLeaveMultiple(size_t cCritSects, PRTCRITSECT *papCritSects)
542{
543 int rc = VINF_SUCCESS;
544 for (size_t i = 0; i < cCritSects; i++)
545 {
546 int rc2 = RTCritSectLeave(papCritSects[i]);
547 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
548 rc = rc2;
549 }
550 return rc;
551}
552RT_EXPORT_SYMBOL(RTCritSectLeaveMultiple);
553
554#endif /* IN_RING3 */
555
556
557
558RTDECL(int) RTCritSectDelete(PRTCRITSECT pCritSect)
559{
560 /*
561 * Assert free waiters and so on.
562 */
563 Assert(pCritSect);
564 Assert(pCritSect->u32Magic == RTCRITSECT_MAGIC);
565 Assert(pCritSect->cNestings == 0);
566 Assert(pCritSect->cLockers == -1);
567 Assert(pCritSect->NativeThreadOwner == NIL_RTNATIVETHREAD);
568#ifdef IN_RING0
569 Assert(pCritSect->fFlags & RTCRITSECT_FLAGS_RING0);
570#else
571 Assert(!(pCritSect->fFlags & RTCRITSECT_FLAGS_RING0));
572#endif
573
574 /*
575 * Invalidate the structure and free the mutex.
576 * In case someone is waiting we'll signal the semaphore cLockers + 1 times.
577 */
578 ASMAtomicWriteU32(&pCritSect->u32Magic, ~RTCRITSECT_MAGIC);
579 pCritSect->fFlags = 0;
580 pCritSect->cNestings = 0;
581 pCritSect->NativeThreadOwner= NIL_RTNATIVETHREAD;
582 RTSEMEVENT EventSem = pCritSect->EventSem;
583 pCritSect->EventSem = NIL_RTSEMEVENT;
584
585 while (pCritSect->cLockers-- >= 0)
586 RTSemEventSignal(EventSem);
587 ASMAtomicWriteS32(&pCritSect->cLockers, -1);
588 int rc = RTSemEventDestroy(EventSem);
589 AssertRC(rc);
590
591#ifdef RTCRITSECT_STRICT
592 RTLockValidatorRecExclDestroy(&pCritSect->pValidatorRec);
593#endif
594
595 return rc;
596}
597RT_EXPORT_SYMBOL(RTCritSectDelete);
598
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