VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp@ 103795

Last change on this file since 103795 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: 20.5 KB
Line 
1/* $Id: semeventmulti-linux.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - Multiple Release Event Semaphore, Linux (2.6.x+).
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#include <features.h>
39#if __GLIBC_PREREQ(2,6) && !defined(IPRT_WITH_FUTEX_BASED_SEMS)
40
41/*
42 * glibc 2.6 fixed a serious bug in the mutex implementation. We wrote this
43 * linux specific event semaphores code in order to work around the bug. As it
44 * turns out, this code seems to have an unresolved issue (@bugref{2599}), so we'll
45 * fall back on the pthread based implementation if glibc is known to contain
46 * the bug fix.
47 *
48 * The external reference to epoll_pwait is a hack which prevents that we link
49 * against glibc < 2.6.
50 */
51#include "../posix/semeventmulti-posix.cpp"
52__asm__ (".global epoll_pwait");
53
54#else /* glibc < 2.6 */
55
56
57/*********************************************************************************************************************************
58* Header Files *
59*********************************************************************************************************************************/
60#include <iprt/semaphore.h>
61#include "internal/iprt.h"
62
63#include <iprt/assert.h>
64#include <iprt/asm.h>
65#include <iprt/err.h>
66#include <iprt/lockvalidator.h>
67#include <iprt/mem.h>
68#include <iprt/time.h>
69#include "internal/magics.h"
70#include "internal/strict.h"
71
72
73#include <errno.h>
74#include <limits.h>
75#include <pthread.h>
76#include <unistd.h>
77#include <sys/time.h>
78#include <sys/syscall.h>
79
80#include "semwait-linux.h"
81
82
83/*********************************************************************************************************************************
84* Structures and Typedefs *
85*********************************************************************************************************************************/
86/**
87 * Linux multiple wakup event semaphore.
88 */
89struct RTSEMEVENTMULTIINTERNAL
90{
91 /** Magic value. */
92 uint32_t volatile u32Magic;
93 /** The futex state variable, see RTSEMEVENTMULTI_LNX_XXX. */
94 uint32_t volatile uState;
95#ifdef RT_STRICT
96 /** Increased on every signalling call. */
97 uint32_t volatile uSignalSerialNo;
98#endif
99#ifdef RTSEMEVENTMULTI_STRICT
100 /** Signallers. */
101 RTLOCKVALRECSHRD Signallers;
102 /** Indicates that lock validation should be performed. */
103 bool volatile fEverHadSignallers;
104#endif
105};
106
107
108/*********************************************************************************************************************************
109* Defined Constants And Macros *
110*********************************************************************************************************************************/
111/** @name RTSEMEVENTMULTI_LNX_XXX - state
112 * @{ */
113#define RTSEMEVENTMULTI_LNX_NOT_SIGNALED UINT32_C(0x00000000)
114#define RTSEMEVENTMULTI_LNX_NOT_SIGNALED_WAITERS UINT32_C(0x00000001)
115#define RTSEMEVENTMULTI_LNX_SIGNALED UINT32_C(0x00000003)
116/** @} */
117
118#define ASSERT_VALID_STATE(a_uState) \
119 AssertMsg( (a_uState) == RTSEMEVENTMULTI_LNX_NOT_SIGNALED \
120 || (a_uState) == RTSEMEVENTMULTI_LNX_NOT_SIGNALED_WAITERS \
121 || (a_uState) == RTSEMEVENTMULTI_LNX_SIGNALED, \
122 (#a_uState "=%s\n", a_uState))
123
124
125/*********************************************************************************************************************************
126* Global Variables *
127*********************************************************************************************************************************/
128/** Whether we can use FUTEX_WAIT_BITSET. */
129static int volatile g_fCanUseWaitBitSet = -1;
130
131
132RTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem)
133{
134 return RTSemEventMultiCreateEx(phEventMultiSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
135}
136
137
138RTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
139 const char *pszNameFmt, ...)
140{
141 AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
142
143 /*
144 * Make sure we know whether FUTEX_WAIT_BITSET works.
145 */
146 rtSemLinuxCheckForFutexWaitBitSet(&g_fCanUseWaitBitSet);
147#if defined(DEBUG_bird) && !defined(IN_GUEST)
148 Assert(g_fCanUseWaitBitSet == true);
149#endif
150
151 /*
152 * Allocate semaphore handle.
153 */
154 struct RTSEMEVENTMULTIINTERNAL *pThis = (struct RTSEMEVENTMULTIINTERNAL *)RTMemAlloc(sizeof(struct RTSEMEVENTMULTIINTERNAL));
155 if (pThis)
156 {
157 pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
158 pThis->uState = RTSEMEVENTMULTI_LNX_NOT_SIGNALED;
159#ifdef RT_STRICT
160 pThis->uSignalSerialNo = 0;
161#endif
162#ifdef RTSEMEVENTMULTI_STRICT
163 if (!pszNameFmt)
164 {
165 static uint32_t volatile s_iSemEventMultiAnon = 0;
166 RTLockValidatorRecSharedInit(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
167 true /*fSignaller*/, !(fFlags & RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL),
168 "RTSemEventMulti-%u", ASMAtomicIncU32(&s_iSemEventMultiAnon) - 1);
169 }
170 else
171 {
172 va_list va;
173 va_start(va, pszNameFmt);
174 RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
175 true /*fSignaller*/, !(fFlags & RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL),
176 pszNameFmt, va);
177 va_end(va);
178 }
179 pThis->fEverHadSignallers = false;
180#else
181 RT_NOREF(hClass, pszNameFmt);
182#endif
183
184 *phEventMultiSem = pThis;
185 return VINF_SUCCESS;
186 }
187 return VERR_NO_MEMORY;
188}
189
190
191RTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
192{
193 /*
194 * Validate input.
195 */
196 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
197 if (pThis == NIL_RTSEMEVENTMULTI)
198 return VINF_SUCCESS;
199 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
200 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
201
202 /*
203 * Invalidate the semaphore and wake up anyone waiting on it.
204 */
205 ASMAtomicWriteU32(&pThis->u32Magic, RTSEMEVENTMULTI_MAGIC + 1);
206 if (ASMAtomicXchgU32(&pThis->uState, RTSEMEVENTMULTI_LNX_SIGNALED) == RTSEMEVENTMULTI_LNX_NOT_SIGNALED_WAITERS)
207 {
208 sys_futex(&pThis->uState, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
209 usleep(1000);
210 }
211
212 /*
213 * Free the semaphore memory and be gone.
214 */
215#ifdef RTSEMEVENTMULTI_STRICT
216 RTLockValidatorRecSharedDelete(&pThis->Signallers);
217#endif
218 RTMemFree(pThis);
219 return VINF_SUCCESS;
220}
221
222
223RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
224{
225 /*
226 * Validate input.
227 */
228 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
229 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
230 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
231
232#ifdef RTSEMEVENTMULTI_STRICT
233 if (pThis->fEverHadSignallers)
234 {
235 int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
236 if (RT_FAILURE(rc9))
237 return rc9;
238 }
239#endif
240
241 /*
242 * Signal it.
243 */
244#ifdef RT_STRICT
245 ASMAtomicIncU32(&pThis->uSignalSerialNo);
246#endif
247 uint32_t uOld = ASMAtomicXchgU32(&pThis->uState, RTSEMEVENTMULTI_LNX_SIGNALED);
248 if (uOld == RTSEMEVENTMULTI_LNX_NOT_SIGNALED_WAITERS)
249 {
250 /* wake up sleeping threads. */
251 long cWoken = sys_futex(&pThis->uState, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
252 AssertMsg(cWoken >= 0, ("%ld\n", cWoken)); NOREF(cWoken);
253 }
254 ASSERT_VALID_STATE(uOld);
255 return VINF_SUCCESS;
256}
257
258
259RTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
260{
261 /*
262 * Validate input.
263 */
264 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
265 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
266 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
267#ifdef RT_STRICT
268 uint32_t const uState = pThis->uState;
269 ASSERT_VALID_STATE(uState);
270#endif
271
272 /*
273 * Reset it.
274 */
275 ASMAtomicCmpXchgU32(&pThis->uState, RTSEMEVENTMULTI_LNX_NOT_SIGNALED, RTSEMEVENTMULTI_LNX_SIGNALED);
276 return VINF_SUCCESS;
277}
278
279
280/**
281 * Performs an indefinite wait on the event.
282 */
283static int rtSemEventMultiLinuxWaitIndefinite(struct RTSEMEVENTMULTIINTERNAL *pThis, uint32_t fFlags, PCRTLOCKVALSRCPOS pSrcPos)
284{
285 RT_NOREF(pSrcPos);
286
287 /*
288 * Quickly check whether it's signaled.
289 */
290 uint32_t uState = ASMAtomicUoReadU32(&pThis->uState);
291 if (uState == RTSEMEVENTMULTI_LNX_SIGNALED)
292 return VINF_SUCCESS;
293 ASSERT_VALID_STATE(uState);
294
295 /*
296 * The wait loop.
297 */
298#ifdef RTSEMEVENTMULTI_STRICT
299 RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
300#else
301 RTTHREAD hThreadSelf = RTThreadSelf();
302#endif
303 for (unsigned i = 0;; i++)
304 {
305 /*
306 * Start waiting. We only account for there being or having been
307 * threads waiting on the semaphore to keep things simple.
308 */
309 uState = ASMAtomicUoReadU32(&pThis->uState);
310 if ( uState == RTSEMEVENTMULTI_LNX_NOT_SIGNALED_WAITERS
311 || ( uState == RTSEMEVENTMULTI_LNX_NOT_SIGNALED
312 && ASMAtomicCmpXchgU32(&pThis->uState, RTSEMEVENTMULTI_LNX_NOT_SIGNALED_WAITERS,
313 RTSEMEVENTMULTI_LNX_NOT_SIGNALED)))
314 {
315#ifdef RTSEMEVENTMULTI_STRICT
316 if (pThis->fEverHadSignallers)
317 {
318 int rc9 = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
319 RT_INDEFINITE_WAIT, RTTHREADSTATE_EVENT_MULTI, true);
320 if (RT_FAILURE(rc9))
321 return rc9;
322 }
323#endif
324#ifdef RT_STRICT
325 uint32_t const uPrevSignalSerialNo = ASMAtomicReadU32(&pThis->uSignalSerialNo);
326#endif
327 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true);
328 long rc = sys_futex(&pThis->uState, FUTEX_WAIT, 1, NULL /*pTimeout*/, NULL, 0);
329 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI);
330
331 /* Check that the structure is still alive before continuing. */
332 if (RT_LIKELY(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC))
333 { /*likely*/ }
334 else
335 return VERR_SEM_DESTROYED;
336
337 /*
338 * Return if success.
339 */
340 if (rc == 0)
341 {
342 Assert(uPrevSignalSerialNo != ASMAtomicReadU32(&pThis->uSignalSerialNo));
343 return VINF_SUCCESS;
344 }
345
346 /*
347 * Act on the wakup code.
348 */
349 if (rc == -EWOULDBLOCK)
350 /* retry, the value changed. */;
351 else if (rc == -EINTR)
352 {
353 if (fFlags & RTSEMWAIT_FLAGS_NORESUME)
354 return VERR_INTERRUPTED;
355 }
356 else
357 {
358 /* this shouldn't happen! */
359 AssertMsgFailed(("rc=%ld errno=%d\n", rc, errno));
360 return RTErrConvertFromErrno(rc);
361 }
362 }
363 else if (uState == RTSEMEVENTMULTI_LNX_SIGNALED)
364 return VINF_SUCCESS;
365 else
366 ASSERT_VALID_STATE(uState);
367 }
368}
369
370
371/**
372 * Handle polling (timeout already expired at the time of the call).
373 *
374 * @returns VINF_SUCCESS, VERR_TIMEOUT, VERR_SEM_DESTROYED.
375 * @param pThis The semaphore.
376 */
377static int rtSemEventMultiLinuxWaitPoll(struct RTSEMEVENTMULTIINTERNAL *pThis)
378{
379 uint32_t uState = ASMAtomicUoReadU32(&pThis->uState);
380 if (uState == RTSEMEVENTMULTI_LNX_SIGNALED)
381 return VINF_SUCCESS;
382 return VERR_TIMEOUT;
383}
384
385
386/**
387 * Performs an indefinite wait on the event.
388 */
389static int rtSemEventMultiLinuxWaitTimed(struct RTSEMEVENTMULTIINTERNAL *pThis, uint32_t fFlags, uint64_t uTimeout,
390 PCRTLOCKVALSRCPOS pSrcPos)
391{
392 RT_NOREF(pSrcPos);
393
394 /*
395 * Quickly check whether it's signaled.
396 */
397 uint32_t uState = ASMAtomicUoReadU32(&pThis->uState);
398 if (uState == RTSEMEVENTMULTI_LNX_SIGNALED)
399 return VINF_SUCCESS;
400 ASSERT_VALID_STATE(uState);
401
402 /*
403 * Convert the timeout value.
404 */
405 struct timespec TsTimeout;
406 int iWaitOp;
407 uint32_t uWaitVal3;
408 uint64_t nsAbsTimeout = uTimeout; /* (older gcc maybe used uninitialized) */
409 uTimeout = rtSemLinuxCalcDeadline(fFlags, uTimeout, g_fCanUseWaitBitSet, &TsTimeout, &iWaitOp, &uWaitVal3, &nsAbsTimeout);
410 if (uTimeout == 0)
411 return rtSemEventMultiLinuxWaitPoll(pThis);
412 if (uTimeout == UINT64_MAX)
413 return rtSemEventMultiLinuxWaitIndefinite(pThis, fFlags, pSrcPos);
414
415 /*
416 * The wait loop.
417 */
418#ifdef RTSEMEVENTMULTI_STRICT
419 RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
420#else
421 RTTHREAD hThreadSelf = RTThreadSelf();
422#endif
423 for (unsigned i = 0;; i++)
424 {
425 /*
426 * Start waiting. We only account for there being or having been
427 * threads waiting on the semaphore to keep things simple.
428 */
429 uState = ASMAtomicUoReadU32(&pThis->uState);
430 if ( uState == RTSEMEVENTMULTI_LNX_NOT_SIGNALED_WAITERS
431 || ( uState == RTSEMEVENTMULTI_LNX_NOT_SIGNALED
432 && ASMAtomicCmpXchgU32(&pThis->uState, RTSEMEVENTMULTI_LNX_NOT_SIGNALED_WAITERS,
433 RTSEMEVENTMULTI_LNX_NOT_SIGNALED)))
434 {
435#ifdef RTSEMEVENTMULTI_STRICT
436 if (pThis->fEverHadSignallers)
437 {
438 int rc9 = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
439 uTimeout / UINT32_C(1000000), RTTHREADSTATE_EVENT_MULTI, true);
440 if (RT_FAILURE(rc9))
441 return rc9;
442 }
443#endif
444#ifdef RT_STRICT
445 uint32_t const uPrevSignalSerialNo = ASMAtomicReadU32(&pThis->uSignalSerialNo);
446#endif
447 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true);
448 long rc = sys_futex(&pThis->uState, iWaitOp, 1, &TsTimeout, NULL, uWaitVal3);
449 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI);
450
451 /* Check that the structure is still alive before continuing. */
452 if (RT_LIKELY(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC))
453 { /*likely*/ }
454 else
455 return VERR_SEM_DESTROYED;
456
457 /*
458 * Return if success.
459 */
460 if (rc == 0)
461 {
462 Assert(uPrevSignalSerialNo != ASMAtomicReadU32(&pThis->uSignalSerialNo));
463 return VINF_SUCCESS;
464 }
465
466 /*
467 * Act on the wakup code.
468 */
469 if (rc == -ETIMEDOUT)
470 {
471 /** @todo something is broken here. shows up every now and again in the ata
472 * code. Should try to run the timeout against RTTimeMilliTS to
473 * check that it's doing the right thing... */
474#ifdef RT_STRICT
475 uint64_t const uNow = RTTimeNanoTS();
476 AssertMsg(uNow >= nsAbsTimeout || nsAbsTimeout - uNow < RT_NS_1MS,
477 ("%#RX64 - %#RX64 => %#RX64 (%RI64)\n", nsAbsTimeout, uNow, nsAbsTimeout - uNow, nsAbsTimeout - uNow));
478#endif
479 return VERR_TIMEOUT;
480 }
481 if (rc == -EWOULDBLOCK)
482 {
483 /* retry, the value changed. */;
484 }
485 else if (rc == -EINTR)
486 {
487 if (fFlags & RTSEMWAIT_FLAGS_NORESUME)
488 return VERR_INTERRUPTED;
489 }
490 else
491 {
492 /* this shouldn't happen! */
493 AssertMsgFailed(("rc=%ld errno=%d\n", rc, errno));
494 return RTErrConvertFromErrno(rc);
495 }
496 }
497 else if (uState == RTSEMEVENTMULTI_LNX_SIGNALED)
498 return VINF_SUCCESS;
499 else
500 ASSERT_VALID_STATE(uState);
501
502 /* adjust the relative timeout if relative */
503 if (iWaitOp == FUTEX_WAIT)
504 {
505 int64_t i64Diff = nsAbsTimeout - RTTimeSystemNanoTS();
506 if (i64Diff < 1000)
507 return VERR_TIMEOUT;
508 TsTimeout.tv_sec = (uint64_t)i64Diff / RT_NS_1SEC;
509 TsTimeout.tv_nsec = (uint64_t)i64Diff % RT_NS_1SEC;
510 }
511 }
512}
513
514/**
515 * Internal wait worker function.
516 */
517DECLINLINE(int) rtSemEventLnxMultiWait(RTSEMEVENTMULTI hEventSem, uint32_t fFlags, uint64_t uTimeout, PCRTLOCKVALSRCPOS pSrcPos)
518{
519 /*
520 * Validate input.
521 */
522 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventSem;
523 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
524 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
525 AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
526
527 /*
528 * Timed or indefinite wait?
529 */
530 if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE)
531 return rtSemEventMultiLinuxWaitIndefinite(pThis, fFlags, pSrcPos);
532 return rtSemEventMultiLinuxWaitTimed(hEventSem, fFlags, uTimeout, pSrcPos);
533}
534
535
536#undef RTSemEventMultiWaitEx
537RTDECL(int) RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout)
538{
539#ifndef RTSEMEVENT_STRICT
540 return rtSemEventLnxMultiWait(hEventMultiSem, fFlags, uTimeout, NULL);
541#else
542 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
543 return rtSemEventLnxMultiWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
544#endif
545}
546
547
548RTDECL(int) RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout,
549 RTHCUINTPTR uId, RT_SRC_POS_DECL)
550{
551 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
552 return rtSemEventLnxMultiWait(hEventMultiSem, fFlags, uTimeout, &SrcPos);
553}
554
555
556RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
557{
558#ifdef RTSEMEVENTMULTI_STRICT
559 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
560 AssertPtrReturnVoid(pThis);
561 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
562
563 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
564 RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
565#else
566 RT_NOREF(hEventMultiSem, hThread);
567#endif
568}
569
570
571RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
572{
573#ifdef RTSEMEVENTMULTI_STRICT
574 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
575 AssertPtrReturnVoid(pThis);
576 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
577
578 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
579 RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
580#else
581 RT_NOREF(hEventMultiSem, hThread);
582#endif
583}
584
585
586RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
587{
588#ifdef RTSEMEVENTMULTI_STRICT
589 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
590 AssertPtrReturnVoid(pThis);
591 AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
592
593 RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
594#else
595 RT_NOREF(hEventMultiSem, hThread);
596#endif
597}
598
599#endif /* glibc < 2.6 || IPRT_WITH_FUTEX_BASED_SEMS */
600
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