poll-posix.cpp revision efdb1947ebed81cc00f8daf2c1040b2b2f5196db
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/* $Id$ */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** @file
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * IPRT - Polling I/O Handles, POSIX Implementation.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Copyright (C) 2010 Sun Microsystems, Inc.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * available from http://www.virtualbox.org. This file is free software;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * General Public License (GPL) as published by the Free Software
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * The contents of this file may alternatively be used under the terms
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * of the Common Development and Distribution License Version 1.0
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * VirtualBox OSE distribution, in which case the provisions of the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * CDDL are applicable instead of those of the GPL.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * You may elect to license modified versions of this file under the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * terms and conditions of either the GPL or the CDDL or both.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * additional information or have any questions.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Header Files *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync*******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <iprt/poll.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include "internal/iprt.h"
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <iprt/asm.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <iprt/assert.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <iprt/err.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <iprt/mem.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <iprt/pipe.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <iprt/string.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <iprt/thread.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <iprt/time.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include "internal/magics.h"
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <limits.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <errno.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#include <sys/poll.h>
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Structures and Typedefs *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync*******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Handle entry in a poll set.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef struct RTPOLLSETHNDENT
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The handle type. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTHANDLETYPE enmType;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The handle ID. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t id;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The handle union. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTHANDLEUNION u;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync} RTPOLLSETHNDENT;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to a handle entry. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef RTPOLLSETHNDENT *PRTPOLLSETHNDENT;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Poll set data, POSIX.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef struct RTPOLLSETINTERNAL
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The magic value (RTPOLLSET_MAGIC). */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t u32Magic;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Set when someone is polling or making changes. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync bool volatile fBusy;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The number of valid handles in the set. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t cHandles;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The number of allocated handles. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t cHandlesAllocated;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Pointer to an array of pollfd structures. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync struct pollfd *paPollFds;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Pointer to an array of handles and IDs. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PRTPOLLSETHNDENT paHandles;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync} RTPOLLSETINTERNAL;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/**
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Common worker for RTPoll and RTPollNoResume
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic int rtPollNoResumeWorker(RTPOLLSETINTERNAL *pThis, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (RT_UNLIKELY(pThis->cHandles == 0 && cMillies == RT_INDEFINITE_WAIT))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return VERR_DEADLOCK;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* clear the revents. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t i = pThis->cHandles;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync while (i-- > 0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paPollFds[i].revents = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync int rc = poll(&pThis->paPollFds[0], pThis->cHandles,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync cMillies == RT_INDEFINITE_WAIT || cMillies >= INT_MAX
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ? -1
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync : (int)cMillies);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (rc == 0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return VERR_TIMEOUT;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (rc < 0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return RTErrConvertFromErrno(errno);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync for (i = 0; i < pThis->cHandles; i++)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pThis->paPollFds[i].revents)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pfEvents)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *pfEvents = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pThis->paPollFds[i].revents & (POLLIN
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef POLLRDNORM
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync | POLLRDNORM /* just in case */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef POLLRDBAND
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync | POLLRDBAND /* ditto */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef POLLPRI
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync | POLLPRI /* ditto */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef POLLMSG
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync | POLLMSG /* ditto */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef POLLWRITE
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync | POLLWRITE /* ditto */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef POLLEXTEND
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync | POLLEXTEND /* ditto */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync )
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync )
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *pfEvents |= RTPOLL_EVT_READ;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pThis->paPollFds[i].revents & (POLLOUT
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef POLLWRNORM
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync | POLLWRNORM /* just in case */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef POLLWRBAND
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync | POLLWRBAND /* ditto */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync )
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync )
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *pfEvents |= RTPOLL_EVT_WRITE;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pThis->paPollFds[i].revents & (POLLERR | POLLHUP | POLLNVAL
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#ifdef POLLRDHUP
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync | POLLRDHUP
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync )
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync )
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *pfEvents |= RTPOLL_EVT_ERROR;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pid)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *pid = pThis->paHandles[i].id;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return VINF_SUCCESS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertFailed();
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTThreadYield();
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return VERR_INTERRUPTED;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncRTDECL(int) RTPoll(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTPOLLSETINTERNAL *pThis = hPollSet;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertPtrNull(pfEvents);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertPtrNull(pid);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Set the busy flag and do the job.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_WRONG_ORDER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync int rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (cMillies == RT_INDEFINITE_WAIT || cMillies == 0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync do rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync while (rc == VERR_INTERRUPTED);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint64_t MsStart = RTTimeMilliTS();
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync while (RT_UNLIKELY(rc == VERR_INTERRUPTED))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (RTTimeMilliTS() - MsStart >= cMillies)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = VERR_TIMEOUT;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ASMAtomicWriteBool(&pThis->fBusy, false);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncRTDECL(int) RTPollNoResume(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTPOLLSETINTERNAL *pThis = hPollSet;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertPtrNull(pfEvents);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertPtrNull(pid);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Set the busy flag and do the job.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_WRONG_ORDER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync int rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ASMAtomicWriteBool(&pThis->fBusy, false);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return rc;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncRTDECL(int) RTPollSetCreate(PRTPOLLSET phPollSet)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertPtrReturn(phPollSet, VERR_INVALID_POINTER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTPOLLSETINTERNAL *pThis = (RTPOLLSETINTERNAL *)RTMemAlloc(sizeof(RTPOLLSETINTERNAL));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (!pThis)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return VERR_NO_MEMORY;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->u32Magic = RTPOLLSET_MAGIC;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->fBusy = false;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->cHandles = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->cHandlesAllocated = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paPollFds = NULL;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paHandles = NULL;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync *phPollSet = pThis;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return VINF_SUCCESS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncRTDECL(int) RTPollSetDestroy(RTPOLLSET hPollSet)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTPOLLSETINTERNAL *pThis = hPollSet;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pThis == NIL_RTPOLLSET)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return VINF_SUCCESS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_WRONG_ORDER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ASMAtomicWriteU32(&pThis->u32Magic, ~RTPOLLSET_MAGIC);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTMemFree(pThis->paPollFds);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paPollFds = NULL;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTMemFree(pThis->paHandles);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paHandles = NULL;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTMemFree(pThis);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return VINF_SUCCESS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync}
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncRTDECL(int) RTPollSetAdd(RTPOLLSET hPollSet, PCRTHANDLE pHandle, uint32_t fEvents, uint32_t id)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync{
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Validate the input (tedious).
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTPOLLSETINTERNAL *pThis = hPollSet;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(!(fEvents & ~RTPOLL_EVT_VALID_MASK), VERR_INVALID_PARAMETER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(fEvents, VERR_INVALID_PARAMETER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(id != UINT32_MAX, VERR_INVALID_PARAMETER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (!pHandle)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return VINF_SUCCESS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertPtrReturn(pHandle, VERR_INVALID_POINTER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(pHandle->enmType > RTHANDLETYPE_INVALID && pHandle->enmType < RTHANDLETYPE_END, VERR_INVALID_PARAMETER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /*
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Set the busy flag and do the job.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_WRONG_ORDER);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync int rc = VINF_SUCCESS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync int fd = -1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync switch (pHandle->enmType)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case RTHANDLETYPE_PIPE:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pHandle->u.hPipe != NIL_RTPIPE)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync fd = RTPipeToNative(pHandle->u.hPipe);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case RTHANDLETYPE_SOCKET:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pHandle->u.hSocket != NIL_RTSOCKET)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync fd = (int)pHandle->u.hSocket; //fd = RTTcpToNative(pHandle->u.hSocket);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case RTHANDLETYPE_FILE:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertMsgFailed(("Files are always ready for reading/writing and thus not pollable. Use native APIs for special devices.\n"));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = VERR_POLL_HANDLE_NOT_POLLABLE;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case RTHANDLETYPE_THREAD:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertMsgFailed(("Thread handles are currently not pollable\n"));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = VERR_POLL_HANDLE_NOT_POLLABLE;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync default:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertMsgFailed(("\n"));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = VERR_POLL_HANDLE_NOT_POLLABLE;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (fd != -1)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t const i = pThis->cHandles;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Check that the handle ID doesn't exist already. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t j = i;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync while (j-- > 0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pThis->paHandles[j].id == id)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = VERR_POLL_HANDLE_ID_EXISTS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync break;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (RT_SUCCESS(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Grow the tables if necessary. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (i + 1 > pThis->cHandlesAllocated)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t const c = pThis->cHandlesAllocated + 32;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync void *pvNew;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pvNew = RTMemRealloc(pThis->paHandles, c * sizeof(pThis->paHandles[0]));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pvNew)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paHandles = (PRTPOLLSETHNDENT)pvNew;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pvNew = RTMemRealloc(pThis->paPollFds, c * sizeof(pThis->paPollFds[0]));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pvNew)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paPollFds = (struct pollfd *)pvNew;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = VERR_NO_MEMORY;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = VERR_NO_MEMORY;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (RT_SUCCESS(rc))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Add it to the poll file descriptor array and call poll to
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync validate the event flags. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paPollFds[i].fd = fd;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paPollFds[i].revents = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paPollFds[i].events = 0;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (fEvents & RTPOLL_EVT_READ)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paPollFds[i].events |= POLLIN;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (fEvents & RTPOLL_EVT_WRITE)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paPollFds[i].events |= POLLOUT;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (fEvents & RTPOLL_EVT_ERROR)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paPollFds[i].events |= POLLERR;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (poll(&pThis->paPollFds[i], 1, 0) >= 0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Add the handle info and close the transaction. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paHandles[i].enmType = pHandle->enmType;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paHandles[i].u = pHandle->u;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paHandles[i].id = id;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->cHandles = i + 1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = VINF_SUCCESS;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = RTErrConvertFromErrno(errno);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pThis->paPollFds[i].fd = -1;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync }
}
}
ASMAtomicWriteBool(&pThis->fBusy, false);
return rc;
}
RTDECL(int) RTPollSetRemove(RTPOLLSET hPollSet, uint32_t id)
{
/*
* Validate the input.
*/
RTPOLLSETINTERNAL *pThis = hPollSet;
AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
AssertReturn(id != UINT32_MAX, VERR_INVALID_PARAMETER);
/*
* Set the busy flag and do the job.
*/
AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_WRONG_ORDER);
int rc = VERR_POLL_HANDLE_ID_NOT_FOUND;
uint32_t i = pThis->cHandles;
while (i-- > 0)
if (pThis->paHandles[i].id == id)
{
pThis->cHandles--;
size_t const cToMove = pThis->cHandles - i;
if (cToMove)
{
memmove(&pThis->paHandles[i], &pThis->paHandles[i + 1], cToMove * sizeof(pThis->paHandles[i]));
memmove(&pThis->paPollFds[i], &pThis->paPollFds[i + 1], cToMove * sizeof(pThis->paPollFds[i]));
}
rc = VINF_SUCCESS;
break;
}
ASMAtomicWriteBool(&pThis->fBusy, false);
return rc;
}
RTDECL(int) RTPollSetQueryHandle(RTPOLLSET hPollSet, uint32_t id, PRTHANDLE pHandle)
{
/*
* Validate the input.
*/
RTPOLLSETINTERNAL *pThis = hPollSet;
AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
AssertReturn(id != UINT32_MAX, VERR_INVALID_PARAMETER);
AssertPtrNullReturn(pHandle, VERR_INVALID_POINTER);
/*
* Set the busy flag and do the job.
*/
AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_WRONG_ORDER);
int rc = VERR_POLL_HANDLE_ID_NOT_FOUND;
uint32_t i = pThis->cHandles;
while (i-- > 0)
if (pThis->paHandles[i].id == id)
{
if (pHandle)
{
pHandle->enmType = pThis->paHandles[i].enmType;
pHandle->u = pThis->paHandles[i].u;
}
rc = VINF_SUCCESS;
break;
}
ASMAtomicWriteBool(&pThis->fBusy, false);
return rc;
}
RTDECL(uint32_t) RTPollGetCount(RTPOLLSET hPollSet)
{
/*
* Validate the input.
*/
RTPOLLSETINTERNAL *pThis = hPollSet;
AssertPtrReturn(pThis, UINT32_MAX);
AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, UINT32_MAX);
/*
* Set the busy flag and do the job.
*/
AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), UINT32_MAX);
uint32_t cHandles = pThis->cHandles;
ASMAtomicWriteBool(&pThis->fBusy, false);
return cHandles;
}