VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/linux/semevent-linux.cpp@ 100194

Last change on this file since 100194 was 98103, checked in by vboxsync, 22 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 19.6 KB
Line 
1/* $Id: semevent-linux.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - Event Semaphore, Linux (2.6.0 and later).
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#include <features.h>
38#if __GLIBC_PREREQ(2,6) && !defined(IPRT_WITH_FUTEX_BASED_SEMS)
39
40/*
41 * glibc 2.6 fixed a serious bug in the mutex implementation. We wrote this
42 * linux specific event semaphores code in order to work around the bug. We
43 * will fall back on the pthread-based implementation if glibc is known to
44 * contain the bug fix.
45 *
46 * The external reference to epoll_pwait is a hack which prevents that we link
47 * against glibc < 2.6.
48 */
49# include "../posix/semevent-posix.cpp"
50__asm__ (".global epoll_pwait");
51
52#else /* glibc < 2.6 */
53
54
55/*********************************************************************************************************************************
56* Header Files *
57*********************************************************************************************************************************/
58#include <iprt/semaphore.h>
59#include "internal/iprt.h"
60
61#include <iprt/asm.h>
62#include <iprt/assert.h>
63#include <iprt/err.h>
64#include <iprt/lockvalidator.h>
65#include <iprt/mem.h>
66#include <iprt/time.h>
67#include "internal/magics.h"
68#include "internal/mem.h"
69#include "internal/strict.h"
70
71#include <errno.h>
72#include <limits.h>
73#include <pthread.h>
74#include <unistd.h>
75#include <sys/time.h>
76#include <sys/syscall.h>
77
78#include "semwait-linux.h"
79
80
81/*********************************************************************************************************************************
82* Structures and Typedefs *
83*********************************************************************************************************************************/
84/**
85 * Linux (single wakup) event semaphore.
86 */
87struct RTSEMEVENTINTERNAL
88{
89 /** Magic value. */
90 intptr_t volatile iMagic;
91 /** The futex state variable.
92 * 0 means not signalled.
93 1 means signalled. */
94 uint32_t volatile fSignalled;
95 /** The number of waiting threads */
96 int32_t volatile cWaiters;
97#ifdef RTSEMEVENT_STRICT
98 /** Signallers. */
99 RTLOCKVALRECSHRD Signallers;
100 /** Indicates that lock validation should be performed. */
101 bool volatile fEverHadSignallers;
102#endif
103 /** The creation flags. */
104 uint32_t fFlags;
105};
106
107
108/*********************************************************************************************************************************
109* Global Variables *
110*********************************************************************************************************************************/
111/** Whether we can use FUTEX_WAIT_BITSET. */
112static int volatile g_fCanUseWaitBitSet = -1;
113
114
115
116
117RTDECL(int) RTSemEventCreate(PRTSEMEVENT phEventSem)
118{
119 return RTSemEventCreateEx(phEventSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
120}
121
122
123RTDECL(int) RTSemEventCreateEx(PRTSEMEVENT phEventSem, uint32_t fFlags, RTLOCKVALCLASS hClass, const char *pszNameFmt, ...)
124{
125 AssertReturn(!(fFlags & ~(RTSEMEVENT_FLAGS_NO_LOCK_VAL | RTSEMEVENT_FLAGS_BOOTSTRAP_HACK)), VERR_INVALID_PARAMETER);
126 Assert(!(fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK) || (fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL));
127
128 /*
129 * Make sure we know whether FUTEX_WAIT_BITSET works.
130 */
131 rtSemLinuxCheckForFutexWaitBitSet(&g_fCanUseWaitBitSet);
132#if defined(DEBUG_bird) && !defined(IN_GUEST)
133 Assert(g_fCanUseWaitBitSet == true);
134#endif
135
136 /*
137 * Allocate semaphore handle.
138 */
139 struct RTSEMEVENTINTERNAL *pThis;
140 if (!(fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK))
141 pThis = (struct RTSEMEVENTINTERNAL *)RTMemAlloc(sizeof(struct RTSEMEVENTINTERNAL));
142 else
143 pThis = (struct RTSEMEVENTINTERNAL *)rtMemBaseAlloc(sizeof(struct RTSEMEVENTINTERNAL));
144 if (pThis)
145 {
146 pThis->iMagic = RTSEMEVENT_MAGIC;
147 pThis->cWaiters = 0;
148 pThis->fSignalled = 0;
149 pThis->fFlags = fFlags;
150#ifdef RTSEMEVENT_STRICT
151 if (!pszNameFmt)
152 {
153 static uint32_t volatile s_iSemEventAnon = 0;
154 RTLockValidatorRecSharedInit(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
155 true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL),
156 "RTSemEvent-%u", ASMAtomicIncU32(&s_iSemEventAnon) - 1);
157 }
158 else
159 {
160 va_list va;
161 va_start(va, pszNameFmt);
162 RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
163 true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL),
164 pszNameFmt, va);
165 va_end(va);
166 }
167 pThis->fEverHadSignallers = false;
168#else
169 RT_NOREF(hClass, pszNameFmt);
170#endif
171
172 *phEventSem = pThis;
173 return VINF_SUCCESS;
174 }
175 return VERR_NO_MEMORY;
176}
177
178
179RTDECL(int) RTSemEventDestroy(RTSEMEVENT hEventSem)
180{
181 /*
182 * Validate input.
183 */
184 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
185 if (pThis == NIL_RTSEMEVENT)
186 return VINF_SUCCESS;
187 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
188 AssertReturn(pThis->iMagic == RTSEMEVENT_MAGIC, VERR_INVALID_HANDLE);
189
190 /*
191 * Invalidate the semaphore and wake up anyone waiting on it.
192 */
193 ASMAtomicXchgSize(&pThis->iMagic, RTSEMEVENT_MAGIC | UINT32_C(0x80000000));
194 if (ASMAtomicXchgS32(&pThis->cWaiters, INT32_MIN / 2) > 0)
195 {
196 sys_futex(&pThis->fSignalled, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
197 usleep(1000);
198 }
199
200 /*
201 * Free the semaphore memory and be gone.
202 */
203#ifdef RTSEMEVENT_STRICT
204 RTLockValidatorRecSharedDelete(&pThis->Signallers);
205#endif
206 if (!(pThis->fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK))
207 RTMemFree(pThis);
208 else
209 rtMemBaseFree(pThis);
210 return VINF_SUCCESS;
211}
212
213
214RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem)
215{
216 /*
217 * Validate input.
218 */
219 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
220 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
221 AssertReturn(pThis->iMagic == RTSEMEVENT_MAGIC, VERR_INVALID_HANDLE);
222
223#ifdef RTSEMEVENT_STRICT
224 if (pThis->fEverHadSignallers)
225 {
226 int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
227 if (RT_FAILURE(rc9))
228 return rc9;
229 }
230#endif
231
232 ASMAtomicWriteU32(&pThis->fSignalled, 1);
233 if (ASMAtomicReadS32(&pThis->cWaiters) < 1)
234 return VINF_SUCCESS;
235
236 /* somebody is waiting, try wake up one of them. */
237 long cWoken = sys_futex(&pThis->fSignalled, FUTEX_WAKE, 1, NULL, NULL, 0);
238 if (RT_LIKELY(cWoken >= 0))
239 return VINF_SUCCESS;
240
241 if (RT_UNLIKELY(pThis->iMagic != RTSEMEVENT_MAGIC))
242 return VERR_SEM_DESTROYED;
243
244 return VERR_INVALID_PARAMETER;
245}
246
247
248/**
249 * Performs an indefinite wait on the event.
250 */
251static int rtSemEventLinuxWaitIndefinite(struct RTSEMEVENTINTERNAL *pThis, uint32_t fFlags, PCRTLOCKVALSRCPOS pSrcPos)
252{
253 RT_NOREF_PV(pSrcPos);
254
255 /*
256 * Quickly check whether it's signaled and there are no other waiters.
257 */
258 uint32_t cWaiters = ASMAtomicIncS32(&pThis->cWaiters);
259 if ( cWaiters == 1
260 && ASMAtomicCmpXchgU32(&pThis->fSignalled, 0, 1))
261 {
262 ASMAtomicDecS32(&pThis->cWaiters);
263 return VINF_SUCCESS;
264 }
265
266 /*
267 * The wait loop.
268 */
269#ifdef RTSEMEVENT_STRICT
270 RTTHREAD hThreadSelf = !(pThis->fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK)
271 ? RTThreadSelfAutoAdopt()
272 : RTThreadSelf();
273#else
274 RTTHREAD hThreadSelf = RTThreadSelf();
275#endif
276 int rc = VINF_SUCCESS;
277 for (;;)
278 {
279#ifdef RTSEMEVENT_STRICT
280 if (pThis->fEverHadSignallers)
281 {
282 rc = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
283 RT_INDEFINITE_WAIT, RTTHREADSTATE_EVENT, true);
284 if (RT_FAILURE(rc))
285 break;
286 }
287#endif
288 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT, true);
289 long lrc = sys_futex(&pThis->fSignalled, FUTEX_WAIT, 0, NULL /*pTimeout*/, NULL, 0);
290 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT);
291 if (RT_UNLIKELY(pThis->iMagic != RTSEMEVENT_MAGIC))
292 {
293 rc = VERR_SEM_DESTROYED;
294 break;
295 }
296
297 if (RT_LIKELY(lrc == 0 || lrc == -EWOULDBLOCK))
298 {
299 /* successful wakeup or fSignalled > 0 in the meantime */
300 if (ASMAtomicCmpXchgU32(&pThis->fSignalled, 0, 1))
301 break;
302 }
303 else if (lrc == -ETIMEDOUT)
304 {
305 rc = VERR_TIMEOUT;
306 break;
307 }
308 else if (lrc == -EINTR)
309 {
310 if (fFlags & RTSEMWAIT_FLAGS_NORESUME)
311 {
312 rc = VERR_INTERRUPTED;
313 break;
314 }
315 }
316 else
317 {
318 /* this shouldn't happen! */
319 AssertMsgFailed(("rc=%ld errno=%d\n", lrc, errno));
320 rc = RTErrConvertFromErrno(lrc);
321 break;
322 }
323 }
324
325 ASMAtomicDecS32(&pThis->cWaiters);
326 return rc;
327}
328
329
330/**
331 * Handle polling (timeout already expired at the time of the call).
332 *
333 * @returns VINF_SUCCESS, VERR_TIMEOUT, VERR_SEM_DESTROYED.
334 * @param pThis The semaphore.
335 */
336static int rtSemEventLinuxWaitPoll(struct RTSEMEVENTINTERNAL *pThis)
337{
338 /*
339 * What we do here is isn't quite fair to anyone else waiting on it, however
340 * it might not be as bad as all that for callers making repeated poll calls
341 * because they cannot block, as that would be a virtual wait but without the
342 * chance of a permanept queue position. So, I hope we can live with this.
343 */
344 if (ASMAtomicCmpXchgU32(&pThis->fSignalled, 0, 1))
345 return VINF_SUCCESS;
346 return VERR_TIMEOUT;
347}
348
349
350/**
351 * Performs an timed wait on the event.
352 */
353static int rtSemEventLinuxWaitTimed(struct RTSEMEVENTINTERNAL *pThis, uint32_t fFlags,
354 uint64_t uTimeout, PCRTLOCKVALSRCPOS pSrcPos)
355{
356 RT_NOREF_PV(pSrcPos);
357
358 /*
359 * Convert the timeout value.
360 */
361 struct timespec TsTimeout;
362 int iWaitOp;
363 uint32_t uWaitVal3;
364 uint64_t nsAbsTimeout = uTimeout; /* (older gcc maybe used uninitialized) */
365 uTimeout = rtSemLinuxCalcDeadline(fFlags, uTimeout, g_fCanUseWaitBitSet, &TsTimeout, &iWaitOp, &uWaitVal3, &nsAbsTimeout);
366 if (uTimeout == 0)
367 return rtSemEventLinuxWaitPoll(pThis);
368 if (uTimeout == UINT64_MAX)
369 return rtSemEventLinuxWaitIndefinite(pThis, fFlags, pSrcPos);
370
371 /*
372 * Quickly check whether it's signaled and there are no other waiters.
373 */
374 uint32_t cWaiters = ASMAtomicIncS32(&pThis->cWaiters);
375 if ( cWaiters == 1
376 && ASMAtomicCmpXchgU32(&pThis->fSignalled, 0, 1))
377 {
378 ASMAtomicDecS32(&pThis->cWaiters);
379 return VINF_SUCCESS;
380 }
381
382 /*
383 * The wait loop.
384 */
385#ifdef RTSEMEVENT_STRICT
386 RTTHREAD hThreadSelf = !(pThis->fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK)
387 ? RTThreadSelfAutoAdopt()
388 : RTThreadSelf();
389#else
390 RTTHREAD hThreadSelf = RTThreadSelf();
391#endif
392 int rc = VINF_SUCCESS;
393 for (;;)
394 {
395#ifdef RTSEMEVENT_STRICT
396 if (pThis->fEverHadSignallers)
397 {
398 rc = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
399 iWaitOp == FUTEX_WAIT ? uTimeout / RT_NS_1MS : RT_MS_1HOUR /*whatever*/,
400 RTTHREADSTATE_EVENT, true);
401 if (RT_FAILURE(rc))
402 break;
403 }
404#endif
405 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT, true);
406 long lrc = sys_futex(&pThis->fSignalled, iWaitOp, 0, &TsTimeout, NULL, uWaitVal3);
407 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT);
408 if (RT_UNLIKELY(pThis->iMagic != RTSEMEVENT_MAGIC))
409 {
410 rc = VERR_SEM_DESTROYED;
411 break;
412 }
413
414 if (RT_LIKELY(lrc == 0 || lrc == -EWOULDBLOCK))
415 {
416 /* successful wakeup or fSignalled > 0 in the meantime */
417 if (ASMAtomicCmpXchgU32(&pThis->fSignalled, 0, 1))
418 break;
419 }
420 else if (lrc == -ETIMEDOUT)
421 {
422#ifdef RT_STRICT
423 uint64_t const uNow = RTTimeNanoTS();
424 AssertMsg(uNow >= nsAbsTimeout || nsAbsTimeout - uNow < RT_NS_1MS,
425 ("%#RX64 - %#RX64 => %#RX64 (%RI64)\n", nsAbsTimeout, uNow, nsAbsTimeout - uNow, nsAbsTimeout - uNow));
426#endif
427 rc = VERR_TIMEOUT;
428 break;
429 }
430 else if (lrc == -EINTR)
431 {
432 if (fFlags & RTSEMWAIT_FLAGS_NORESUME)
433 {
434 rc = VERR_INTERRUPTED;
435 break;
436 }
437 }
438 else
439 {
440 /* this shouldn't happen! */
441 AssertMsgFailed(("rc=%ld errno=%d\n", lrc, errno));
442 rc = RTErrConvertFromErrno(lrc);
443 break;
444 }
445
446 /* adjust the relative timeout */
447 if (iWaitOp == FUTEX_WAIT)
448 {
449 int64_t i64Diff = nsAbsTimeout - RTTimeSystemNanoTS();
450 if (i64Diff < 1000)
451 {
452 rc = VERR_TIMEOUT;
453 break;
454 }
455 TsTimeout.tv_sec = (uint64_t)i64Diff / RT_NS_1SEC;
456 TsTimeout.tv_nsec = (uint64_t)i64Diff % RT_NS_1SEC;
457 }
458 }
459
460 ASMAtomicDecS32(&pThis->cWaiters);
461 return rc;
462}
463
464
465/**
466 * Internal wait worker function.
467 */
468DECLINLINE(int) rtSemEventLinuxWait(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout, PCRTLOCKVALSRCPOS pSrcPos)
469{
470 /*
471 * Validate input.
472 */
473 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
474 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
475 AssertReturn(pThis->iMagic == RTSEMEVENT_MAGIC, VERR_INVALID_HANDLE);
476 AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);
477#ifdef RT_STRICT
478 uint32_t const fSignalled = pThis->fSignalled;
479 Assert(fSignalled == false || fSignalled == true);
480#endif
481
482 /*
483 * Timed or indefinite wait?
484 */
485 if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE)
486 return rtSemEventLinuxWaitIndefinite(pThis, fFlags, pSrcPos);
487 return rtSemEventLinuxWaitTimed(hEventSem, fFlags, uTimeout, pSrcPos);
488}
489
490
491RTDECL(int) RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
492{
493 int rc;
494#ifndef RTSEMEVENT_STRICT
495 if (cMillies == RT_INDEFINITE_WAIT)
496 rc = rtSemEventLinuxWait(hEventSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0, NULL);
497 else
498 rc = rtSemEventLinuxWait(hEventSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS,
499 cMillies, NULL);
500#else
501 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
502 if (cMillies == RT_INDEFINITE_WAIT)
503 rc = rtSemEventLinuxWait(hEventSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0, &SrcPos);
504 else
505 rc = rtSemEventLinuxWait(hEventSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS,
506 cMillies, &SrcPos);
507#endif
508 Assert(rc != VERR_INTERRUPTED);
509 return rc;
510}
511
512
513RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
514{
515 int rc;
516#ifndef RTSEMEVENT_STRICT
517 if (cMillies == RT_INDEFINITE_WAIT)
518 rc = rtSemEventLinuxWait(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0, NULL);
519 else
520 rc = rtSemEventLinuxWait(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS,
521 cMillies, NULL);
522#else
523 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
524 if (cMillies == RT_INDEFINITE_WAIT)
525 rc = rtSemEventLinuxWait(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0, &SrcPos);
526 else
527 rc = rtSemEventLinuxWait(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS,
528 cMillies, &SrcPos);
529#endif
530 Assert(rc != VERR_INTERRUPTED);
531 return rc;
532}
533
534
535RTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout)
536{
537#ifndef RTSEMEVENT_STRICT
538 return rtSemEventLinuxWait(hEventSem, fFlags, uTimeout, NULL);
539#else
540 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
541 return rtSemEventLinuxWait(hEventSem, fFlags, uTimeout, &SrcPos);
542#endif
543}
544
545
546RTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout,
547 RTHCUINTPTR uId, RT_SRC_POS_DECL)
548{
549 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
550 return rtSemEventLinuxWait(hEventSem, fFlags, uTimeout, &SrcPos);
551}
552
553
554RTDECL(uint32_t) RTSemEventGetResolution(void)
555{
556 /** @todo we have 1ns parameter resolution, but need to verify that this is what
557 * the kernel actually will use when setting the timer. Most likely
558 * it's rounded a little, but hopefully not to a multiple of HZ. */
559 return 1;
560}
561
562
563RTDECL(void) RTSemEventSetSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
564{
565#ifdef RTSEMEVENT_STRICT
566 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
567 AssertPtrReturnVoid(pThis);
568 AssertReturnVoid(pThis->iMagic == RTSEMEVENT_MAGIC);
569
570 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
571 RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
572#else
573 RT_NOREF(hEventSem, hThread);
574#endif
575}
576
577
578RTDECL(void) RTSemEventAddSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
579{
580#ifdef RTSEMEVENT_STRICT
581 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
582 AssertPtrReturnVoid(pThis);
583 AssertReturnVoid(pThis->iMagic == RTSEMEVENT_MAGIC);
584
585 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
586 RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
587#else
588 RT_NOREF(hEventSem, hThread);
589#endif
590}
591
592
593RTDECL(void) RTSemEventRemoveSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)
594{
595#ifdef RTSEMEVENT_STRICT
596 struct RTSEMEVENTINTERNAL *pThis = hEventSem;
597 AssertPtrReturnVoid(pThis);
598 AssertReturnVoid(pThis->iMagic == RTSEMEVENT_MAGIC);
599
600 RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
601#else
602 RT_NOREF(hEventSem, hThread);
603#endif
604}
605
606#endif /* glibc < 2.6 || IPRT_WITH_FUTEX_BASED_SEMS */
607
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