VirtualBox

Changeset 14221 in vbox


Ignore:
Timestamp:
Nov 14, 2008 3:06:59 PM (16 years ago)
Author:
vboxsync
Message:

Additions/VBoxGuest: Add VBOXGUEST_IOCTL_CALL_TIMEOUT support on non-Windows and Linux guests (disabled until someone can test it)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp

    r13305 r14221  
    919919}
    920920
     921#ifdef HGCM_TIMEOUT
     922/**
     923 * This is a callback for dealing with async waits with a timeout.
     924 *
     925 * It operates in a manner similar to VBoxGuestCommonIOCtl_WaitEvent.
     926 */
     927static DECLCALLBACK(void)
     928VBoxGuestHGCMAsyncWaitCallbackTimeout(VMMDevHGCMRequestHeader *pHdrNonVolatile, void *pvUser,
     929                                      uint32_t u32User)
     930{
     931    VMMDevHGCMRequestHeader volatile *pHdr = (VMMDevHGCMRequestHeader volatile *)pHdrNonVolatile;
     932    PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pvUser;
     933    Log(("VBoxGuestHGCMAsyncWaitCallback: requestType=%d\n", pHdr->header.requestType));
     934
     935    /*
     936     * Check to see if the condition was met by the time we got here.
     937     *
     938     * We create a simple poll loop here for dealing with out-of-memory
     939     * conditions since the caller isn't necessarily able to deal with
     940     * us returning too early.
     941     */
     942    RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
     943    PVBOXGUESTWAIT pWait;
     944    for (;;)
     945    {
     946        RTSpinlockAcquireNoInts(pDevExt->WaitSpinlock, &Tmp);
     947        if ((pHdr->fu32Flags & VBOX_HGCM_REQ_DONE) != 0)
     948        {
     949            RTSpinlockReleaseNoInts(pDevExt->WaitSpinlock, &Tmp);
     950            return;
     951        }
     952        RTSpinlockReleaseNoInts(pDevExt->WaitSpinlock, &Tmp);
     953
     954        pWait = VBoxGuestWaitAlloc(pDevExt);
     955        if (pWait)
     956            break;
     957        return;
     958    }
     959    pWait->fReqEvents = VMMDEV_EVENT_HGCM;
     960    pWait->pHGCMReq = pHdr;
     961
     962    /*
     963     * Re-enter the spinlock and re-check for the condition.
     964     * If the condition is met, return.
     965     * Otherwise link us into the HGCM wait list and go to sleep.
     966     */
     967    RTSpinlockAcquireNoInts(pDevExt->WaitSpinlock, &Tmp);
     968    if ((pHdr->fu32Flags & VBOX_HGCM_REQ_DONE) != 0)
     969    {
     970        VBoxGuestWaitFreeLocked(pDevExt, pWait);
     971        RTSpinlockReleaseNoInts(pDevExt->WaitSpinlock, &Tmp);
     972        return;
     973    }
     974    VBoxGuestWaitAppend(&pDevExt->HGCMWaitList, pWait);
     975    RTSpinlockReleaseNoInts(pDevExt->WaitSpinlock, &Tmp);
     976
     977    int rc = RTSemEventMultiWaitNoResume(pWait->Event, u32User);
     978
     979    /*
     980     * This shouldn't ever return failure...
     981     * Unlink, free and return.
     982     */
     983    if (rc == VERR_SEM_DESTROYED)
     984        return;
     985    if (RT_FAILURE(rc))
     986        LogRel(("VBoxGuestHGCMAsyncWaitCallback: wait failed! %Rrc\n", rc));
     987
     988    RTSpinlockAcquireNoInts(pDevExt->WaitSpinlock, &Tmp);
     989    VBoxGuestWaitUnlink(&pDevExt->HGCMWaitList, pWait);
     990    VBoxGuestWaitFreeLocked(pDevExt, pWait);
     991    RTSpinlockReleaseNoInts(pDevExt->WaitSpinlock, &Tmp);
     992}
     993#endif /* HGCM_TIMEOUT */
     994
    921995
    922996static int VBoxGuestCommonIOCtl_HGCMConnect(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, VBoxGuestHGCMConnectInfo *pInfo,
     
    10791153
    10801154
     1155#ifdef /* HGCM_TIMEOUT */
     1156static int VBoxGuestCommonIOCtl_HGCMCallTimeout(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, VBoxGuestHGCMCallInfoTimeout *pInfoTimeout,
     1157                                         size_t cbData, size_t *pcbDataReturned)
     1158{
     1159    VBoxGuestHGCMCallInfo *pInfo = &pInfoTimeout->info;
     1160    /*
     1161     * Some more validations.
     1162     */
     1163    if (pInfo->cParms > 4096) /* (Just make sure it doesn't overflow the next check.) */
     1164    {
     1165        Log(("VBoxGuestCommonIOCtl: HGCM_CALL: cParm=%RX32 is not sane\n", pInfo->cParms));
     1166        return VERR_INVALID_PARAMETER;
     1167    }
     1168    const size_t cbActual = sizeof(*pInfoTimeout) + pInfo->cParms * sizeof(HGCMFunctionParameter);
     1169    if (cbData < cbActual)
     1170    {
     1171        Log(("VBoxGuestCommonIOCtl: HGCM_CALL: cbData=%#zx (%zu) required size is %#zx (%zu)\n",
     1172             cbData, cbActual));
     1173        return VERR_INVALID_PARAMETER;
     1174    }
     1175
     1176    /*
     1177     * Validate the client id.
     1178     */
     1179    const uint32_t u32ClientId = pInfo->u32ClientID;
     1180    unsigned i;
     1181    RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
     1182    RTSpinlockAcquireNoInts(pDevExt->SessionSpinlock, &Tmp);
     1183    for (i = 0; i < RT_ELEMENTS(pSession->aHGCMClientIds); i++)
     1184        if (pSession->aHGCMClientIds[i] == u32ClientId)
     1185            break;
     1186    RTSpinlockReleaseNoInts(pDevExt->SessionSpinlock, &Tmp);
     1187    if (RT_UNLIKELY(i >= RT_ELEMENTS(pSession->aHGCMClientIds)))
     1188    {
     1189        static unsigned s_cErrors = 0;
     1190        if (s_cErrors++ > 32)
     1191            LogRel(("VBoxGuestCommonIOCtl: HGCM_CALL: Invalid handle. u32Client=%RX32\n", u32ClientId));
     1192        return VERR_INVALID_HANDLE;
     1193    }
     1194
     1195    /*
     1196     * The VbglHGCMCall call will invoke the callback if the HGCM
     1197     * call is performed in an ASYNC fashion. This function can
     1198     * deal with cancelled requests, so we let user more requests
     1199     * be interruptible (should add a flag for this later I guess).
     1200     */
     1201    Log(("VBoxGuestCommonIOCtl: HGCM_CALL: u32Client=%RX32\n", pInfo->u32ClientID));
     1202    int rc = VbglHGCMCall(pInfo, VBoxGuestHGCMAsyncWaitCallbackTimeout, pDevExt, pInfoTimeout->u32Timeout);
     1203    if (RT_SUCCESS(rc))
     1204    {
     1205        Log(("VBoxGuestCommonIOCtl: HGCM_CALL: result=%Rrc\n", pInfo->result));
     1206        if (pcbDataReturned)
     1207            *pcbDataReturned = cbActual;
     1208    }
     1209    Log(("VBoxGuestCommonIOCtl: HGCM_CALL: Failed. rc=%Rrc.\n", rc));
     1210    return rc;
     1211}
     1212#endif /* HGCM_TIMEOUT */
     1213
     1214
    10811215/**
    10821216 * @returns VBox status code. Unlike the other HGCM IOCtls this will combine
     
    12231357#ifdef VBOX_WITH_HGCM
    12241358    /*
    1225      * This one is tricky and can be done later.
     1359     * These ones are tricky and can be done later.
    12261360     */
    12271361    else if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_HGCM_CALL(0)))
     
    12301364        rc = VBoxGuestCommonIOCtl_HGCMCall(pDevExt, pSession, (VBoxGuestHGCMCallInfo *)pvData, cbData, pcbDataReturned);
    12311365    }
     1366#ifdef HGCM_TIMEOUT
     1367    else if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_HGCM_CALL_TIMEOUT(0)))
     1368    {
     1369        CHECKRET_MIN_SIZE("HGCM_CALL", sizeof(VBoxGuestHGCMCallInfoTimeout));
     1370        rc = VBoxGuestCommonIOCtl_HGCMCallTimeout(pDevExt, pSession, (VBoxGuestHGCMCallInfoTimeout *)pvData, cbData, pcbDataReturned);
     1371    }
     1372#endif /* HGCM_TIMEOUT */
    12321373#endif /* VBOX_WITH_HGCM */
    12331374    else if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_LOG(0)))
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette