VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 21.1 KB
Line 
1/* $Id: semeventmulti-posix.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - Multiple Release Event Semaphore, POSIX.
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#include <iprt/semaphore.h>
42#include "internal/iprt.h"
43
44#include <iprt/asm.h>
45#include <iprt/assert.h>
46#include <iprt/err.h>
47#include <iprt/lockvalidator.h>
48#include <iprt/mem.h>
49#include <iprt/time.h>
50
51#include "internal/strict.h"
52
53#include <errno.h>
54#include <pthread.h>
55#include <unistd.h>
56#include <sys/time.h>
57
58#include "semwait.h"
59
60
61/*********************************************************************************************************************************
62* Structures and Typedefs *
63*********************************************************************************************************************************/
64/** Posix internal representation of a Mutex Multi semaphore.
65 * The POSIX implementation uses a mutex and a condition variable to implement
66 * the automatic reset event semaphore semantics. */
67struct RTSEMEVENTMULTIINTERNAL
68{
69 /** pthread condition. */
70 pthread_cond_t Cond;
71 /** pthread mutex which protects the condition and the event state. */
72 pthread_mutex_t Mutex;
73 /** The state of the semaphore.
74 * This is operated while owning mutex and using atomic updating. */
75 volatile uint32_t u32State;
76 /** Number of waiters. */
77 volatile uint32_t cWaiters;
78#ifdef RTSEMEVENTMULTI_STRICT
79 /** Signallers. */
80 RTLOCKVALRECSHRD Signallers;
81 /** Indicates that lock validation should be performed. */
82 bool volatile fEverHadSignallers;
83#endif
84 /** Set if we're using the monotonic clock. */
85 bool fMonotonicClock;
86};
87
88/** The values of the u32State variable in RTSEMEVENTMULTIINTERNAL.
89 * @{ */
90/** The object isn't initialized. */
91#define EVENTMULTI_STATE_UNINITIALIZED 0
92/** The semaphore is signaled. */
93#define EVENTMULTI_STATE_SIGNALED 0xff00ff00
94/** The semaphore is not signaled. */
95#define EVENTMULTI_STATE_NOT_SIGNALED 0x00ff00ff
96/** @} */
97
98
99
100RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem)
101{
102 return RTSemEventMultiCreateEx(phEventMultiSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
103}
104
105
106RTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
107 const char *pszNameFmt, ...)
108{
109 AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
110
111 /*
112 * Allocate semaphore handle.
113 */
114 int rc;
115 struct RTSEMEVENTMULTIINTERNAL *pThis = (struct RTSEMEVENTMULTIINTERNAL *)RTMemAlloc(sizeof(struct RTSEMEVENTMULTIINTERNAL));
116 if (pThis)
117 {
118 /*
119 * Create the condition variable.
120 */
121 pthread_condattr_t CondAttr;
122 rc = pthread_condattr_init(&CondAttr);
123 if (!rc)
124 {
125#if defined(CLOCK_MONOTONIC) && defined(IPRT_HAVE_PTHREAD_CONDATTR_SETCLOCK)
126 /* ASSUMES RTTimeSystemNanoTS() == RTTimeNanoTS() == clock_gettime(CLOCK_MONOTONIC). */
127 rc = pthread_condattr_setclock(&CondAttr, CLOCK_MONOTONIC);
128 pThis->fMonotonicClock = rc == 0;
129#else
130 pThis->fMonotonicClock = false;
131#endif
132 rc = pthread_cond_init(&pThis->Cond, &CondAttr);
133 if (!rc)
134 {
135 /*
136 * Create the semaphore.
137 */
138 rc = pthread_mutex_init(&pThis->Mutex, NULL);
139 if (!rc)
140 {
141 pthread_condattr_destroy(&CondAttr);
142
143 ASMAtomicWriteU32(&pThis->u32State, EVENTMULTI_STATE_NOT_SIGNALED);
144 ASMAtomicWriteU32(&pThis->cWaiters, 0);
145#ifdef RTSEMEVENTMULTI_STRICT
146 if (!pszNameFmt)
147 {
148 static uint32_t volatile s_iSemEventMultiAnon = 0;
149 RTLockValidatorRecSharedInit(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
150 true /*fSignaller*/, !(fFlags & RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL),
151 "RTSemEventMulti-%u", ASMAtomicIncU32(&s_iSemEventMultiAnon) - 1);
152 }
153 else
154 {
155 va_list va;
156 va_start(va, pszNameFmt);
157 RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
158 true /*fSignaller*/, !(fFlags & RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL),
159 pszNameFmt, va);
160 va_end(va);
161 }
162 pThis->fEverHadSignallers = false;
163#else
164 RT_NOREF_PV(hClass); RT_NOREF_PV(pszNameFmt);
165#endif
166
167 *phEventMultiSem = pThis;
168 return VINF_SUCCESS;
169 }
170
171 pthread_cond_destroy(&pThis->Cond);
172 }
173 pthread_condattr_destroy(&CondAttr);
174 }
175 rc = RTErrConvertFromErrno(rc);
176 RTMemFree(pThis);
177 }
178 else
179 rc = VERR_NO_MEMORY;
180
181 return rc;
182
183}
184
185
186RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
187{
188 /*
189 * Validate handle.
190 */
191 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
192 if (pThis == NIL_RTSEMEVENTMULTI)
193 return VINF_SUCCESS;
194 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
195 uint32_t u32 = pThis->u32State;
196 AssertReturn(u32 == EVENTMULTI_STATE_NOT_SIGNALED || u32 == EVENTMULTI_STATE_SIGNALED, VERR_INVALID_HANDLE);
197
198 /*
199 * Abort all waiters forcing them to return failure.
200 */
201 int rc;
202 for (int i = 30; i > 0; i--)
203 {
204 ASMAtomicXchgU32(&pThis->u32State, EVENTMULTI_STATE_UNINITIALIZED);
205 rc = pthread_cond_destroy(&pThis->Cond);
206 if (rc != EBUSY)
207 break;
208 pthread_cond_broadcast(&pThis->Cond);
209 usleep(1000);
210 }
211 if (rc)
212 {
213 AssertMsgFailed(("Failed to destroy event sem %p, rc=%d.\n", hEventMultiSem, rc));
214 return RTErrConvertFromErrno(rc);
215 }
216
217 /*
218 * Destroy the semaphore
219 * If it's busy we'll wait a bit to give the threads a chance to be scheduled.
220 */
221 for (int i = 30; i > 0; i--)
222 {
223 rc = pthread_mutex_destroy(&pThis->Mutex);
224 if (rc != EBUSY)
225 break;
226 usleep(1000);
227 }
228 if (rc)
229 {
230 AssertMsgFailed(("Failed to destroy event sem %p, rc=%d. (mutex)\n", hEventMultiSem, rc));
231 return RTErrConvertFromErrno(rc);
232 }
233
234 /*
235 * Free the semaphore memory and be gone.
236 */
237#ifdef RTSEMEVENTMULTI_STRICT
238 RTLockValidatorRecSharedDelete(&pThis->Signallers);
239#endif
240 RTMemFree(pThis);
241 return VINF_SUCCESS;
242}
243
244
245RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
246{
247 /*
248 * Validate input.
249 */
250 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
251 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
252 uint32_t u32 = pThis->u32State;
253 AssertReturn(u32 == EVENTMULTI_STATE_NOT_SIGNALED || u32 == EVENTMULTI_STATE_SIGNALED, VERR_INVALID_HANDLE);
254
255#ifdef RTSEMEVENTMULTI_STRICT
256 if (pThis->fEverHadSignallers)
257 {
258 int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
259 if (RT_FAILURE(rc9))
260 return rc9;
261 }
262#endif
263
264 /*
265 * Lock the mutex semaphore.
266 */
267 int rc = pthread_mutex_lock(&pThis->Mutex);
268 if (rc)
269 {
270 AssertMsgFailed(("Failed to lock event sem %p, rc=%d.\n", hEventMultiSem, rc));
271 return RTErrConvertFromErrno(rc);
272 }
273
274 /*
275 * Check the state.
276 */
277 if (pThis->u32State == EVENTMULTI_STATE_NOT_SIGNALED)
278 {
279 ASMAtomicXchgU32(&pThis->u32State, EVENTMULTI_STATE_SIGNALED);
280 rc = pthread_cond_broadcast(&pThis->Cond);
281 AssertMsg(!rc, ("Failed to signal event sem %p, rc=%d.\n", hEventMultiSem, rc));
282 }
283 else if (pThis->u32State == EVENTMULTI_STATE_SIGNALED)
284 {
285 rc = pthread_cond_broadcast(&pThis->Cond); /* give'm another kick... */
286 AssertMsg(!rc, ("Failed to signal event sem %p, rc=%d. (2)\n", hEventMultiSem, rc));
287 }
288 else
289 rc = VERR_SEM_DESTROYED;
290
291 /*
292 * Release the mutex and return.
293 */
294 int rc2 = pthread_mutex_unlock(&pThis->Mutex);
295 AssertMsg(!rc2, ("Failed to unlock event sem %p, rc=%d.\n", hEventMultiSem, rc));
296 if (rc)
297 return RTErrConvertFromErrno(rc);
298 if (rc2)
299 return RTErrConvertFromErrno(rc2);
300
301 return VINF_SUCCESS;
302}
303
304
305RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
306{
307 /*
308 * Validate input.
309 */
310 int rc = VINF_SUCCESS;
311 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
312 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
313 uint32_t u32 = pThis->u32State;
314 AssertReturn(u32 == EVENTMULTI_STATE_NOT_SIGNALED || u32 == EVENTMULTI_STATE_SIGNALED, VERR_INVALID_HANDLE);
315
316 /*
317 * Lock the mutex semaphore.
318 */
319 int rcPosix = pthread_mutex_lock(&pThis->Mutex);
320 if (RT_UNLIKELY(rcPosix))
321 {
322 AssertMsgFailed(("Failed to lock event multi sem %p, rc=%d.\n", hEventMultiSem, rcPosix));
323 return RTErrConvertFromErrno(rcPosix);
324 }
325
326 /*
327 * Check the state.
328 */
329 if (pThis->u32State == EVENTMULTI_STATE_SIGNALED)
330 ASMAtomicXchgU32(&pThis->u32State, EVENTMULTI_STATE_NOT_SIGNALED);
331 else if (pThis->u32State != EVENTMULTI_STATE_NOT_SIGNALED)
332 rc = VERR_SEM_DESTROYED;
333
334 /*
335 * Release the mutex and return.
336 */
337 rcPosix = pthread_mutex_unlock(&pThis->Mutex);
338 if (RT_UNLIKELY(rcPosix))
339 {
340 AssertMsgFailed(("Failed to unlock event multi sem %p, rc=%d.\n", hEventMultiSem, rcPosix));
341 return RTErrConvertFromErrno(rcPosix);
342 }
343
344 return rc;
345}
346
347
348/**
349 * Handle polling (timeout already expired at the time of the call).
350 *
351 * @returns VINF_SUCCESS, VERR_TIMEOUT, VERR_SEM_DESTROYED.
352 * @param pThis The semaphore.
353 */
354DECLINLINE(int) rtSemEventMultiPosixWaitPoll(struct RTSEMEVENTMULTIINTERNAL *pThis)
355{
356 int rc = pthread_mutex_lock(&pThis->Mutex);
357 AssertMsgReturn(!rc, ("Failed to lock event multi sem %p, rc=%d.\n", pThis, rc), RTErrConvertFromErrno(rc));
358
359 uint32_t const u32State = pThis->u32State;
360
361 rc = pthread_mutex_unlock(&pThis->Mutex);
362 AssertMsg(!rc, ("Failed to unlock event multi sem %p, rc=%d.\n", pThis, rc)); NOREF(rc);
363
364 return u32State == EVENTMULTI_STATE_SIGNALED
365 ? VINF_SUCCESS
366 : u32State != EVENTMULTI_STATE_UNINITIALIZED
367 ? VERR_TIMEOUT
368 : VERR_SEM_DESTROYED;
369}
370
371
372
373/**
374 * Implements the indefinite wait.
375 *
376 * @returns See RTSemEventMultiWaitEx.
377 * @param pThis The semaphore.
378 * @param fFlags See RTSemEventMultiWaitEx.
379 * @param pSrcPos The source position, can be NULL.
380 */
381static int rtSemEventMultiPosixWaitIndefinite(struct RTSEMEVENTMULTIINTERNAL *pThis, uint32_t fFlags, PCRTLOCKVALSRCPOS pSrcPos)
382{
383 /* take mutex */
384 int rc = pthread_mutex_lock(&pThis->Mutex);
385 AssertMsgReturn(!rc, ("Failed to lock event multi sem %p, rc=%d.\n", pThis, rc), RTErrConvertFromErrno(rc));
386 ASMAtomicIncU32(&pThis->cWaiters);
387
388 for (;;)
389 {
390 /* check state. */
391 uint32_t const u32State = pThis->u32State;
392 if (u32State != EVENTMULTI_STATE_NOT_SIGNALED)
393 {
394 ASMAtomicDecU32(&pThis->cWaiters);
395 rc = pthread_mutex_unlock(&pThis->Mutex);
396 AssertMsg(!rc, ("Failed to unlock event multi sem %p, rc=%d.\n", pThis, rc));
397 return u32State == EVENTMULTI_STATE_SIGNALED
398 ? VINF_SUCCESS
399 : VERR_SEM_DESTROYED;
400 }
401
402 /* wait */
403#ifdef RTSEMEVENTMULTI_STRICT
404 RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
405 if (pThis->fEverHadSignallers)
406 {
407 rc = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
408 RT_INDEFINITE_WAIT, RTTHREADSTATE_EVENT_MULTI, true);
409 if (RT_FAILURE(rc))
410 {
411 ASMAtomicDecU32(&pThis->cWaiters);
412 pthread_mutex_unlock(&pThis->Mutex);
413 return rc;
414 }
415 }
416#else
417 RTTHREAD hThreadSelf = RTThreadSelf();
418 RT_NOREF_PV(pSrcPos);
419#endif
420 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true);
421 /** @todo interruptible wait is not implementable... */ NOREF(fFlags);
422 rc = pthread_cond_wait(&pThis->Cond, &pThis->Mutex);
423 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI);
424 if (RT_UNLIKELY(rc))
425 {
426 AssertMsgFailed(("Failed to wait on event multi sem %p, rc=%d.\n", pThis, rc));
427 ASMAtomicDecU32(&pThis->cWaiters);
428 int rc2 = pthread_mutex_unlock(&pThis->Mutex);
429 AssertMsg(!rc2, ("Failed to unlock event multi sem %p, rc=%d.\n", pThis, rc2)); NOREF(rc2);
430 return RTErrConvertFromErrno(rc);
431 }
432 }
433}
434
435
436/**
437 * Implements the timed wait.
438 *
439 * @returns See RTSemEventMultiWaitEx
440 * @param pThis The semaphore.
441 * @param fFlags See RTSemEventMultiWaitEx.
442 * @param uTimeout See RTSemEventMultiWaitEx.
443 * @param pSrcPos The source position, can be NULL.
444 */
445static int rtSemEventMultiPosixWaitTimed(struct RTSEMEVENTMULTIINTERNAL *pThis, uint32_t fFlags, uint64_t uTimeout,
446 PCRTLOCKVALSRCPOS pSrcPos)
447{
448 /*
449 * Convert the timeout specification to absolute and relative deadlines,
450 * divierting polling and infinite waits to the appropriate workers.
451 */
452 struct timespec AbsDeadline = { 0, 0 };
453 uint64_t const cNsRelativeDeadline = rtSemPosixCalcDeadline(fFlags, uTimeout, pThis->fMonotonicClock, &AbsDeadline);
454 if (cNsRelativeDeadline == 0)
455 return rtSemEventMultiPosixWaitPoll(pThis);
456 if (cNsRelativeDeadline == UINT64_MAX)
457 return rtSemEventMultiPosixWaitIndefinite(pThis, fFlags, pSrcPos);
458
459 /*
460 * To business!
461 */
462 /* take mutex */
463 int rc = pthread_mutex_lock(&pThis->Mutex);
464 AssertMsgReturn(rc == 0, ("rc=%d pThis=%p\n", rc, pThis), RTErrConvertFromErrno(rc)); NOREF(rc);
465 ASMAtomicIncU32(&pThis->cWaiters);
466
467 for (;;)
468 {
469 /* check state. */
470 uint32_t const u32State = pThis->u32State;
471 if (u32State != EVENTMULTI_STATE_NOT_SIGNALED)
472 {
473 ASMAtomicDecU32(&pThis->cWaiters);
474 rc = pthread_mutex_unlock(&pThis->Mutex);
475 AssertMsg(!rc, ("Failed to unlock event multi sem %p, rc=%d.\n", pThis, rc));
476 return u32State == EVENTMULTI_STATE_SIGNALED
477 ? VINF_SUCCESS
478 : VERR_SEM_DESTROYED;
479 }
480
481 /* wait */
482#ifdef RTSEMEVENTMULTI_STRICT
483 RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
484 if (pThis->fEverHadSignallers)
485 {
486 rc = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
487 (uTimeout + RT_NS_1MS - 1)/ RT_NS_1MS, RTTHREADSTATE_EVENT_MULTI, true);
488 if (RT_FAILURE(rc))
489 {
490 ASMAtomicDecU32(&pThis->cWaiters);
491 pthread_mutex_unlock(&pThis->Mutex);
492 return rc;
493 }
494 }
495#else
496 RTTHREAD hThreadSelf = RTThreadSelf();
497#endif
498 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true);
499 rc = pthread_cond_timedwait(&pThis->Cond, &pThis->Mutex, &AbsDeadline);
500 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI);
501
502 /* According to SuS this function shall not return EINTR, but linux man page might have said differently at some point... */
503 if ( rc != 0
504 && ( rc != EINTR
505 || (fFlags & RTSEMWAIT_FLAGS_NORESUME)) )
506 {
507 AssertMsg(rc == ETIMEDOUT, ("Failed to wait on event multi sem %p, rc=%d.\n", pThis, rc));
508 ASMAtomicDecU32(&pThis->cWaiters);
509 int rc2 = pthread_mutex_unlock(&pThis->Mutex);
510 AssertMsg(!rc2, ("Failed to unlock event multi sem %p, rc=%d.\n", pThis, rc2)); NOREF(rc2);
511 return RTErrConvertFromErrno(rc);
512 }
513 }
514}
515
516
517DECLINLINE(int) rtSemEventMultiPosixWait(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
518 PCRTLOCKVALSRCPOS pSrcPos)
519{
520 /*
521 * Validate input.
522 */
523 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
524 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
525 uint32_t u32 = pThis->u32State;
526 AssertReturn(u32 == EVENTMULTI_STATE_NOT_SIGNALED || u32 == EVENTMULTI_STATE_SIGNALED, VERR_INVALID_HANDLE);
527 AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
528
529 /*
530 * Optimize the case where the event is signalled.
531 */
532 if (ASMAtomicUoReadU32(&pThis->u32State) == EVENTMULTI_STATE_SIGNALED)
533 {
534 int rc = rtSemEventMultiPosixWaitPoll(pThis);
535 if (RT_LIKELY(rc != VERR_TIMEOUT))
536 return rc;
537 }
538
539 /*
540 * Indefinite or timed wait?
541 */
542 if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE)
543 return rtSemEventMultiPosixWaitIndefinite(pThis, fFlags, pSrcPos);
544 return rtSemEventMultiPosixWaitTimed(pThis, fFlags, uTimeout, pSrcPos);
545}
546
547
548#undef RTSemEventMultiWaitEx
549RTDECL(int) RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout)
550{
551#ifndef RTSEMEVENT_STRICT
552 return rtSemEventMultiPosixWait(hEventMultiSem, fFlags, uTimeout, NULL);
553#else
554 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
555 return rtSemEventMultiPosixWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
556#endif
557}
558
559
560RTDECL(int) RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
561 RTHCUINTPTR uId, RT_SRC_POS_DECL)
562{
563 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
564 return rtSemEventMultiPosixWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
565}
566
567
568RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
569{
570#ifdef RTSEMEVENTMULTI_STRICT
571 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
572 AssertPtrReturnVoid(pThis);
573 uint32_t u32 = pThis->u32State;
574 AssertReturnVoid(u32 == EVENTMULTI_STATE_NOT_SIGNALED || u32 == EVENTMULTI_STATE_SIGNALED);
575
576 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
577 RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
578#else
579 RT_NOREF_PV(hEventMultiSem); RT_NOREF_PV(hThread);
580#endif
581}
582
583
584RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
585{
586#ifdef RTSEMEVENTMULTI_STRICT
587 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
588 AssertPtrReturnVoid(pThis);
589 uint32_t u32 = pThis->u32State;
590 AssertReturnVoid(u32 == EVENTMULTI_STATE_NOT_SIGNALED || u32 == EVENTMULTI_STATE_SIGNALED);
591
592 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
593 RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
594#else
595 RT_NOREF_PV(hEventMultiSem); RT_NOREF_PV(hThread);
596#endif
597}
598
599
600RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
601{
602#ifdef RTSEMEVENTMULTI_STRICT
603 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
604 AssertPtrReturnVoid(pThis);
605 uint32_t u32 = pThis->u32State;
606 AssertReturnVoid(u32 == EVENTMULTI_STATE_NOT_SIGNALED || u32 == EVENTMULTI_STATE_SIGNALED);
607
608 RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
609#else
610 RT_NOREF_PV(hEventMultiSem); RT_NOREF_PV(hThread);
611#endif
612}
613
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use