semeventmulti-linux.cpp revision ab93606043a9881487aa83be04191d2f4ea24071
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync/* $Id$ */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync/** @file
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * IPRT - Multiple Release Event Semaphore, Linux (2.6.x+).
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync/*
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync *
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * available from http://www.virtualbox.org. This file is free software;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * you can redistribute it and/or modify it under the terms of the GNU
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * General Public License (GPL) as published by the Free Software
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync *
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * The contents of this file may alternatively be used under the terms
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * of the Common Development and Distribution License Version 1.0
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * VirtualBox OSE distribution, in which case the provisions of the
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * CDDL are applicable instead of those of the GPL.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync *
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * You may elect to license modified versions of this file under the
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * terms and conditions of either the GPL or the CDDL or both.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync *
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * additional information or have any questions.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include <features.h>
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#if __GLIBC_PREREQ(2,6) && !defined(IPRT_WITH_FUTEX_BASED_SEMS)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync/*
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * glibc 2.6 fixed a serious bug in the mutex implementation. We wrote this
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * linux specific event semaphores code in order to work around the bug. As it
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * turns out, this code seems to have an unresolved issue (#2599), so we'll
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * fall back on the pthread based implementation if glibc is known to contain
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * the bug fix.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync *
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * The external refernce to epoll_pwait is a hack which prevents that we link
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * against glibc < 2.6.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include "../posix/semeventmulti-posix.cpp"
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncasm volatile (".global epoll_pwait");
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#else /* glibc < 2.6 */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync/*******************************************************************************
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync* Header Files *
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync*******************************************************************************/
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include <iprt/semaphore.h>
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include "internal/iprt.h"
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include <iprt/assert.h>
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include <iprt/asm.h>
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include <iprt/err.h>
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include <iprt/lockvalidator.h>
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include <iprt/mem.h>
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include <iprt/time.h>
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include "internal/magics.h"
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include "internal/strict.h"
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include <errno.h>
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include <limits.h>
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include <pthread.h>
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include <unistd.h>
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include <sys/time.h>
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#include <sys/syscall.h>
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#if 0 /* With 2.6.17 futex.h has become C++ unfriendly. */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync# include <linux/futex.h>
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#else
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync# define FUTEX_WAIT 0
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync# define FUTEX_WAKE 1
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#endif
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync/*******************************************************************************
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync* Structures and Typedefs *
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync*******************************************************************************/
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync/**
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * Linux multiple wakup event semaphore.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncstruct RTSEMEVENTMULTIINTERNAL
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync{
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync /** Magic value. */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync uint32_t volatile u32Magic;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync /** The futex state variable.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * -1 means signaled.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * 0 means not signaled, no waiters.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * 1 means not signaled and that someone is waiting.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync int32_t volatile iState;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#ifdef RTSEMEVENTMULTI_STRICT
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync /** Signallers. */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync RTLOCKVALRECSHRD Signallers;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync /** Indicates that lock validation should be performed. */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync bool volatile fEverHadSignallers;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#endif
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync};
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync/**
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * Wrapper for the futex syscall.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncstatic long sys_futex(int32_t volatile *uaddr, int op, int val, struct timespec *utime, int32_t *uaddr2, int val3)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync{
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync errno = 0;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync long rc = syscall(__NR_futex, uaddr, op, val, utime, uaddr2, val3);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if (rc < 0)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync {
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Assert(rc == -1);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync rc = -errno;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync }
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return rc;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncRTDECL(int) RTSemEventMultiCreate(PRTSEMEVENTMULTI phEventMultiSem)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync{
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return RTSemEventMultiCreateEx(phEventMultiSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, NULL);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncRTDECL(int) RTSemEventMultiCreateEx(PRTSEMEVENTMULTI phEventMultiSem, uint32_t fFlags, RTLOCKVALCLASS hClass,
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync const char *pszNameFmt, ...)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync{
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync AssertReturn(!(fFlags & ~RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync /*
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * Allocate semaphore handle.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync struct RTSEMEVENTMULTIINTERNAL *pThis = (struct RTSEMEVENTMULTIINTERNAL *)RTMemAlloc(sizeof(struct RTSEMEVENTMULTIINTERNAL));
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync if (pThis)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync {
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync pThis->iState = 0;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#ifdef RTSEMEVENTMULTI_STRICT
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync va_list va;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync va_start(va, pszNameFmt);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis,
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync true /*fSignaller*/, !(fFlags & RTSEMEVENTMULTI_FLAGS_NO_LOCK_VAL),
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync pszNameFmt, va);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync va_end(va);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync pThis->fEverHadSignallers = false;
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync#endif
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync *phEventMultiSem = pThis;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return VINF_SUCCESS;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync }
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return VERR_NO_MEMORY;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncRTDECL(int) RTSemEventMultiDestroy(RTSEMEVENTMULTI hEventMultiSem)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync{
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync /*
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * Validate input.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if (pThis == NIL_RTSEMEVENTMULTI)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return VINF_SUCCESS;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync /*
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync * Invalidate the semaphore and wake up anyone waiting on it.
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync */
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync ASMAtomicWriteSize(&pThis->u32Magic, RTSEMEVENTMULTI_MAGIC + 1);
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync if (ASMAtomicXchgS32(&pThis->iState, -1) == 1)
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync {
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync sys_futex(&pThis->iState, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync usleep(1000);
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync }
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync /*
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync * Free the semaphore memory and be gone.
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync */
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync#ifdef RTSEMEVENTMULTI_STRICT
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync RTLockValidatorRecSharedDelete(&pThis->Signallers);
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync#endif
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync RTMemFree(pThis);
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync return VINF_SUCCESS;
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync}
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsyncRTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem)
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync{
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync /*
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync * Validate input.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync VERR_INVALID_HANDLE);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#ifdef RTSEMEVENTMULTI_STRICT
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if (pThis->fEverHadSignallers)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync {
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if (RT_FAILURE(rc9))
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return rc9;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync }
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#endif
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync /*
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * Signal it.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync int32_t iOld = ASMAtomicXchgS32(&pThis->iState, -1);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if (iOld > 0)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync {
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync /* wake up sleeping threads. */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync long cWoken = sys_futex(&pThis->iState, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync AssertMsg(cWoken >= 0, ("%ld\n", cWoken)); NOREF(cWoken);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync }
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Assert(iOld == 0 || iOld == -1 || iOld == 1);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return VINF_SUCCESS;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncRTDECL(int) RTSemEventMultiReset(RTSEMEVENTMULTI hEventMultiSem)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync{
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync /*
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * Validate input.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync VERR_INVALID_HANDLE);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#ifdef RT_STRICT
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync int32_t i = pThis->iState;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Assert(i == 0 || i == -1 || i == 1);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#endif
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync /*
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * Reset it.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync ASMAtomicCmpXchgS32(&pThis->iState, 0, -1);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return VINF_SUCCESS;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncstatic int rtSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, unsigned cMillies, bool fAutoResume)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync{
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync PCRTLOCKVALSRCPOS pSrcPos = NULL;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync /*
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * Validate input.
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync VERR_INVALID_HANDLE);
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync /*
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync * Quickly check whether it's signaled.
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync */
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync int32_t iCur = ASMAtomicUoReadS32(&pThis->iState);
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync Assert(iCur == 0 || iCur == -1 || iCur == 1);
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync if (iCur == -1)
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync return VINF_SUCCESS;
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync /*
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync * Convert the timeout value.
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync struct timespec ts;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync struct timespec *pTimeout = NULL;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync uint64_t u64End = 0; /* shut up gcc */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if (cMillies != RT_INDEFINITE_WAIT)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync {
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync /* If the timeout is zero, then we're done. */
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if (!cMillies)
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync return VERR_TIMEOUT;
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync ts.tv_sec = cMillies / 1000;
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync ts.tv_nsec = (cMillies % 1000) * UINT32_C(1000000);
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync u64End = RTTimeSystemNanoTS() + cMillies * UINT64_C(1000000);
270236340676d2385b27ea992e07fcb643bb78b6vboxsync pTimeout = &ts;
270236340676d2385b27ea992e07fcb643bb78b6vboxsync }
270236340676d2385b27ea992e07fcb643bb78b6vboxsync
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync /*
270236340676d2385b27ea992e07fcb643bb78b6vboxsync * The wait loop.
270236340676d2385b27ea992e07fcb643bb78b6vboxsync */
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync#ifdef RTSEMEVENTMULTI_STRICT
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#else
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync RTTHREAD hThreadSelf = RTThreadSelf();
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#endif
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync for (unsigned i = 0;; i++)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync {
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync /*
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * Start waiting. We only account for there being or having been
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync * threads waiting on the semaphore to keep things simple.
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync iCur = ASMAtomicUoReadS32(&pThis->iState);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync Assert(iCur == 0 || iCur == -1 || iCur == 1);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if ( iCur == 1
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync || ASMAtomicCmpXchgS32(&pThis->iState, 1, 0))
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync {
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync /* adjust the relative timeout */
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if (pTimeout)
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync {
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync int64_t i64Diff = u64End - RTTimeSystemNanoTS();
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync if (i64Diff < 1000)
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync return VERR_TIMEOUT;
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync ts.tv_sec = (uint64_t)i64Diff / UINT32_C(1000000000);
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync ts.tv_nsec = (uint64_t)i64Diff % UINT32_C(1000000000);
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync }
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync#ifdef RTSEMEVENTMULTI_STRICT
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if (pThis->fEverHadSignallers)
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync {
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync int rc9 = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
51ef69064b4ea4d571ed129ab883b0c08967c901vboxsync cMillies, RTTHREADSTATE_EVENT_MULTI, true);
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync if (RT_FAILURE(rc9))
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync return rc9;
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync }
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync#endif
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true);
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync long rc = sys_futex(&pThis->iState, FUTEX_WAIT, 1, pTimeout, NULL, 0);
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI);
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync return VERR_SEM_DESTROYED;
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if (rc == 0)
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync return VINF_SUCCESS;
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync /*
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync * Act on the wakup code.
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync */
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if (rc == -ETIMEDOUT)
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync {
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync/** @todo something is broken here. shows up every now and again in the ata
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync * code. Should try to run the timeout against RTTimeMilliTS to
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync * check that it's doing the right thing... */
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync Assert(pTimeout);
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync return VERR_TIMEOUT;
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync }
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if (rc == -EWOULDBLOCK)
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync /* retry, the value changed. */;
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync else if (rc == -EINTR)
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync {
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync if (!fAutoResume)
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync return VERR_INTERRUPTED;
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync }
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync else
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync {
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync /* this shouldn't happen! */
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync AssertMsgFailed(("rc=%ld errno=%d\n", rc, errno));
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync return RTErrConvertFromErrno(rc);
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync }
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync }
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync else if (iCur == -1)
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync return VINF_SUCCESS;
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync }
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync}
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsyncRTDECL(int) RTSemEventMultiWait(RTSEMEVENTMULTI hEventMultiSem, unsigned cMillies)
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync{
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync int rc = rtSemEventMultiWait(hEventMultiSem, cMillies, true);
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync Assert(rc != VERR_INTERRUPTED);
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync return rc;
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync}
0ab80a5f847b8c908ee2d9db5cc37da8e8dd5697vboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsyncRTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI hEventMultiSem, unsigned cMillies)
270236340676d2385b27ea992e07fcb643bb78b6vboxsync{
270236340676d2385b27ea992e07fcb643bb78b6vboxsync return rtSemEventMultiWait(hEventMultiSem, cMillies, false);
270236340676d2385b27ea992e07fcb643bb78b6vboxsync}
270236340676d2385b27ea992e07fcb643bb78b6vboxsync
270236340676d2385b27ea992e07fcb643bb78b6vboxsync
270236340676d2385b27ea992e07fcb643bb78b6vboxsyncRTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
270236340676d2385b27ea992e07fcb643bb78b6vboxsync{
270236340676d2385b27ea992e07fcb643bb78b6vboxsync#ifdef RTSEMEVENTMULTI_STRICT
270236340676d2385b27ea992e07fcb643bb78b6vboxsync struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
270236340676d2385b27ea992e07fcb643bb78b6vboxsync AssertPtrReturnVoid(pThis);
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
270236340676d2385b27ea992e07fcb643bb78b6vboxsync
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
6cd3c708987d8c77397659c5a80ef0eea7ef1fd1vboxsync#endif
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync}
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
917f4ee9f101c9786cf09ea0fe7923a7f6dfe40cvboxsync
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsyncRTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync{
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync#ifdef RTSEMEVENTMULTI_STRICT
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync AssertPtrReturnVoid(pThis);
c6383709c15c809f8cfb09b5cfe670760f06e2b9vboxsync AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
ac91d9d0626a52f79cf554c81b1fdf5f262092bbvboxsync
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync#endif
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync}
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsync
f372af8e6ee2a011213b11cc69f4a29530ff7ce5vboxsyncRTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync{
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync#ifdef RTSEMEVENTMULTI_STRICT
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync AssertPtrReturnVoid(pThis);
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync#endif
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync}
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync#endif /* glibc < 2.6 || IPRT_WITH_FUTEX_BASED_SEMS */
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync
e2ba4c7fd718dba1d5b73cd9e40486df3ce06e77vboxsync