semevent-linux.cpp revision 660fd430a3a8cfa16505d04c7c577acf89d45a40
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder/* $Id$ */
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder/** @file
e6d40133bc9f858308654afb1262b8b483ec5922Till Mossakowski * IPRT - Event Semaphore, Linux (2.6.x+).
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder */
97018cf5fa25b494adffd7e9b4e87320dae6bf47Christian Maeder
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder/*
b4fbc96e05117839ca409f5f20f97b3ac872d1edTill Mossakowski * Copyright (C) 2006-2007 Sun Microsystems, Inc.
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder *
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder * This file is part of VirtualBox Open Source Edition (OSE), as
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder * available from http://www.virtualbox.org. This file is free software;
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder * you can redistribute it and/or modify it under the terms of the GNU
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder * General Public License (GPL) as published by the Free Software
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder * Foundation, in version 2 as it comes in the "COPYING" file of the
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder *
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder * The contents of this file may alternatively be used under the terms
5a635ded758223aace5fd93489167f03cc336502Christian Maeder * of the Common Development and Distribution License Version 1.0
5a635ded758223aace5fd93489167f03cc336502Christian Maeder * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder * VirtualBox OSE distribution, in which case the provisions of the
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder * CDDL are applicable instead of those of the GPL.
2eb84fc82d3ffa9116bc471fda3742bd9e5a24bbChristian Maeder *
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder * You may elect to license modified versions of this file under the
6ab1767d594a99e063bb698c123823411c05700eChristian Maeder * terms and conditions of either the GPL or the CDDL or both.
6ab1767d594a99e063bb698c123823411c05700eChristian Maeder *
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder * Clara, CA 95054 USA or visit http://www.sun.com if you need
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder * additional information or have any questions.
efcb75d747dcdecc53bc5a584b6b4d98d1ae2755Christian Maeder */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder/*******************************************************************************
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder* Header Files *
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder*******************************************************************************/
efcb75d747dcdecc53bc5a584b6b4d98d1ae2755Christian Maeder#include <iprt/semaphore.h>
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski#include <iprt/assert.h>
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski#include <iprt/alloc.h>
efcb75d747dcdecc53bc5a584b6b4d98d1ae2755Christian Maeder#include <iprt/asm.h>
efcb75d747dcdecc53bc5a584b6b4d98d1ae2755Christian Maeder#include <iprt/err.h>
efcb75d747dcdecc53bc5a584b6b4d98d1ae2755Christian Maeder#include "internal/magics.h"
efcb75d747dcdecc53bc5a584b6b4d98d1ae2755Christian Maeder
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder#include <errno.h>
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski#include <limits.h>
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski#include <pthread.h>
efcb75d747dcdecc53bc5a584b6b4d98d1ae2755Christian Maeder#include <unistd.h>
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder#include <sys/time.h>
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski#include <sys/syscall.h>
efcb75d747dcdecc53bc5a584b6b4d98d1ae2755Christian Maeder#if 0 /* With 2.6.17 futex.h has become C++ unfriendly. */
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski# include <linux/futex.h>
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski#else
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski# define FUTEX_WAIT 0
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski# define FUTEX_WAKE 1
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski#endif
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski/*******************************************************************************
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski* Structures and Typedefs *
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski*******************************************************************************/
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski/**
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski * Linux (single wakup) event semaphore.
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski */
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowskistruct RTSEMEVENTINTERNAL
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski{
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski /** Magic value. */
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski intptr_t volatile iMagic;
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski /** The futex state variable.
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski * <0 means signaled.
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder * 0 means not signaled, no waiters.
efcb75d747dcdecc53bc5a584b6b4d98d1ae2755Christian Maeder * >0 means not signaled, and the value gives the number of waiters.
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder int32_t volatile cWaiters;
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder};
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder/**
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder * Wrapper for the futex syscall.
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder */
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maederstatic long sys_futex(int32_t volatile *uaddr, int op, int val, struct timespec *utime, int32_t *uaddr2, int val3)
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder{
5516c28f6575b3550029d1d82c6a14f8402ac3a2Christian Maeder errno = 0;
5516c28f6575b3550029d1d82c6a14f8402ac3a2Christian Maeder long rc = syscall(__NR_futex, uaddr, op, val, utime, uaddr2, val3);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder if (rc < 0)
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder {
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder Assert(rc == -1);
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder rc = -errno;
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder }
f8c976764f99f18f986cfbb75da7150741d2e883Klaus Luettich return rc;
5a635ded758223aace5fd93489167f03cc336502Christian Maeder}
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill MossakowskiRTDECL(int) RTSemEventCreate(PRTSEMEVENT pEventSem)
efcb75d747dcdecc53bc5a584b6b4d98d1ae2755Christian Maeder{
781d04c5e02635caed8b98f0adcf559f9426a39cTill Mossakowski /*
781d04c5e02635caed8b98f0adcf559f9426a39cTill Mossakowski * Allocate semaphore handle.
5516c28f6575b3550029d1d82c6a14f8402ac3a2Christian Maeder */
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder struct RTSEMEVENTINTERNAL *pThis = (struct RTSEMEVENTINTERNAL *)RTMemAlloc(sizeof(struct RTSEMEVENTINTERNAL));
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder if (pThis)
5a635ded758223aace5fd93489167f03cc336502Christian Maeder {
5a635ded758223aace5fd93489167f03cc336502Christian Maeder pThis->iMagic = RTSEMEVENT_MAGIC;
efcb75d747dcdecc53bc5a584b6b4d98d1ae2755Christian Maeder pThis->cWaiters = 0;
5a635ded758223aace5fd93489167f03cc336502Christian Maeder *pEventSem = pThis;
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski return VINF_SUCCESS;
5a635ded758223aace5fd93489167f03cc336502Christian Maeder }
db7143998eee23e3d781f1f1e97e953bb831df1fTill Mossakowski return VERR_NO_MEMORY;
db7143998eee23e3d781f1f1e97e953bb831df1fTill Mossakowski}
db7143998eee23e3d781f1f1e97e953bb831df1fTill Mossakowski
6ab1767d594a99e063bb698c123823411c05700eChristian Maeder
6ab1767d594a99e063bb698c123823411c05700eChristian MaederRTDECL(int) RTSemEventDestroy(RTSEMEVENT EventSem)
6ab1767d594a99e063bb698c123823411c05700eChristian Maeder{
6ab1767d594a99e063bb698c123823411c05700eChristian Maeder /*
6ab1767d594a99e063bb698c123823411c05700eChristian Maeder * Validate input.
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder */
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder if (EventSem == NIL_RTSEMEVENT) /* don't bitch */
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder return VERR_INVALID_HANDLE;
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder struct RTSEMEVENTINTERNAL *pThis = EventSem;
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski AssertReturn(pThis->iMagic == RTSEMEVENT_MAGIC, VERR_INVALID_HANDLE);
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski /*
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski * Invalidate the semaphore and wake up anyone waiting on it.
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski */
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder ASMAtomicXchgSize(&pThis->iMagic, RTSEMEVENT_MAGIC + 1);
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder if (ASMAtomicXchgS32(&pThis->cWaiters, INT32_MIN / 2) > 0)
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski {
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder sys_futex(&pThis->cWaiters, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder usleep(1000);
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski }
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski /*
5a635ded758223aace5fd93489167f03cc336502Christian Maeder * Free the semaphore memory and be gone.
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder */
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder RTMemFree(pThis);
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder return VINF_SUCCESS;
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder}
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder
1df7e6a9e5273f3eeb770d9f2fbbee40fb1ba51dChristian MaederRTDECL(int) RTSemEventSignal(RTSEMEVENT EventSem)
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder{
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder /*
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder * Validate input.
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder */
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder struct RTSEMEVENTINTERNAL *pThis = EventSem;
277f12a72ee6876b9c48f01ef34d7cde65a423c8Christian Maeder AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMEVENT_MAGIC,
277f12a72ee6876b9c48f01ef34d7cde65a423c8Christian Maeder VERR_INVALID_HANDLE);
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder /*
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder * Try signal it.
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder */
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder for (unsigned i = 0;; i++)
277f12a72ee6876b9c48f01ef34d7cde65a423c8Christian Maeder {
277f12a72ee6876b9c48f01ef34d7cde65a423c8Christian Maeder int32_t iCur = pThis->cWaiters;
277f12a72ee6876b9c48f01ef34d7cde65a423c8Christian Maeder if (iCur == 0)
277f12a72ee6876b9c48f01ef34d7cde65a423c8Christian Maeder {
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder if (ASMAtomicCmpXchgS32(&pThis->cWaiters, -1, 0))
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder break; /* nobody is waiting */
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder }
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder else if (iCur < 0)
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder break; /* already signaled */
5a635ded758223aace5fd93489167f03cc336502Christian Maeder else
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder {
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder /* somebody is waiting, try wake up one of them. */
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder long cWoken = sys_futex(&pThis->cWaiters, FUTEX_WAKE, 1, NULL, NULL, 0);
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder if (RT_LIKELY(cWoken == 1))
781d04c5e02635caed8b98f0adcf559f9426a39cTill Mossakowski {
781d04c5e02635caed8b98f0adcf559f9426a39cTill Mossakowski ASMAtomicDecS32(&pThis->cWaiters);
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder break;
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder }
94fa5b6f4ce199b15c9e3c530d96a8c403e20193Christian Maeder AssertMsg(cWoken == 0, ("%ld\n", cWoken));
94fa5b6f4ce199b15c9e3c530d96a8c403e20193Christian Maeder
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski /*
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder * This path is taken in two situations:
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder * 1) A waiting thread is returning from the sys_futex call with a
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder * non-zero return value.
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder * 2) There are two threads signaling the event at the
5a635ded758223aace5fd93489167f03cc336502Christian Maeder * same time and only one thread waiting.
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder *
eca18e4fda019d7e57e1fe1cc16ed21592c9e11bChristian Maeder * At this point we know that nobody is activly waiting on the event but
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder * at the same time, we are racing someone updating the state. The current
5a635ded758223aace5fd93489167f03cc336502Christian Maeder * strategy is to spin till the thread racing us is done, this is kind of
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder * brain dead and need fixing of course.
eca18e4fda019d7e57e1fe1cc16ed21592c9e11bChristian Maeder */
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder if (RT_UNLIKELY(i > 32))
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder {
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder if ((i % 128) == 127)
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder usleep(1000);
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder else if (!(i % 4))
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder pthread_yield();
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder else
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder AssertReleaseMsg(i < 4096, ("iCur=%#x pThis=%p\n", iCur, pThis));
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder }
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder }
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder }
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder return VINF_SUCCESS;
4561227a776bdf0ab679b19fb92f1eaaed8786f7Christian Maeder}
277f12a72ee6876b9c48f01ef34d7cde65a423c8Christian Maeder
277f12a72ee6876b9c48f01ef34d7cde65a423c8Christian Maeder
277f12a72ee6876b9c48f01ef34d7cde65a423c8Christian Maederstatic int rtSemEventWait(RTSEMEVENT EventSem, unsigned cMillies, bool fAutoResume)
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder{
5a635ded758223aace5fd93489167f03cc336502Christian Maeder /*
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder * Validate input.
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder */
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder struct RTSEMEVENTINTERNAL *pThis = EventSem;
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMEVENT_MAGIC,
5a635ded758223aace5fd93489167f03cc336502Christian Maeder VERR_INVALID_HANDLE);
5a635ded758223aace5fd93489167f03cc336502Christian Maeder
5a635ded758223aace5fd93489167f03cc336502Christian Maeder /*
5a635ded758223aace5fd93489167f03cc336502Christian Maeder * Quickly check whether it's signaled.
5a635ded758223aace5fd93489167f03cc336502Christian Maeder */
5a635ded758223aace5fd93489167f03cc336502Christian Maeder if (ASMAtomicCmpXchgS32(&pThis->cWaiters, 0, -1))
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder return VINF_SUCCESS;
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder /*
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder * Convert timeout value.
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder */
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder struct timespec ts;
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder struct timespec *pTimeout = NULL;
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder if (cMillies != RT_INDEFINITE_WAIT)
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder {
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder ts.tv_sec = cMillies / 1000;
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder ts.tv_nsec = (cMillies % 1000) * 1000000;
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder pTimeout = &ts;
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder }
5a635ded758223aace5fd93489167f03cc336502Christian Maeder
5a635ded758223aace5fd93489167f03cc336502Christian Maeder /*
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder * The wait loop.
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder */
dd776ca56af505d39e16e9eecf69948beddfb279Christian Maeder for (unsigned i = 0;; i++)
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder {
dd776ca56af505d39e16e9eecf69948beddfb279Christian Maeder /*
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder * Announce that we're among the waiters.
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder int32_t iNew = ASMAtomicIncS32(&pThis->cWaiters);
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder if (iNew == 0)
27273a2967ca2f12b5e6ff0ec5e3f66e2ea8fcb2Christian Maeder return VINF_SUCCESS;
25a0b76bc87e80c0f697951d9817862755a71d33Christian Maeder if (RT_LIKELY(iNew > 0))
27273a2967ca2f12b5e6ff0ec5e3f66e2ea8fcb2Christian Maeder {
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder /*
27273a2967ca2f12b5e6ff0ec5e3f66e2ea8fcb2Christian Maeder * Go to sleep.
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder */
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder long rc = sys_futex(&pThis->cWaiters, FUTEX_WAIT, iNew, pTimeout, NULL, 0);
27273a2967ca2f12b5e6ff0ec5e3f66e2ea8fcb2Christian Maeder if (RT_UNLIKELY(pThis->iMagic != RTSEMEVENT_MAGIC))
27273a2967ca2f12b5e6ff0ec5e3f66e2ea8fcb2Christian Maeder return VERR_SEM_DESTROYED;
5a635ded758223aace5fd93489167f03cc336502Christian Maeder
5a635ded758223aace5fd93489167f03cc336502Christian Maeder /* Did somebody wake us up from RTSemEventSignal()? */
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder if (rc == 0)
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder return VINF_SUCCESS;
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski /* No, then the kernel woke us up or we failed going to sleep. Adjust the accounting. */
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder iNew = ASMAtomicDecS32(&pThis->cWaiters);
6e6ba3ab90205840b9c0ea408befaed7d1d7b80bChristian Maeder Assert(iNew >= 0);
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski
6e6ba3ab90205840b9c0ea408befaed7d1d7b80bChristian Maeder /*
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski * Act on the wakup code.
6e6ba3ab90205840b9c0ea408befaed7d1d7b80bChristian Maeder */
6e6ba3ab90205840b9c0ea408befaed7d1d7b80bChristian Maeder if (rc == -ETIMEDOUT)
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder {
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder Assert(pTimeout);
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder return VERR_TIMEOUT;
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski }
b645cf3dc1e449038ed291bbd11fcc6e02b2fc7fChristian Maeder if (rc == -EWOULDBLOCK)
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* retry with new value. */;
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder else if (rc == -EINTR)
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder {
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder if (!fAutoResume)
25d484b7e8a319494046201857a80ed4dd2cea86Christian Maeder return VERR_INTERRUPTED;
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder }
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder else
25d484b7e8a319494046201857a80ed4dd2cea86Christian Maeder {
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder /* this shouldn't happen! */
25d484b7e8a319494046201857a80ed4dd2cea86Christian Maeder AssertMsgFailed(("rc=%ld errno=%d\n", rc, errno));
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder return RTErrConvertFromErrno(rc);
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski }
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder }
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder else
0cb5f9c8582ad87ceef1c16b5d92347ae0878019Christian Maeder {
25d484b7e8a319494046201857a80ed4dd2cea86Christian Maeder /* this can't happen. */
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder if (RT_UNLIKELY(pThis->iMagic != RTSEMEVENT_MAGIC))
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder return VERR_SEM_DESTROYED;
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder AssertReleaseMsgFailed(("iNew=%d\n", iNew));
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder }
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder }
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder}
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder
9929f81562adecc8aafaefb14a0159afcf4a3351Christian MaederRTDECL(int) RTSemEventWait(RTSEMEVENT EventSem, unsigned cMillies)
5a635ded758223aace5fd93489167f03cc336502Christian Maeder{
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder int rc = rtSemEventWait(EventSem, cMillies, true);
aefb25a4f42b9078ea2b04fe2b599da4ca20cd34Christian Maeder Assert(rc != VERR_INTERRUPTED);
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder Assert(rc != VERR_TIMEOUT || cMillies != RT_INDEFINITE_WAIT);
42c01284bba8d7c8d995c8dfb96ace57d28ed1bcTill Mossakowski return rc;
9929f81562adecc8aafaefb14a0159afcf4a3351Christian Maeder}
1f726c6d4aea88acb19f73a1471257dbde301156Till Mossakowski
1f726c6d4aea88acb19f73a1471257dbde301156Till Mossakowski
1f726c6d4aea88acb19f73a1471257dbde301156Till MossakowskiRTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT EventSem, unsigned cMillies)
1f726c6d4aea88acb19f73a1471257dbde301156Till Mossakowski{
add1aac0ed564b88495edb5491efd8c511607ea9Christian Maeder return rtSemEventWait(EventSem, cMillies, false);
0ed43197461f040473d13c45f85c384c3e83144dChristian Maeder}
0ed43197461f040473d13c45f85c384c3e83144dChristian Maeder
0ed43197461f040473d13c45f85c384c3e83144dChristian Maeder