req.cpp revision 653078b995fb7a9ee76867cc676f08c90187cfe9
/* $Id$ */
/** @file
* IPRT - Request packets
*/
/*
* Copyright (C) 2006-2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* 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/semaphore.h>
/*******************************************************************************
* Internal Functions *
*******************************************************************************/
/**
* Allocate a new request from the heap.
*
* @returns IPRT status code.
* @param enmType The reques type.
* @param fPoolOrQueue The owner type.
* @param pvOwner The owner.
* @param phReq Where to return the request handle.
*/
{
if (RT_UNLIKELY(!pReq))
return VERR_NO_MEMORY;
/*
* Create the semaphore used for waiting.
*/
/*
* Initialize the packet and return it.
*/
pReq->fEventSemClear = true;
pReq->fSignalPushBack = true;
return VINF_SUCCESS;
}
/**
* Re-initializes a request when it's being recycled.
*
* @returns IRPT status code, the request is freed on failure.
* @param pReq The request.
* @param enmType The request type.
*/
{
/*
* Make sure the event sem is not signaled.
*/
if (!pReq->fEventSemClear)
{
{
/*
* This shall not happen, but if it does we'll just destroy
* the semaphore and create a new one.
*/
if (RT_FAILURE(rc))
{
return rc;
}
}
pReq->fEventSemClear = true;
}
else
/*
* Initialize the packet and return it.
*/
return VINF_SUCCESS;
}
{
}
/**
* Frees a request.
*
* @param pReq The request.
*/
{
}
{
/*
* Ignore NULL and validate the request.
*/
if (!hReq)
return 0;
/*
* Drop a reference, recycle the request when we reach 0.
*/
if (cRefs == 0)
{
/*
* Check packet state.
*/
{
case RTREQSTATE_ALLOCATED:
case RTREQSTATE_COMPLETED:
break;
default:
return 0;
}
/*
* Make it a free packet and put it into one of the free packet lists.
*/
bool fRecycled;
if (pReq->fPoolOrQueue)
else
if (!fRecycled)
}
return cRefs;
}
{
/*
* Verify the supplied package.
*/
AssertMsgReturn(pReq->enmState == RTREQSTATE_ALLOCATED, ("%d\n", pReq->enmState), VERR_RT_REQUEST_STATE);
("Invalid request package! Anyone cooking their own packages???\n"),
("Invalid package type %d valid range %d-%d inclusively. This was verified on alloc too...\n",
/*
* Insert it. Donate the caller's reference if RTREQFLAGS_NO_WAIT is set,
* otherwise retain another reference for the queue.
*/
if (!(fFlags & RTREQFLAGS_NO_WAIT))
if (!pReq->fPoolOrQueue)
else
/*
* Wait and return.
*/
int rc = VINF_SUCCESS;
if (!(fFlags & RTREQFLAGS_NO_WAIT))
return rc;
}
{
/*
* Verify the supplied package.
*/
("Invalid request package! Anyone cooking their own packages???\n"),
("Invalid package type %d valid range %d-%d inclusively. This was verified on alloc too...\n",
/*
* Wait on the package.
*/
int rc;
if (cMillies != RT_INDEFINITE_WAIT)
else
{
do
{
}
if (rc == VINF_SUCCESS)
rc = VINF_SUCCESS;
return rc;
}
{
}
/**
* Process one request.
*
* @returns IPRT status code.
*
* @param pReq Request packet to process.
*/
{
/*
* Process the request.
*/
{
/*
* A packed down call frame.
*/
case RTREQTYPE_INTERNAL:
{
union
{
DECLCALLBACKMEMBER(int, pfn00)(void);
DECLCALLBACKMEMBER(int, pfn07)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
DECLCALLBACKMEMBER(int, pfn08)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
DECLCALLBACKMEMBER(int, pfn09)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
DECLCALLBACKMEMBER(int, pfn10)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
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);
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);
} u;
#ifndef RT_ARCH_X86
{
case 6: rcRet = u.pfn06(pauArgs[0], pauArgs[1], pauArgs[2], pauArgs[3], pauArgs[4], pauArgs[5]); break;
case 7: rcRet = u.pfn07(pauArgs[0], pauArgs[1], pauArgs[2], pauArgs[3], pauArgs[4], pauArgs[5], pauArgs[6]); break;
case 8: rcRet = u.pfn08(pauArgs[0], pauArgs[1], pauArgs[2], pauArgs[3], pauArgs[4], pauArgs[5], pauArgs[6], pauArgs[7]); break;
case 9: rcRet = u.pfn09(pauArgs[0], pauArgs[1], pauArgs[2], pauArgs[3], pauArgs[4], pauArgs[5], pauArgs[6], pauArgs[7], pauArgs[8]); break;
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;
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;
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;
default:
break;
}
#else /* RT_ARCH_X86 */
# ifdef __GNUC__
"subl %2, %%esp\n\t"
"andl $0xfffffff0, %%esp\n\t"
"shrl $2, %2\n\t"
"movl %%esp, %%edi\n\t"
"rep movsl\n\t"
"movl %%edx, %%edi\n\t"
"call *%%eax\n\t"
"mov %%edi, %%esp\n\t"
: "=a" (rcRet),
"=S" (pauArgs),
"=c" (cbArgs)
: "0" (u.pfn),
"1" (pauArgs),
"2" (cbArgs)
: "edi", "edx");
# else
{
}
# endif
#endif /* RT_ARCH_X86 */
break;
}
default:
break;
}
/*
* Complete the request and then release our request handle reference.
*/
LogFlow(("rtReqProcessOne: Completed request %p: rcReq=%Rrc rcRet=%Rrc (no wait)\n",
else
{
/* Notify the waiting thread. */
LogFlow(("rtReqProcessOne: Completed request %p: rcReq=%Rrc rcRet=%Rrc - notifying waiting thread\n",
if (rc2 != VINF_SUCCESS)
{
}
}
return rcRet;
}