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