VirtualBox

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

Last change on this file since 92776 was 92776, checked in by vboxsync, 3 years ago

IPRT/r3/posix: Implemented RTSemEventWaitEx. bugref:10138

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