req.cpp revision 52f16f53a955f5b24bc2132c418a5fffb700f089
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* $Id$ */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** @file
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * IPRT - Request packets
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*
cce0c6096dee0c5353bb74431dc47b05f87a1c6dvboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * available from http://www.virtualbox.org. This file is free software;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The contents of this file may alternatively be used under the terms
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * of the Common Development and Distribution License Version 1.0
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * VirtualBox OSE distribution, in which case the provisions of the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * CDDL are applicable instead of those of the GPL.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * You may elect to license modified versions of this file under the
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync * terms and conditions of either the GPL or the CDDL or both.
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync *
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync * additional information or have any questions.
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync */
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*******************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync* Header Files *
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync*******************************************************************************/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/req.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "internal/iprt.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/assert.h>
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync#include <iprt/asm.h>
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync#include <iprt/string.h>
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync#include <iprt/time.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/semaphore.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/thread.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/log.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/mem.h>
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*******************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync* Internal Functions *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync*******************************************************************************/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int rtReqProcessOne(PRTREQ pReq);
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync
11923fc977be1686f5428c3e790c04d0701a074cvboxsync
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Create a request packet queueu
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns iprt status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param ppQueue Where to store the request queue pointer.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsyncRTDECL(int) RTReqCreateQueue(PRTREQQUEUE *ppQueue)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTREQQUEUE pQueue = (PRTREQQUEUE)RTMemAllocZ(sizeof(RTREQQUEUE));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!pQueue)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync return VERR_NO_MEMORY;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync int rc = RTSemEventCreate(&pQueue->EventSem);
ffa39e5fea478b00909918ab8d45fb3ffb02bc14vboxsync if (RT_SUCCESS(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync *ppQueue = pQueue;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTMemFree(pQueue);
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync return rc;
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync}
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsyncRT_EXPORT_SYMBOL(RTReqCreateQueue);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync/**
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * Destroy a request packet queueu
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync *
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * @returns iprt status code.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * @param pQueue The request queue.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync */
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsyncRTDECL(int) RTReqDestroyQueue(PRTREQQUEUE pQueue)
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync{
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync /*
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * Check input.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync */
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync if (!pQueue)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertPtr(pQueue);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTSemEventDestroy(pQueue->EventSem);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pQueue->EventSem = NIL_RTSEMEVENT;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync RTMemFree(pQueue);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync return VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsyncRT_EXPORT_SYMBOL(RTReqDestroyQueue);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Process one or more request packets
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * @returns iprt status code.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * @returns VERR_TIMEOUT if cMillies was reached without the packet being added.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
38b70b2dcb1783801f7580cba797a0c8af4b5326vboxsync * @param pQueue The request queue.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * @param cMillies Number of milliseconds to wait for a pending request.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Use RT_INDEFINITE_WAIT to only wait till one is added.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync */
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsyncRTDECL(int) RTReqProcess(PRTREQQUEUE pQueue, RTMSINTERVAL cMillies)
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync{
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync LogFlow(("RTReqProcess %x\n", pQueue));
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync /*
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * Check input.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!pQueue)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync AssertFailed();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VERR_INVALID_PARAMETER;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Process loop.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * We do not repeat the outer loop if we've got an informationtional status code
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * since that code needs processing by our caller.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = VINF_SUCCESS;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync while (rc <= VINF_SUCCESS)
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync {
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync /*
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * Get pending requests.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync */
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync PRTREQ pReqs = (PRTREQ)ASMAtomicXchgPtr((void * volatile *)&pQueue->pReqs, NULL);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync if (!pReqs)
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync {
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync ASMAtomicWriteBool(&pQueue->fBusy, false); /* this aint 100% perfect, but it's good enough for now... */
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync /** @todo We currently don't care if the entire time wasted here is larger than
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * cMillies */
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync rc = RTSemEventWait(pQueue->EventSem, cMillies);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rc != VINF_SUCCESS)
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync break;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync continue;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync }
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync ASMAtomicWriteBool(&pQueue->fBusy, true);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Reverse the list to process it in FIFO order.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTREQ pReq = pReqs;
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync if (pReq->pNext)
17c6e5e8177d068d1bc6af875d1610718efcfdb4vboxsync Log2(("RTReqProcess: 2+ requests: %p %p %p\n", pReq, pReq->pNext, pReq->pNext->pNext));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pReqs = NULL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync while (pReq)
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pReq->enmState == RTREQSTATE_QUEUED);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pReq->pQueue == pQueue);
fa92c704624def98d3c4aca86d65182effb98e04vboxsync PRTREQ pCur = pReq;
fa92c704624def98d3c4aca86d65182effb98e04vboxsync pReq = pReq->pNext;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCur->pNext = pReqs;
17c6e5e8177d068d1bc6af875d1610718efcfdb4vboxsync pReqs = pCur;
17c6e5e8177d068d1bc6af875d1610718efcfdb4vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync * Process the requests.
17c6e5e8177d068d1bc6af875d1610718efcfdb4vboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync while (pReqs)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync /* Unchain the first request and advance the list. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pReq = pReqs;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pReqs = pReqs->pNext;
fa92c704624def98d3c4aca86d65182effb98e04vboxsync pReq->pNext = NULL;
fa92c704624def98d3c4aca86d65182effb98e04vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Process the request */
17c6e5e8177d068d1bc6af875d1610718efcfdb4vboxsync rc = rtReqProcessOne(pReq);
17c6e5e8177d068d1bc6af875d1610718efcfdb4vboxsync AssertRC(rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rc != VINF_SUCCESS)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync break; /** @todo r=bird: we're dropping requests here! Add 2nd queue that can hold them. (will fix when writing a testcase) */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("RTReqProcess: returns %Rrc\n", rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRT_EXPORT_SYMBOL(RTReqProcess);
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Allocate and queue a call request.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * If it's desired to poll on the completion of the request set cMillies
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * to 0 and use RTReqWait() to check for completation. In the other case
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * use RT_INDEFINITE_WAIT.
8b43c87d70eb66ea6a484c18d7c23f2bc733e134vboxsync * The returned request packet must be freed using RTReqFree().
8b43c87d70eb66ea6a484c18d7c23f2bc733e134vboxsync *
8b43c87d70eb66ea6a484c18d7c23f2bc733e134vboxsync * @returns iprt statuscode.
8b43c87d70eb66ea6a484c18d7c23f2bc733e134vboxsync * Will not return VERR_INTERRUPTED.
8b43c87d70eb66ea6a484c18d7c23f2bc733e134vboxsync * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
8b43c87d70eb66ea6a484c18d7c23f2bc733e134vboxsync *
8b43c87d70eb66ea6a484c18d7c23f2bc733e134vboxsync * @param pQueue The request queue.
8b43c87d70eb66ea6a484c18d7c23f2bc733e134vboxsync * @param ppReq Where to store the pointer to the request.
8b43c87d70eb66ea6a484c18d7c23f2bc733e134vboxsync * This will be NULL or a valid request pointer not matter what happens.
8b43c87d70eb66ea6a484c18d7c23f2bc733e134vboxsync * @param cMillies Number of milliseconds to wait for the request to
8b43c87d70eb66ea6a484c18d7c23f2bc733e134vboxsync * be completed. Use RT_INDEFINITE_WAIT to only
8b43c87d70eb66ea6a484c18d7c23f2bc733e134vboxsync * wait till it's completed.
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync * @param pfnFunction Pointer to the function to call.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cArgs Number of arguments following in the ellipsis.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param ... Function arguments.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @remarks See remarks on RTReqCallV.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsyncRTDECL(int) RTReqCall(PRTREQQUEUE pQueue, PRTREQ *ppReq, RTMSINTERVAL cMillies, PFNRT pfnFunction, unsigned cArgs, ...)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync va_list va;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync va_start(va, cArgs);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = RTReqCallV(pQueue, ppReq, cMillies, RTREQFLAGS_IPRT_STATUS, pfnFunction, cArgs, va);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync va_end(va);
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRT_EXPORT_SYMBOL(RTReqCall);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Allocate and queue a call request to a void function.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * If it's desired to poll on the completion of the request set cMillies
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync * to 0 and use RTReqWait() to check for completation. In the other case
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync * use RT_INDEFINITE_WAIT.
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync * The returned request packet must be freed using RTReqFree().
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync *
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync * @returns iprt status code.
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync * Will not return VERR_INTERRUPTED.
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync *
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync * @param pQueue The request queue.
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync * @param ppReq Where to store the pointer to the request.
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync * This will be NULL or a valid request pointer not matter what happends.
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync * @param cMillies Number of milliseconds to wait for the request to
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync * be completed. Use RT_INDEFINITE_WAIT to only
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync * wait till it's completed.
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync * @param pfnFunction Pointer to the function to call.
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync * @param cArgs Number of arguments following in the ellipsis.
940dbfa4936f2e3966e9e874c4886709f0c75b44vboxsync * @param ... Function arguments.
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync *
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync * @remarks See remarks on RTReqCallV.
5eca6b757429b1f1d768e16fba65c485af34319dvboxsync */
5eca6b757429b1f1d768e16fba65c485af34319dvboxsyncRTDECL(int) RTReqCallVoid(PRTREQQUEUE pQueue, PRTREQ *ppReq, RTMSINTERVAL cMillies, PFNRT pfnFunction, unsigned cArgs, ...)
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync va_list va;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync va_start(va, cArgs);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = RTReqCallV(pQueue, ppReq, cMillies, RTREQFLAGS_VOID, pfnFunction, cArgs, va);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync va_end(va);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return rc;
ada08ea58e7613c10d4c40669fd4fb955324bfdfvboxsync}
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsyncRT_EXPORT_SYMBOL(RTReqCallVoid);
ada08ea58e7613c10d4c40669fd4fb955324bfdfvboxsync
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync
ada08ea58e7613c10d4c40669fd4fb955324bfdfvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Allocate and queue a call request to a void function.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
5cd35366dd244ca8c8c583904fc6ff2a0c60fa0fvboxsync * If it's desired to poll on the completion of the request set cMillies
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync * to 0 and use RTReqWait() to check for completation. In the other case
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync * use RT_INDEFINITE_WAIT.
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync * The returned request packet must be freed using RTReqFree().
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync *
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync * @returns iprt status code.
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync * Will not return VERR_INTERRUPTED.
2a08e12d5dcc1bb5057a9620e87ad361d41a1c1fvboxsync * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
43d3e60a2bcef646da0887a845e67c3a47759158vboxsync * @param pQueue The request queue.
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync * @param ppReq Where to store the pointer to the request.
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync * This will be NULL or a valid request pointer not matter what happends, unless fFlags
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync * contains RTREQFLAGS_NO_WAIT when it will be optional and always NULL.
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync * @param cMillies Number of milliseconds to wait for the request to
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync * be completed. Use RT_INDEFINITE_WAIT to only
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync * wait till it's completed.
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync * @param fFlags A combination of the RTREQFLAGS values.
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync * @param pfnFunction Pointer to the function to call.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cArgs Number of arguments following in the ellipsis.
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync * @param ... Function arguments.
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync *
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync * @remarks See remarks on RTReqCallV.
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync */
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsyncRTDECL(int) RTReqCallEx(PRTREQQUEUE pQueue, PRTREQ *ppReq, RTMSINTERVAL cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, ...)
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync{
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync va_list va;
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync va_start(va, cArgs);
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync int rc = RTReqCallV(pQueue, ppReq, cMillies, fFlags, pfnFunction, cArgs, va);
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync va_end(va);
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync return rc;
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync}
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsyncRT_EXPORT_SYMBOL(RTReqCallEx);
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync/**
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync * Allocate and queue a call request.
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync *
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync * If it's desired to poll on the completion of the request set cMillies
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync * to 0 and use RTReqWait() to check for completation. In the other case
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync * use RT_INDEFINITE_WAIT.
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync * The returned request packet must be freed using RTReqFree().
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync *
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync * @returns iprt status code.
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync * Will not return VERR_INTERRUPTED.
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync *
a1d83f29ade4c8f9fe95fc75d3fb2642f36081c1vboxsync * @param pQueue The request queue.
a1d83f29ade4c8f9fe95fc75d3fb2642f36081c1vboxsync * @param ppReq Where to store the pointer to the request.
a1d83f29ade4c8f9fe95fc75d3fb2642f36081c1vboxsync * This will be NULL or a valid request pointer not matter what happends, unless fFlags
a1d83f29ade4c8f9fe95fc75d3fb2642f36081c1vboxsync * contains RTREQFLAGS_NO_WAIT when it will be optional and always NULL.
a1d83f29ade4c8f9fe95fc75d3fb2642f36081c1vboxsync * @param cMillies Number of milliseconds to wait for the request to
a1d83f29ade4c8f9fe95fc75d3fb2642f36081c1vboxsync * be completed. Use RT_INDEFINITE_WAIT to only
a1d83f29ade4c8f9fe95fc75d3fb2642f36081c1vboxsync * wait till it's completed.
a1d83f29ade4c8f9fe95fc75d3fb2642f36081c1vboxsync * @param fFlags A combination of the RTREQFLAGS values.
a1d83f29ade4c8f9fe95fc75d3fb2642f36081c1vboxsync * @param pfnFunction Pointer to the function to call.
a1d83f29ade4c8f9fe95fc75d3fb2642f36081c1vboxsync * @param cArgs Number of arguments following in the ellipsis.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * @param Args Variable argument vector.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync *
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * @remarks Caveats:
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * - Do not pass anything which is larger than an uintptr_t.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * - 64-bit integers are larger than uintptr_t on 32-bit hosts.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * Pass integers > 32-bit by reference (pointers).
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * - Don't use NULL since it should be the integer 0 in C++ and may
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * therefore end up with garbage in the bits 63:32 on 64-bit
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * hosts because 'int' is 32-bit.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * Use (void *)NULL or (uintptr_t)0 instead of NULL.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync */
e74eef731a813e4e06680c587a6759b9974b29c9vboxsyncRTDECL(int) RTReqCallV(PRTREQQUEUE pQueue, PRTREQ *ppReq, RTMSINTERVAL cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync{
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync LogFlow(("RTReqCallV: cMillies=%d fFlags=%#x pfnFunction=%p cArgs=%d\n", cMillies, fFlags, pfnFunction, cArgs));
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync /*
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * Check input.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync */
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync if (!pfnFunction || !pQueue || (fFlags & ~(RTREQFLAGS_RETURN_MASK | RTREQFLAGS_NO_WAIT)))
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync {
8b43c87d70eb66ea6a484c18d7c23f2bc733e134vboxsync AssertFailed();
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync return VERR_INVALID_PARAMETER;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync }
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync if (!(fFlags & RTREQFLAGS_NO_WAIT) || ppReq)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync {
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync Assert(ppReq);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync *ppReq = NULL;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync }
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync PRTREQ pReq = NULL;
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync if (cArgs * sizeof(uintptr_t) > sizeof(pReq->u.Internal.aArgs))
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync {
c3ad1c4d80999dbb6c9c3e6ff44a35f70566c306vboxsync AssertMsgFailed(("cArg=%d\n", cArgs));
a1d83f29ade4c8f9fe95fc75d3fb2642f36081c1vboxsync return VERR_TOO_MUCH_DATA;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync }
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync /*
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * Allocate request
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync */
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync int rc = RTReqAlloc(pQueue, &pReq, RTREQTYPE_INTERNAL);
5cd35366dd244ca8c8c583904fc6ff2a0c60fa0fvboxsync if (rc != VINF_SUCCESS)
43d3e60a2bcef646da0887a845e67c3a47759158vboxsync return rc;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync /*
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * Initialize the request data.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync */
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync pReq->fFlags = fFlags;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pReq->u.Internal.pfn = pfnFunction;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pReq->u.Internal.cArgs = cArgs;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (unsigned iArg = 0; iArg < cArgs; iArg++)
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync pReq->u.Internal.aArgs[iArg] = va_arg(Args, uintptr_t);
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync /*
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync * Queue the request and return.
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync */
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync rc = RTReqQueue(pReq, cMillies);
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync if ( rc != VINF_SUCCESS
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync && rc != VERR_TIMEOUT)
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync {
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync RTReqFree(pReq);
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync pReq = NULL;
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync }
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync if (!(fFlags & RTREQFLAGS_NO_WAIT))
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync {
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync *ppReq = pReq;
da2ac963e5567d049d02bad0ad7783a0b9181637vboxsync LogFlow(("RTReqCallV: returns %Rrc *ppReq=%p\n", rc, pReq));
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("RTReqCallV: returns %Rrc\n", rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(rc != VERR_INTERRUPTED);
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRT_EXPORT_SYMBOL(RTReqCallV);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync/**
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync * Joins the list pList with whatever is linked up at *pHead.
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync */
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsyncstatic void vmr3ReqJoinFreeSub(volatile PRTREQ *ppHead, PRTREQ pList)
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync{
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync for (unsigned cIterations = 0;; cIterations++)
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync {
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync PRTREQ pHead = (PRTREQ)ASMAtomicXchgPtr((void * volatile *)ppHead, pList);
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync if (!pHead)
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync return;
447f830b91e4e0a6702f578f2c0babfd812a5d74vboxsync PRTREQ pTail = pHead;
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync while (pTail->pNext)
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync pTail = pTail->pNext;
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync pTail->pNext = pList;
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync if (ASMAtomicCmpXchgPtr((void * volatile *)ppHead, (void *)pHead, pList))
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync return;
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync pTail->pNext = NULL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (ASMAtomicCmpXchgPtr((void * volatile *)ppHead, (void *)pHead, NULL))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pList = pHead;
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync Assert(cIterations != 32);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(cIterations != 64);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Joins the list pList with whatever is linked up at *pHead.
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic void vmr3ReqJoinFree(PRTREQQUEUE pQueue, PRTREQ pList)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync * Split the list if it's too long.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync unsigned cReqs = 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTREQ pTail = pList;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync while (pTail->pNext)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync {
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync if (cReqs++ > 25)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync {
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync const uint32_t i = pQueue->iReqFree;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync vmr3ReqJoinFreeSub(&pQueue->apReqFree[(i + 2) % RT_ELEMENTS(pQueue->apReqFree)], pTail->pNext);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync pTail->pNext = NULL;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync vmr3ReqJoinFreeSub(&pQueue->apReqFree[(i + 2 + (i == pQueue->iReqFree)) % RT_ELEMENTS(pQueue->apReqFree)], pTail->pNext);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync return;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync }
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync pTail = pTail->pNext;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync }
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync vmr3ReqJoinFreeSub(&pQueue->apReqFree[(pQueue->iReqFree + 2) % RT_ELEMENTS(pQueue->apReqFree)], pList);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync}
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync/**
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * Allocates a request packet.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync *
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * The caller allocates a request packet, fills in the request data
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * union and queues the request.
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync *
1f67f03c498fb10dfaa104a3698a1e149b7e9eb5vboxsync * @returns iprt status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pQueue The request queue.
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * @param ppReq Where to store the pointer to the allocated packet.
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * @param enmType Package type.
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync */
e17f587595bd5d3a7be56a892e3fd3a0ef83d268vboxsyncRTDECL(int) RTReqAlloc(PRTREQQUEUE pQueue, PRTREQ *ppReq, RTREQTYPE enmType)
10eaaac806009b8336cc5d746fe5072f6c9f58c0vboxsync{
ef5b48babdb77b6bcc17a490cbbd0eef5e46e9fcvboxsync RT_EXPORT_SYMBOL(RTReqAlloc);
ef5b48babdb77b6bcc17a490cbbd0eef5e46e9fcvboxsync /*
1f67f03c498fb10dfaa104a3698a1e149b7e9eb5vboxsync * Validate input.
1f67f03c498fb10dfaa104a3698a1e149b7e9eb5vboxsync */
1f67f03c498fb10dfaa104a3698a1e149b7e9eb5vboxsync if ( enmType < RTREQTYPE_INVALID
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync || enmType > RTREQTYPE_MAX)
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync {
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync AssertMsgFailed(("Invalid package type %d valid range %d-%d inclusivly.\n",
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync enmType, RTREQTYPE_INVALID + 1, RTREQTYPE_MAX - 1));
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync return VERR_RT_REQUEST_INVALID_TYPE;
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync }
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync /*
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync * Try get a recycled packet.
3c292c68aeb0a95090706381edf33b886c81afd1vboxsync * While this could all be solved with a single list with a lock, it's a sport
3c292c68aeb0a95090706381edf33b886c81afd1vboxsync * of mine to avoid locks.
3c292c68aeb0a95090706381edf33b886c81afd1vboxsync */
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync int cTries = RT_ELEMENTS(pQueue->apReqFree) * 2;
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync while (--cTries >= 0)
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync {
1f67f03c498fb10dfaa104a3698a1e149b7e9eb5vboxsync PRTREQ volatile *ppHead = &pQueue->apReqFree[ASMAtomicIncU32(&pQueue->iReqFree) % RT_ELEMENTS(pQueue->apReqFree)];
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsync#if 0 /* sad, but this won't work safely because the reading of pReq->pNext. */
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsync PRTREQ pNext = NULL;
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsync PRTREQ pReq = *ppHead;
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsync if ( pReq
6a2b7cefae549318ba64aee5d6f40d0aae28f1a3vboxsync && !ASMAtomicCmpXchgPtr((void * volatile *)ppHead, (pNext = pReq->pNext), pReq)
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsync && (pReq = *ppHead)
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync && !ASMAtomicCmpXchgPtr((void * volatile *)ppHead, (pNext = pReq->pNext), pReq))
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync pReq = NULL;
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync if (pReq)
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync {
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync Assert(pReq->pNext == pNext); NOREF(pReq);
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync#else
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync PRTREQ pReq = (PRTREQ)ASMAtomicXchgPtr((void * volatile *)ppHead, NULL);
395ac8a20a012656020c61a3975493a65fee0e77vboxsync if (pReq)
960d1f2d42faa8d833309114e5adc46a6a658c27vboxsync {
395ac8a20a012656020c61a3975493a65fee0e77vboxsync PRTREQ pNext = pReq->pNext;
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsync if ( pNext
8809400ad2407593d3471b82d5caf0c24cbcdf8avboxsync && !ASMAtomicCmpXchgPtr((void * volatile *)ppHead, pNext, NULL))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync vmr3ReqJoinFree(pQueue, pReq->pNext);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync#endif
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync ASMAtomicDecU32(&pQueue->cReqFree);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * Make sure the event sem is not signaled.
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync */
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync if (!pReq->fEventSemClear)
e17f587595bd5d3a7be56a892e3fd3a0ef83d268vboxsync {
10eaaac806009b8336cc5d746fe5072f6c9f58c0vboxsync int rc = RTSemEventWait(pReq->EventSem, 0);
1bc5a31ae6d57c2b4731a23205f3958678b60193vboxsync if (rc != VINF_SUCCESS && rc != VERR_TIMEOUT)
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync {
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync /*
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync * This shall not happen, but if it does we'll just destroy
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync * the semaphore and create a new one.
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync */
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync AssertMsgFailed(("rc=%Rrc from RTSemEventWait(%#x).\n", rc, pReq->EventSem));
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync RTSemEventDestroy(pReq->EventSem);
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync rc = RTSemEventCreate(&pReq->EventSem);
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync AssertRC(rc);
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync if (rc != VINF_SUCCESS)
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync return rc;
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync }
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync pReq->fEventSemClear = true;
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync }
09b36b509b761f9ce006fa9c25cb86d12757b937vboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(RTSemEventWait(pReq->EventSem, 0) == VERR_TIMEOUT);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
0c5d6027e582baa247e987e184f93d44623e7443vboxsync * Initialize the packet and return it.
0c5d6027e582baa247e987e184f93d44623e7443vboxsync */
0c5d6027e582baa247e987e184f93d44623e7443vboxsync Assert(pReq->enmType == RTREQTYPE_INVALID);
0c5d6027e582baa247e987e184f93d44623e7443vboxsync Assert(pReq->enmState == RTREQSTATE_FREE);
0c5d6027e582baa247e987e184f93d44623e7443vboxsync Assert(pReq->pQueue == pQueue);
0c5d6027e582baa247e987e184f93d44623e7443vboxsync ASMAtomicXchgSize(&pReq->pNext, NULL);
0c5d6027e582baa247e987e184f93d44623e7443vboxsync pReq->enmState = RTREQSTATE_ALLOCATED;
0c5d6027e582baa247e987e184f93d44623e7443vboxsync pReq->iStatus = VERR_RT_REQUEST_STATUS_STILL_PENDING;
0c5d6027e582baa247e987e184f93d44623e7443vboxsync pReq->fFlags = RTREQFLAGS_IPRT_STATUS;
0c5d6027e582baa247e987e184f93d44623e7443vboxsync pReq->enmType = enmType;
0c5d6027e582baa247e987e184f93d44623e7443vboxsync
0c5d6027e582baa247e987e184f93d44623e7443vboxsync *ppReq = pReq;
0c5d6027e582baa247e987e184f93d44623e7443vboxsync LogFlow(("RTReqAlloc: returns VINF_SUCCESS *ppReq=%p recycled\n", pReq));
0c5d6027e582baa247e987e184f93d44623e7443vboxsync return VINF_SUCCESS;
0c5d6027e582baa247e987e184f93d44623e7443vboxsync }
0c5d6027e582baa247e987e184f93d44623e7443vboxsync }
4bfa7b58e362a1bca0628643c352c137900bf01avboxsync
0c5d6027e582baa247e987e184f93d44623e7443vboxsync /*
0c5d6027e582baa247e987e184f93d44623e7443vboxsync * Ok allocate one.
0c5d6027e582baa247e987e184f93d44623e7443vboxsync */
0c5d6027e582baa247e987e184f93d44623e7443vboxsync PRTREQ pReq = (PRTREQ)RTMemAllocZ(sizeof(*pReq));
0c5d6027e582baa247e987e184f93d44623e7443vboxsync if (!pReq)
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync return VERR_NO_MEMORY;
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Create the semaphore.
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsync */
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsync int rc = RTSemEventCreate(&pReq->EventSem);
b0d29fd0a868929a608ff72658aac997cc95319avboxsync AssertRC(rc);
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsync if (rc != VINF_SUCCESS)
b0d29fd0a868929a608ff72658aac997cc95319avboxsync {
b0d29fd0a868929a608ff72658aac997cc95319avboxsync RTMemFree(pReq);
b0d29fd0a868929a608ff72658aac997cc95319avboxsync return rc;
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsync }
b0d29fd0a868929a608ff72658aac997cc95319avboxsync
b0d29fd0a868929a608ff72658aac997cc95319avboxsync /*
b0d29fd0a868929a608ff72658aac997cc95319avboxsync * Initialize the packet and return it.
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsync */
b0d29fd0a868929a608ff72658aac997cc95319avboxsync pReq->pNext = NULL;
b0d29fd0a868929a608ff72658aac997cc95319avboxsync pReq->pQueue = pQueue;
b0d29fd0a868929a608ff72658aac997cc95319avboxsync pReq->enmState = RTREQSTATE_ALLOCATED;
b0d29fd0a868929a608ff72658aac997cc95319avboxsync pReq->iStatus = VERR_RT_REQUEST_STATUS_STILL_PENDING;
c50100d1513854735d4e3593b3b385c007f6d8b6vboxsync pReq->fEventSemClear = true;
b0d29fd0a868929a608ff72658aac997cc95319avboxsync pReq->fFlags = RTREQFLAGS_IPRT_STATUS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pReq->enmType = enmType;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *ppReq = pReq;
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync LogFlow(("RTReqAlloc: returns VINF_SUCCESS *ppReq=%p new\n", pReq));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Free a request packet.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync * @returns iprt status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pReq Package to free.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @remark The request packet must be in allocated or completed state!
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTReqFree(PRTREQ pReq)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync * Ignore NULL (all free functions should do this imho).
6c83eb6b98d1dd1b1d9795c16801ee2f53d2cc31vboxsync */
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync if (!pReq)
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync return VINF_SUCCESS;
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync
6565c2fb4f10f47bcb5436630d2dc35e5a4f28e2vboxsync /*
2da513a7caa29822c9991d7e8615658a194c0cf8vboxsync * Check packet state.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync */
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync switch (pReq->enmState)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync {
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync case RTREQSTATE_ALLOCATED:
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync case RTREQSTATE_COMPLETED:
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync break;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync default:
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync AssertMsgFailed(("Invalid state %d!\n", pReq->enmState));
0c5d6027e582baa247e987e184f93d44623e7443vboxsync return VERR_RT_REQUEST_STATE;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync }
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync /*
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * Make it a free packet and put it into one of the free packet lists.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync */
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync pReq->enmState = RTREQSTATE_FREE;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync pReq->iStatus = VERR_RT_REQUEST_STATUS_FREED;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync pReq->enmType = RTREQTYPE_INVALID;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync PRTREQQUEUE pQueue = pReq->pQueue;
2da513a7caa29822c9991d7e8615658a194c0cf8vboxsync if (pQueue->cReqFree < 128)
2da513a7caa29822c9991d7e8615658a194c0cf8vboxsync {
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync ASMAtomicIncU32(&pQueue->cReqFree);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync PRTREQ volatile *ppHead = &pQueue->apReqFree[ASMAtomicIncU32(&pQueue->iReqFree) % RT_ELEMENTS(pQueue->apReqFree)];
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync PRTREQ pNext;
2da513a7caa29822c9991d7e8615658a194c0cf8vboxsync do
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync {
86b620001857a05e9e7b83b11525094c34637e23vboxsync pNext = *ppHead;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync ASMAtomicXchgPtr((void * volatile *)&pReq->pNext, pNext);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync } while (!ASMAtomicCmpXchgPtr((void * volatile *)ppHead, (void *)pReq, (void *)pNext));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync else
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync {
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync RTSemEventDestroy(pReq->EventSem);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTMemFree(pReq);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync return VINF_SUCCESS;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync}
86b620001857a05e9e7b83b11525094c34637e23vboxsyncRT_EXPORT_SYMBOL(RTReqFree);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync * Queue a request.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The quest must be allocated using RTReqAlloc() and contain
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * all the required data.
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync * If it's disired to poll on the completion of the request set cMillies
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * to 0 and use RTReqWait() to check for completation. In the other case
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * use RT_INDEFINITE_WAIT.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync * @returns iprt status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Will not return VERR_INTERRUPTED.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync * @param pReq The request to queue.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cMillies Number of milliseconds to wait for the request to
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * be completed. Use RT_INDEFINITE_WAIT to only
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * wait till it's completed.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync */
e74eef731a813e4e06680c587a6759b9974b29c9vboxsyncRTDECL(int) RTReqQueue(PRTREQ pReq, RTMSINTERVAL cMillies)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync{
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync LogFlow(("RTReqQueue: pReq=%p cMillies=%d\n", pReq, cMillies));
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync /*
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * Verify the supplied package.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync */
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync if (pReq->enmState != RTREQSTATE_ALLOCATED)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync {
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync AssertMsgFailed(("Invalid state %d\n", pReq->enmState));
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync return VERR_RT_REQUEST_STATE;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync }
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync if ( !pReq->pQueue
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync || pReq->pNext
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync || !pReq->EventSem)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Invalid request package! Anyone cooking their own packages???\n"));
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync return VERR_RT_REQUEST_INVALID_PACKAGE;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync }
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync if ( pReq->enmType < RTREQTYPE_INVALID
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync || pReq->enmType > RTREQTYPE_MAX)
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync {
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync AssertMsgFailed(("Invalid package type %d valid range %d-%d inclusivly. This was verified on alloc too...\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pReq->enmType, RTREQTYPE_INVALID + 1, RTREQTYPE_MAX - 1));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VERR_RT_REQUEST_INVALID_TYPE;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync }
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync int rc = VINF_SUCCESS;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync /*
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * Insert it.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTREQQUEUE pQueue = ((RTREQ volatile *)pReq)->pQueue; /* volatile paranoia */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync unsigned fFlags = ((RTREQ volatile *)pReq)->fFlags; /* volatile paranoia */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pReq->enmState = RTREQSTATE_QUEUED;
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync PRTREQ pNext;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync do
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pNext = pQueue->pReqs;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync pReq->pNext = pNext;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync ASMAtomicWriteBool(&pQueue->fBusy, true);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync } while (!ASMAtomicCmpXchgPtr((void * volatile *)&pQueue->pReqs, (void *)pReq, (void *)pNext));
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync /*
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * Notify queue thread.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync */
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync RTSemEventSignal(pQueue->EventSem);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync /*
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * Wait and return.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync */
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync if (!(fFlags & RTREQFLAGS_NO_WAIT))
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync rc = RTReqWait(pReq, cMillies);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync LogFlow(("RTReqQueue: returns %Rrc\n", rc));
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync return rc;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync}
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsyncRT_EXPORT_SYMBOL(RTReqQueue);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync/**
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * Wait for a request to be completed.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync *
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * @returns iprt status code.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * Will not return VERR_INTERRUPTED.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pReq The request to wait for.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * @param cMillies Number of milliseconds to wait.
f1f55b6ac890efaabca0ff940f58aa8df1dc84c8vboxsync * Use RT_INDEFINITE_WAIT to only wait till it's completed.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync */
f1f55b6ac890efaabca0ff940f58aa8df1dc84c8vboxsyncRTDECL(int) RTReqWait(PRTREQ pReq, RTMSINTERVAL cMillies)
f1f55b6ac890efaabca0ff940f58aa8df1dc84c8vboxsync{
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync LogFlow(("RTReqWait: pReq=%p cMillies=%d\n", pReq, cMillies));
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync /*
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * Verify the supplied package.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync */
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync if ( pReq->enmState != RTREQSTATE_QUEUED
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync && pReq->enmState != RTREQSTATE_PROCESSING
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync && pReq->enmState != RTREQSTATE_COMPLETED)
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync {
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync AssertMsgFailed(("Invalid state %d\n", pReq->enmState));
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync return VERR_RT_REQUEST_STATE;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync }
f1f55b6ac890efaabca0ff940f58aa8df1dc84c8vboxsync if ( !pReq->pQueue
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync || !pReq->EventSem)
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync {
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync AssertMsgFailed(("Invalid request package! Anyone cooking their own packages???\n"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VERR_RT_REQUEST_INVALID_PACKAGE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ( pReq->enmType < RTREQTYPE_INVALID
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync || pReq->enmType > RTREQTYPE_MAX)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Invalid package type %d valid range %d-%d inclusivly. This was verified on alloc and queue too...\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pReq->enmType, RTREQTYPE_INVALID + 1, RTREQTYPE_MAX - 1));
ce666b71b4eb6477625b0057689a08aaa7c11b64vboxsync return VERR_RT_REQUEST_INVALID_TYPE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
dee2201f96a012bfb966c8de4ab006c2c90a0eefvboxsync * Wait on the package.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (cMillies != RT_INDEFINITE_WAIT)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync rc = RTSemEventWait(pReq->EventSem, cMillies);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync else
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync {
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync do
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync {
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync rc = RTSemEventWait(pReq->EventSem, RT_INDEFINITE_WAIT);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync Assert(rc != VERR_TIMEOUT);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync } while (pReq->enmState != RTREQSTATE_COMPLETED);
f1f55b6ac890efaabca0ff940f58aa8df1dc84c8vboxsync }
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync if (rc == VINF_SUCCESS)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync ASMAtomicXchgSize(&pReq->fEventSemClear, true);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync if (pReq->enmState == RTREQSTATE_COMPLETED)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync rc = VINF_SUCCESS;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync LogFlow(("RTReqWait: returns %Rrc\n", rc));
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync Assert(rc != VERR_INTERRUPTED);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync return rc;
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync}
e74eef731a813e4e06680c587a6759b9974b29c9vboxsyncRT_EXPORT_SYMBOL(RTReqWait);
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync/**
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * Process one request.
cce0c6096dee0c5353bb74431dc47b05f87a1c6dvboxsync *
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * @returns IPRT status code.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync *
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * @param pReq Request packet to process.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync */
e74eef731a813e4e06680c587a6759b9974b29c9vboxsyncstatic int rtReqProcessOne(PRTREQ pReq)
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync{
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync LogFlow(("rtReqProcessOne: pReq=%p type=%d fFlags=%#x\n", pReq, pReq->enmType, pReq->fFlags));
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync /*
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync * Process the request.
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync */
e74eef731a813e4e06680c587a6759b9974b29c9vboxsync Assert(pReq->enmState == RTREQSTATE_QUEUED);
cce0c6096dee0c5353bb74431dc47b05f87a1c6dvboxsync pReq->enmState = RTREQSTATE_PROCESSING;
11923fc977be1686f5428c3e790c04d0701a074cvboxsync int rcRet = VINF_SUCCESS; /* the return code of this function. */
11923fc977be1686f5428c3e790c04d0701a074cvboxsync int rcReq = VERR_NOT_IMPLEMENTED; /* the request status. */
11923fc977be1686f5428c3e790c04d0701a074cvboxsync switch (pReq->enmType)
cce0c6096dee0c5353bb74431dc47b05f87a1c6dvboxsync {
cce0c6096dee0c5353bb74431dc47b05f87a1c6dvboxsync /*
11923fc977be1686f5428c3e790c04d0701a074cvboxsync * A packed down call frame.
11923fc977be1686f5428c3e790c04d0701a074cvboxsync */
11923fc977be1686f5428c3e790c04d0701a074cvboxsync case RTREQTYPE_INTERNAL:
11923fc977be1686f5428c3e790c04d0701a074cvboxsync {
11923fc977be1686f5428c3e790c04d0701a074cvboxsync uintptr_t *pauArgs = &pReq->u.Internal.aArgs[0];
11923fc977be1686f5428c3e790c04d0701a074cvboxsync union
11923fc977be1686f5428c3e790c04d0701a074cvboxsync {
11923fc977be1686f5428c3e790c04d0701a074cvboxsync PFNRT pfn;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync DECLCALLBACKMEMBER(int, pfn00)(void);
11923fc977be1686f5428c3e790c04d0701a074cvboxsync DECLCALLBACKMEMBER(int, pfn01)(uintptr_t);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync DECLCALLBACKMEMBER(int, pfn02)(uintptr_t, uintptr_t);
cce0c6096dee0c5353bb74431dc47b05f87a1c6dvboxsync DECLCALLBACKMEMBER(int, pfn03)(uintptr_t, uintptr_t, uintptr_t);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync DECLCALLBACKMEMBER(int, pfn04)(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync DECLCALLBACKMEMBER(int, pfn05)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync DECLCALLBACKMEMBER(int, pfn06)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync DECLCALLBACKMEMBER(int, pfn07)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync DECLCALLBACKMEMBER(int, pfn08)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync DECLCALLBACKMEMBER(int, pfn09)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync DECLCALLBACKMEMBER(int, pfn10)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync DECLCALLBACKMEMBER(int, pfn11)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync DECLCALLBACKMEMBER(int, pfn12)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync } u;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync u.pfn = pReq->u.Internal.pfn;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync#ifdef RT_ARCH_AMD64
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync switch (pReq->u.Internal.cArgs)
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync {
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync case 0: rcRet = u.pfn00(); break;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync case 1: rcRet = u.pfn01(pauArgs[0]); break;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync case 2: rcRet = u.pfn02(pauArgs[0], pauArgs[1]); break;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync case 3: rcRet = u.pfn03(pauArgs[0], pauArgs[1], pauArgs[2]); break;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync case 4: rcRet = u.pfn04(pauArgs[0], pauArgs[1], pauArgs[2], pauArgs[3]); break;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync case 5: rcRet = u.pfn05(pauArgs[0], pauArgs[1], pauArgs[2], pauArgs[3], pauArgs[4]); break;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync case 6: rcRet = u.pfn06(pauArgs[0], pauArgs[1], pauArgs[2], pauArgs[3], pauArgs[4], pauArgs[5]); break;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync case 7: rcRet = u.pfn07(pauArgs[0], pauArgs[1], pauArgs[2], pauArgs[3], pauArgs[4], pauArgs[5], pauArgs[6]); break;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync case 8: rcRet = u.pfn08(pauArgs[0], pauArgs[1], pauArgs[2], pauArgs[3], pauArgs[4], pauArgs[5], pauArgs[6], pauArgs[7]); break;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync case 9: rcRet = u.pfn09(pauArgs[0], pauArgs[1], pauArgs[2], pauArgs[3], pauArgs[4], pauArgs[5], pauArgs[6], pauArgs[7], pauArgs[8]); break;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync case 10: rcRet = u.pfn10(pauArgs[0], pauArgs[1], pauArgs[2], pauArgs[3], pauArgs[4], pauArgs[5], pauArgs[6], pauArgs[7], pauArgs[8], pauArgs[9]); break;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync case 11: rcRet = u.pfn11(pauArgs[0], pauArgs[1], pauArgs[2], pauArgs[3], pauArgs[4], pauArgs[5], pauArgs[6], pauArgs[7], pauArgs[8], pauArgs[9], pauArgs[10]); break;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync case 12: rcRet = u.pfn12(pauArgs[0], pauArgs[1], pauArgs[2], pauArgs[3], pauArgs[4], pauArgs[5], pauArgs[6], pauArgs[7], pauArgs[8], pauArgs[9], pauArgs[10], pauArgs[11]); break;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync default:
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync AssertReleaseMsgFailed(("cArgs=%d\n", pReq->u.Internal.cArgs));
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync rcRet = rcReq = VERR_INTERNAL_ERROR;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync break;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync }
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync#else /* x86: */
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync size_t cbArgs = pReq->u.Internal.cArgs * sizeof(uintptr_t);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync# ifdef __GNUC__
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync __asm__ __volatile__("movl %%esp, %%edx\n\t"
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync "subl %2, %%esp\n\t"
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync "andl $0xfffffff0, %%esp\n\t"
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync "shrl $2, %2\n\t"
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync "movl %%esp, %%edi\n\t"
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync "rep movsl\n\t"
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync "movl %%edx, %%edi\n\t"
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync "call *%%eax\n\t"
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync "mov %%edi, %%esp\n\t"
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync : "=a" (rcRet),
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync "=S" (pauArgs),
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync "=c" (cbArgs)
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync : "0" (u.pfn),
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync "1" (pauArgs),
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync "2" (cbArgs)
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync : "edi", "edx");
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync# else
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync __asm
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync {
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync xor edx, edx /* just mess it up. */
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync mov eax, u.pfn
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync mov ecx, cbArgs
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync shr ecx, 2
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync mov esi, pauArgs
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync mov ebx, esp
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync sub esp, cbArgs
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync and esp, 0xfffffff0
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync mov edi, esp
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync rep movsd
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync call eax
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync mov esp, ebx
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync mov rcRet, eax
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync }
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync# endif
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync#endif /* x86 */
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync if ((pReq->fFlags & (RTREQFLAGS_RETURN_MASK)) == RTREQFLAGS_VOID)
5bc12adcd2551b1a206b40f9ad976fed75bea9a0vboxsync rcRet = VINF_SUCCESS;
af86e71b7cb472cb35c26e2d78c0152fad35e0e7vboxsync rcReq = rcRet;
af86e71b7cb472cb35c26e2d78c0152fad35e0e7vboxsync break;
af86e71b7cb472cb35c26e2d78c0152fad35e0e7vboxsync }
af86e71b7cb472cb35c26e2d78c0152fad35e0e7vboxsync
af86e71b7cb472cb35c26e2d78c0152fad35e0e7vboxsync default:
af86e71b7cb472cb35c26e2d78c0152fad35e0e7vboxsync AssertMsgFailed(("pReq->enmType=%d\n", pReq->enmType));
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync rcReq = VERR_NOT_IMPLEMENTED;
5bc12adcd2551b1a206b40f9ad976fed75bea9a0vboxsync break;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync }
766956791b9a42fc91ba6f8bd8be7f6a6f7ba092vboxsync
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync /*
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync * Complete the request.
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync */
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync pReq->iStatus = rcReq;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync pReq->enmState = RTREQSTATE_COMPLETED;
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync if (pReq->fFlags & RTREQFLAGS_NO_WAIT)
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync {
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync /* Free the packet, nobody is waiting. */
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync LogFlow(("rtReqProcessOne: Completed request %p: rcReq=%Rrc rcRet=%Rrc - freeing it\n",
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync pReq, rcReq, rcRet));
af86e71b7cb472cb35c26e2d78c0152fad35e0e7vboxsync RTReqFree(pReq);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync }
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync else
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync {
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync /* Notify the waiter and him free up the packet. */
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync LogFlow(("rtReqProcessOne: Completed request %p: rcReq=%Rrc rcRet=%Rrc - notifying waiting thread\n",
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync pReq, rcReq, rcRet));
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync ASMAtomicXchgSize(&pReq->fEventSemClear, false);
06dc6eb95cf33b2b83f0d07c602d1ca20a575663vboxsync int rc2 = RTSemEventSignal(pReq->EventSem);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (rc2 != VINF_SUCCESS)
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertRC(rc2);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync rcRet = rc2;
4bfa7b58e362a1bca0628643c352c137900bf01avboxsync }
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync }
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync return rcRet;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync}
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/**
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * Checks if the queue is busy or not.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * The caller is responsible for dealing with any concurrent submitts.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync *
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * @returns true if busy, false if idle.
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync * @param pQueue The queue.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(bool) RTReqIsBusy(PRTREQQUEUE pQueue)
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertPtrReturn(pQueue, false);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync if (ASMAtomicReadBool(&pQueue->fBusy))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return true;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (ASMAtomicReadPtr((void * volatile *)&pQueue->pReqs) != NULL)
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync return true;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync if (ASMAtomicReadBool(&pQueue->fBusy))
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync return true;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return false;
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync}
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsyncRT_EXPORT_SYMBOL(RTReqIsBusy);
377f1df8d6ec248927bcdf0efabf87ab55c4a615vboxsync