VirtualBox

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

Last change on this file since 100762 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 18.7 KB
Line 
1/* $Id: critsect-generic.cpp 98103 2023-01-17 14:15:46Z 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) RTCritSectInitEx(PRTCRITSECT pCritSect, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass,
80 const char *pszNameFmt, ...)
81{
82 AssertReturn(!(fFlags & ~(RTCRITSECT_FLAGS_NO_NESTING | RTCRITSECT_FLAGS_NO_LOCK_VAL | RTCRITSECT_FLAGS_BOOTSTRAP_HACK | RTCRITSECT_FLAGS_NOP)),
83 VERR_INVALID_PARAMETER);
84 RT_NOREF_PV(hClass); RT_NOREF_PV(uSubClass); RT_NOREF_PV(pszNameFmt);
85
86 /*
87 * Initialize the structure and
88 */
89 pCritSect->u32Magic = RTCRITSECT_MAGIC;
90#ifdef IN_RING0
91 pCritSect->fFlags = fFlags | RTCRITSECT_FLAGS_RING0;
92#else
93 pCritSect->fFlags = fFlags & ~RTCRITSECT_FLAGS_RING0;
94#endif
95 pCritSect->cNestings = 0;
96 pCritSect->cLockers = -1;
97 pCritSect->NativeThreadOwner = NIL_RTNATIVETHREAD;
98 pCritSect->pValidatorRec = NULL;
99 int rc = VINF_SUCCESS;
100#ifdef RTCRITSECT_STRICT
101 if (!(fFlags & (RTCRITSECT_FLAGS_BOOTSTRAP_HACK | RTCRITSECT_FLAGS_NOP)))
102 {
103 if (!pszNameFmt)
104 {
105 static uint32_t volatile s_iCritSectAnon = 0;
106 rc = RTLockValidatorRecExclCreate(&pCritSect->pValidatorRec, hClass, uSubClass, pCritSect,
107 !(fFlags & RTCRITSECT_FLAGS_NO_LOCK_VAL),
108 "RTCritSect-%u", ASMAtomicIncU32(&s_iCritSectAnon) - 1);
109 }
110 else
111 {
112 va_list va;
113 va_start(va, pszNameFmt);
114 rc = RTLockValidatorRecExclCreateV(&pCritSect->pValidatorRec, hClass, uSubClass, pCritSect,
115 !(fFlags & RTCRITSECT_FLAGS_NO_LOCK_VAL), pszNameFmt, va);
116 va_end(va);
117 }
118 }
119#endif
120 if (RT_SUCCESS(rc))
121 {
122#ifdef IN_RING0
123 rc = RTSemEventCreate(&pCritSect->EventSem);
124
125#else
126 rc = RTSemEventCreateEx(&pCritSect->EventSem,
127 fFlags & RTCRITSECT_FLAGS_BOOTSTRAP_HACK
128 ? RTSEMEVENT_FLAGS_NO_LOCK_VAL | RTSEMEVENT_FLAGS_BOOTSTRAP_HACK
129 : RTSEMEVENT_FLAGS_NO_LOCK_VAL,
130 NIL_RTLOCKVALCLASS,
131 NULL);
132#endif
133 if (RT_SUCCESS(rc))
134 return VINF_SUCCESS;
135#ifdef RTCRITSECT_STRICT
136 RTLockValidatorRecExclDestroy(&pCritSect->pValidatorRec);
137#endif
138 }
139
140 AssertRC(rc);
141 pCritSect->EventSem = NULL;
142 pCritSect->u32Magic = (uint32_t)rc;
143 return rc;
144}
145RT_EXPORT_SYMBOL(RTCritSectInitEx);
146
147
148RTDECL(uint32_t) RTCritSectSetSubClass(PRTCRITSECT pCritSect, uint32_t uSubClass)
149{
150# ifdef RTCRITSECT_STRICT
151 AssertPtrReturn(pCritSect, RTLOCKVAL_SUB_CLASS_INVALID);
152 AssertReturn(pCritSect->u32Magic == RTCRITSECT_MAGIC, RTLOCKVAL_SUB_CLASS_INVALID);
153 AssertReturn(!(pCritSect->fFlags & RTCRITSECT_FLAGS_NOP), RTLOCKVAL_SUB_CLASS_INVALID);
154 return RTLockValidatorRecExclSetSubClass(pCritSect->pValidatorRec, uSubClass);
155# else
156 RT_NOREF_PV(pCritSect); RT_NOREF_PV(uSubClass);
157 return RTLOCKVAL_SUB_CLASS_INVALID;
158# endif
159}
160
161
162DECL_FORCE_INLINE(int) rtCritSectTryEnter(PRTCRITSECT pCritSect, PCRTLOCKVALSRCPOS pSrcPos)
163{
164 Assert(pCritSect);
165 Assert(pCritSect->u32Magic == RTCRITSECT_MAGIC);
166 /*AssertReturn(pCritSect->u32Magic == RTCRITSECT_MAGIC, VERR_SEM_DESTROYED);*/
167#ifdef IN_RING0
168 Assert(pCritSect->fFlags & RTCRITSECT_FLAGS_RING0);
169#else
170 Assert(!(pCritSect->fFlags & RTCRITSECT_FLAGS_RING0));
171#endif
172 RT_NOREF_PV(pSrcPos);
173
174 /*
175 * Return straight away if NOP.
176 */
177 if (pCritSect->fFlags & RTCRITSECT_FLAGS_NOP)
178 return VINF_SUCCESS;
179
180 /*
181 * Try take the lock. (cLockers is -1 if it's free)
182 */
183 RTNATIVETHREAD NativeThreadSelf = RTThreadNativeSelf();
184 if (!ASMAtomicCmpXchgS32(&pCritSect->cLockers, 0, -1))
185 {
186 /*
187 * Somebody is owning it (or will be soon). Perhaps it's us?
188 */
189 if (pCritSect->NativeThreadOwner == NativeThreadSelf)
190 {
191 if (!(pCritSect->fFlags & RTCRITSECT_FLAGS_NO_NESTING))
192 {
193#ifdef RTCRITSECT_STRICT
194 int rc9 = RTLockValidatorRecExclRecursion(pCritSect->pValidatorRec, pSrcPos);
195 if (RT_FAILURE(rc9))
196 return rc9;
197#endif
198 int32_t cLockers = ASMAtomicIncS32(&pCritSect->cLockers); NOREF(cLockers);
199 pCritSect->cNestings++;
200 IPRT_CRITSECT_ENTERED(pCritSect, NULL, cLockers, pCritSect->cNestings);
201 return VINF_SUCCESS;
202 }
203 AssertMsgFailed(("Nested entry of critsect %p\n", pCritSect));
204 return VERR_SEM_NESTED;
205 }
206 IPRT_CRITSECT_BUSY(pCritSect, NULL, pCritSect->cLockers, (void *)pCritSect->NativeThreadOwner);
207 return VERR_SEM_BUSY;
208 }
209
210 /*
211 * First time
212 */
213 pCritSect->cNestings = 1;
214 ASMAtomicWriteHandle(&pCritSect->NativeThreadOwner, NativeThreadSelf);
215#ifdef RTCRITSECT_STRICT
216 RTLockValidatorRecExclSetOwner(pCritSect->pValidatorRec, NIL_RTTHREAD, pSrcPos, true);
217#endif
218 IPRT_CRITSECT_ENTERED(pCritSect, NULL, 0, 1);
219
220 return VINF_SUCCESS;
221}
222
223
224RTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect)
225{
226#ifndef RTCRTISECT_STRICT
227 return rtCritSectTryEnter(pCritSect, NULL);
228#else
229 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
230 return rtCritSectTryEnter(pCritSect, &SrcPos);
231#endif
232}
233RT_EXPORT_SYMBOL(RTCritSectTryEnter);
234
235
236RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
237{
238 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
239 return rtCritSectTryEnter(pCritSect, &SrcPos);
240}
241RT_EXPORT_SYMBOL(RTCritSectTryEnterDebug);
242
243
244DECL_FORCE_INLINE(int) rtCritSectEnter(PRTCRITSECT pCritSect, PCRTLOCKVALSRCPOS pSrcPos)
245{
246 AssertPtr(pCritSect);
247 AssertReturn(pCritSect->u32Magic == RTCRITSECT_MAGIC, VERR_SEM_DESTROYED);
248#ifdef IN_RING0
249 Assert(pCritSect->fFlags & RTCRITSECT_FLAGS_RING0);
250#else
251 Assert(!(pCritSect->fFlags & RTCRITSECT_FLAGS_RING0));
252#endif
253 RT_NOREF_PV(pSrcPos);
254
255 /*
256 * Return straight away if NOP.
257 */
258 if (pCritSect->fFlags & RTCRITSECT_FLAGS_NOP)
259 return VINF_SUCCESS;
260
261 /*
262 * How is calling and is the order right?
263 */
264 RTNATIVETHREAD NativeThreadSelf = RTThreadNativeSelf();
265#ifdef RTCRITSECT_STRICT
266 RTTHREAD hThreadSelf = pCritSect->pValidatorRec
267 ? RTThreadSelfAutoAdopt()
268 : RTThreadSelf();
269 int rc9;
270 if (pCritSect->pValidatorRec) /* (bootstap) */
271 {
272 rc9 = RTLockValidatorRecExclCheckOrder(pCritSect->pValidatorRec, hThreadSelf, pSrcPos, RT_INDEFINITE_WAIT);
273 if (RT_FAILURE(rc9))
274 return rc9;
275 }
276#endif
277
278 /*
279 * Increment the waiter counter.
280 * This becomes 0 when the section is free.
281 */
282 int32_t cLockers = ASMAtomicIncS32(&pCritSect->cLockers);
283 if (cLockers > 0)
284 {
285 /*
286 * Nested?
287 */
288 if (pCritSect->NativeThreadOwner == NativeThreadSelf)
289 {
290 if (!(pCritSect->fFlags & RTCRITSECT_FLAGS_NO_NESTING))
291 {
292#ifdef RTCRITSECT_STRICT
293 rc9 = RTLockValidatorRecExclRecursion(pCritSect->pValidatorRec, pSrcPos);
294 if (RT_FAILURE(rc9))
295 {
296 ASMAtomicDecS32(&pCritSect->cLockers);
297 return rc9;
298 }
299#endif
300 pCritSect->cNestings++;
301 IPRT_CRITSECT_ENTERED(pCritSect, NULL, cLockers, pCritSect->cNestings);
302 return VINF_SUCCESS;
303 }
304
305 AssertBreakpoint(); /* don't do normal assertion here, the logger uses this code too. */
306 ASMAtomicDecS32(&pCritSect->cLockers);
307 return VERR_SEM_NESTED;
308 }
309
310 /*
311 * Wait for the current owner to release it.
312 */
313 IPRT_CRITSECT_WAITING(pCritSect, NULL, cLockers, (void *)pCritSect->NativeThreadOwner);
314#if !defined(RTCRITSECT_STRICT) && defined(IN_RING3)
315 RTTHREAD hThreadSelf = RTThreadSelf();
316#endif
317 for (;;)
318 {
319#ifdef RTCRITSECT_STRICT
320 rc9 = RTLockValidatorRecExclCheckBlocking(pCritSect->pValidatorRec, hThreadSelf, pSrcPos,
321 !(pCritSect->fFlags & RTCRITSECT_FLAGS_NO_NESTING),
322 RT_INDEFINITE_WAIT, RTTHREADSTATE_CRITSECT, false);
323 if (RT_FAILURE(rc9))
324 {
325 ASMAtomicDecS32(&pCritSect->cLockers);
326 return rc9;
327 }
328#elif defined(IN_RING3)
329 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_CRITSECT, false);
330#endif
331 int rc = RTSemEventWait(pCritSect->EventSem, RT_INDEFINITE_WAIT);
332#ifdef IN_RING3
333 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_CRITSECT);
334#endif
335
336 if (pCritSect->u32Magic != RTCRITSECT_MAGIC)
337 return VERR_SEM_DESTROYED;
338 if (rc == VINF_SUCCESS)
339 break;
340 AssertMsg(rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED, ("rc=%Rrc\n", rc));
341 }
342 AssertMsg(pCritSect->NativeThreadOwner == NIL_RTNATIVETHREAD, ("pCritSect->NativeThreadOwner=%p\n", pCritSect->NativeThreadOwner));
343 }
344
345 /*
346 * First time
347 */
348 pCritSect->cNestings = 1;
349 ASMAtomicWriteHandle(&pCritSect->NativeThreadOwner, NativeThreadSelf);
350#ifdef RTCRITSECT_STRICT
351 RTLockValidatorRecExclSetOwner(pCritSect->pValidatorRec, hThreadSelf, pSrcPos, true);
352#endif
353 IPRT_CRITSECT_ENTERED(pCritSect, NULL, 0, 1);
354
355 return VINF_SUCCESS;
356}
357
358
359RTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect)
360{
361#ifndef RTCRITSECT_STRICT
362 return rtCritSectEnter(pCritSect, NULL);
363#else
364 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
365 return rtCritSectEnter(pCritSect, &SrcPos);
366#endif
367}
368RT_EXPORT_SYMBOL(RTCritSectEnter);
369
370
371RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
372{
373 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
374 return rtCritSectEnter(pCritSect, &SrcPos);
375}
376RT_EXPORT_SYMBOL(RTCritSectEnterDebug);
377
378
379RTDECL(int) RTCritSectLeave(PRTCRITSECT pCritSect)
380{
381 /*
382 * Assert sanity and check for NOP.
383 */
384 Assert(pCritSect);
385 Assert(pCritSect->u32Magic == RTCRITSECT_MAGIC);
386#ifdef IN_RING0
387 Assert(pCritSect->fFlags & RTCRITSECT_FLAGS_RING0);
388#else
389 Assert(!(pCritSect->fFlags & RTCRITSECT_FLAGS_RING0));
390#endif
391 if (pCritSect->fFlags & RTCRITSECT_FLAGS_NOP)
392 return VINF_SUCCESS;
393
394 /*
395 * Assert ownership and so on.
396 */
397 Assert(pCritSect->cNestings > 0);
398 Assert(pCritSect->cLockers >= 0);
399 Assert(pCritSect->NativeThreadOwner == RTThreadNativeSelf());
400
401#ifdef RTCRITSECT_STRICT
402 int rc9 = RTLockValidatorRecExclReleaseOwner(pCritSect->pValidatorRec, pCritSect->cNestings == 1);
403 if (RT_FAILURE(rc9))
404 return rc9;
405#endif
406
407 /*
408 * Decrement nestings, if <= 0 when we'll release the critsec.
409 */
410 uint32_t cNestings = --pCritSect->cNestings;
411 IPRT_CRITSECT_LEAVING(pCritSect, NULL, ASMAtomicUoReadS32(&pCritSect->cLockers) - 1, cNestings);
412 if (cNestings > 0)
413 ASMAtomicDecS32(&pCritSect->cLockers);
414 else
415 {
416 /*
417 * Set owner to zero.
418 * Decrement waiters, if >= 0 then we have to wake one of them up.
419 */
420 ASMAtomicWriteHandle(&pCritSect->NativeThreadOwner, NIL_RTNATIVETHREAD);
421 if (ASMAtomicDecS32(&pCritSect->cLockers) >= 0)
422 {
423 int rc = RTSemEventSignal(pCritSect->EventSem);
424 AssertReleaseMsgRC(rc, ("RTSemEventSignal -> %Rrc\n", rc));
425 }
426 }
427 return VINF_SUCCESS;
428}
429RT_EXPORT_SYMBOL(RTCritSectLeave);
430
431
432
433#ifdef IN_RING3
434
435static int rtCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects, PCRTLOCKVALSRCPOS pSrcPos)
436{
437 Assert(cCritSects > 0);
438 AssertPtr(papCritSects);
439
440 /*
441 * Try get them all.
442 */
443 int rc = VERR_INVALID_PARAMETER;
444 size_t i;
445 for (i = 0; i < cCritSects; i++)
446 {
447 rc = rtCritSectTryEnter(papCritSects[i], pSrcPos);
448 if (RT_FAILURE(rc))
449 break;
450 }
451 if (RT_SUCCESS(rc))
452 return rc;
453
454 /*
455 * The retry loop.
456 */
457 for (unsigned cTries = 0; ; cTries++)
458 {
459 /*
460 * We've failed, release any locks we might have gotten. ('i' is the lock that failed btw.)
461 */
462 size_t j = i;
463 while (j-- > 0)
464 {
465 int rc2 = RTCritSectLeave(papCritSects[j]);
466 AssertRC(rc2);
467 }
468 if (rc != VERR_SEM_BUSY)
469 return rc;
470
471 /*
472 * Try prevent any theoretical synchronous races with other threads.
473 */
474 Assert(cTries < 1000000);
475 if (cTries > 10000)
476 RTThreadSleep(cTries % 3);
477
478 /*
479 * Wait on the one we failed to get.
480 */
481 rc = rtCritSectEnter(papCritSects[i], pSrcPos);
482 if (RT_FAILURE(rc))
483 return rc;
484
485 /*
486 * Try take the others.
487 */
488 for (j = 0; j < cCritSects; j++)
489 {
490 if (j != i)
491 {
492 rc = rtCritSectTryEnter(papCritSects[j], pSrcPos);
493 if (RT_FAILURE(rc))
494 break;
495 }
496 }
497 if (RT_SUCCESS(rc))
498 return rc;
499
500 /*
501 * We failed.
502 */
503 if (i > j)
504 {
505 int rc2 = RTCritSectLeave(papCritSects[i]);
506 AssertRC(rc2);
507 }
508 i = j;
509 }
510}
511
512
513RTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects)
514{
515#ifndef RTCRITSECT_STRICT
516 return rtCritSectEnterMultiple(cCritSects, papCritSects, NULL);
517#else
518 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
519 return rtCritSectEnterMultiple(cCritSects, papCritSects, &SrcPos);
520#endif
521}
522RT_EXPORT_SYMBOL(RTCritSectEnterMultiple);
523
524
525RTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTHCUINTPTR uId, RT_SRC_POS_DECL)
526{
527 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
528 return rtCritSectEnterMultiple(cCritSects, papCritSects, &SrcPos);
529}
530RT_EXPORT_SYMBOL(RTCritSectEnterMultipleDebug);
531
532
533
534RTDECL(int) RTCritSectLeaveMultiple(size_t cCritSects, PRTCRITSECT *papCritSects)
535{
536 int rc = VINF_SUCCESS;
537 for (size_t i = 0; i < cCritSects; i++)
538 {
539 int rc2 = RTCritSectLeave(papCritSects[i]);
540 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
541 rc = rc2;
542 }
543 return rc;
544}
545RT_EXPORT_SYMBOL(RTCritSectLeaveMultiple);
546
547#endif /* IN_RING3 */
548
549
550
551RTDECL(int) RTCritSectDelete(PRTCRITSECT pCritSect)
552{
553 /*
554 * Assert free waiters and so on.
555 */
556 Assert(pCritSect);
557 Assert(pCritSect->u32Magic == RTCRITSECT_MAGIC);
558 Assert(pCritSect->cNestings == 0);
559 Assert(pCritSect->cLockers == -1);
560 Assert(pCritSect->NativeThreadOwner == NIL_RTNATIVETHREAD);
561#ifdef IN_RING0
562 Assert(pCritSect->fFlags & RTCRITSECT_FLAGS_RING0);
563#else
564 Assert(!(pCritSect->fFlags & RTCRITSECT_FLAGS_RING0));
565#endif
566
567 /*
568 * Invalidate the structure and free the mutex.
569 * In case someone is waiting we'll signal the semaphore cLockers + 1 times.
570 */
571 ASMAtomicWriteU32(&pCritSect->u32Magic, ~RTCRITSECT_MAGIC);
572 pCritSect->fFlags = 0;
573 pCritSect->cNestings = 0;
574 pCritSect->NativeThreadOwner= NIL_RTNATIVETHREAD;
575 RTSEMEVENT EventSem = pCritSect->EventSem;
576 pCritSect->EventSem = NIL_RTSEMEVENT;
577
578 while (pCritSect->cLockers-- >= 0)
579 RTSemEventSignal(EventSem);
580 ASMAtomicWriteS32(&pCritSect->cLockers, -1);
581 int rc = RTSemEventDestroy(EventSem);
582 AssertRC(rc);
583
584#ifdef RTCRITSECT_STRICT
585 RTLockValidatorRecExclDestroy(&pCritSect->pValidatorRec);
586#endif
587
588 return rc;
589}
590RT_EXPORT_SYMBOL(RTCritSectDelete);
591
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