VirtualBox

Changeset 21506 in vbox


Ignore:
Timestamp:
Jul 10, 2009 11:54:26 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
49956
Message:

VBoxGuest,VMMDev: New HGCM cancellation request.

Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/VBoxGuestLib.h

    r21461 r21506  
    166166 * completion IRQ is required.
    167167 *
    168  * @param pvData     VBoxGuest pointer to be passed to callback.
    169  * @param u32Data    VBoxGuest 32 bit value to be passed to callback.
    170  */
    171 
    172 typedef DECLVBGL(void) VBGLHGCMCALLBACK(VMMDevHGCMRequestHeader *pHeader, void *pvData, uint32_t u32Data);
     168 * @returns VINF_SUCCESS, VERR_INTERRUPT or VERR_TIMEOUT.
     169 * @param   pvData      VBoxGuest pointer to be passed to callback.
     170 * @param   u32Data     VBoxGuest 32 bit value to be passed to callback.
     171 */
     172typedef DECLVBGL(int) FNVBGLHGCMCALLBACK(VMMDevHGCMRequestHeader *pHeader, void *pvData, uint32_t u32Data);
     173/** Pointer to a FNVBGLHGCMCALLBACK. */
     174typedef FNVBGLHGCMCALLBACK *PFNVBGLHGCMCALLBACK;
    173175
    174176/**
     
    178180 * @note This function can NOT handle cancelled requests!
    179181 *
    180  * @param pConnectInfo    The request data.
    181  * @param pAsyncCallback  Required pointer to function that is called when
    182  *                        host returns VINF_HGCM_ASYNC_EXECUTE. VBoxGuest
    183  *                        implements waiting for an IRQ in this function.
    184  * @param pvAsyncData     An arbitrary VBoxGuest pointer to be passed to callback.
    185  * @param u32AsyncData    An arbitrary VBoxGuest 32 bit value to be passed to callback.
    186  *
    187  * @return VBox status code.
     182 * @param   pConnectInfo        The request data.
     183 * @param   pfnAsyncCallback    Required pointer to function that is calledwhen
     184 *                              host returns VINF_HGCM_ASYNC_EXECUTE. VBoxGuest
     185 *                              implements waiting for an IRQ in this function.
     186 * @param   pvAsyncData         An arbitrary VBoxGuest pointer to be passed to callback.
     187 * @param   u32AsyncData        An arbitrary VBoxGuest 32 bit value to be passed to callback.
     188 *
     189 * @return  VBox status code.
    188190 */
    189191
    190192DECLR0VBGL(int) VbglR0HGCMInternalConnect (VBoxGuestHGCMConnectInfo *pConnectInfo,
    191                                            VBGLHGCMCALLBACK *pAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);
     193                                           PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);
    192194
    193195
     
    198200 * @note This function can NOT handle cancelled requests!
    199201 *
    200  * @param pDisconnectInfo The request data.
    201  * @param pAsyncCallback  Required pointer to function that is called when
    202  *                        host returns VINF_HGCM_ASYNC_EXECUTE. VBoxGuest
    203  *                        implements waiting for an IRQ in this function.
    204  * @param pvAsyncData     An arbitrary VBoxGuest pointer to be passed to callback.
    205  * @param u32AsyncData    An arbitrary VBoxGuest 32 bit value to be passed to callback.
    206  *
    207  * @return VBox status code.
     202 * @param   pDisconnectInfo     The request data.
     203 * @param   pfnAsyncCallback    Required pointer to function that is called when
     204 *                              host returns VINF_HGCM_ASYNC_EXECUTE. VBoxGuest
     205 *                              implements waiting for an IRQ in this function.
     206 * @param   pvAsyncData         An arbitrary VBoxGuest pointer to be passed to callback.
     207 * @param   u32AsyncData        An arbitrary VBoxGuest 32 bit value to be passed to
     208 *                              callback.
     209 *
     210 * @return  VBox status code.
    208211 */
    209212
    210213DECLR0VBGL(int) VbglR0HGCMInternalDisconnect (VBoxGuestHGCMDisconnectInfo *pDisconnectInfo,
    211                                               VBGLHGCMCALLBACK *pAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);
     214                                              PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);
    212215
    213216/** Call a HGCM service.
     
    215218 * @note This function can deal with cancelled requests.
    216219 *
    217  * @param pCallInfo       The request data.
    218  * @param fFlags          Flags, see VBGLR0_HGCMCALL_F_XXX.
    219  * @param pAsyncCallback  Required pointer to function that is called when
    220  *                        host returns VINF_HGCM_ASYNC_EXECUTE. VBoxGuest
    221  *                        implements waiting for an IRQ in this function.
    222  * @param pvAsyncData     An arbitrary VBoxGuest pointer to be passed to callback.
    223  * @param u32AsyncData    An arbitrary VBoxGuest 32 bit value to be passed to callback.
     220 * @param   pCallInfo           The request data.
     221 * @param   fFlags              Flags, see VBGLR0_HGCMCALL_F_XXX.
     222 * @param   pfnAsyncCallback    Required pointer to function that is called when
     223 *                              host returns VINF_HGCM_ASYNC_EXECUTE. VBoxGuest
     224 *                              implements waiting for an IRQ in this function.
     225 * @param   pvAsyncData         An arbitrary VBoxGuest pointer to be passed to callback.
     226 * @param   u32AsyncData        An arbitrary VBoxGuest 32 bit value to be passed to callback.
    224227 *
    225228 * @return VBox status code.
    226229 */
    227230DECLR0VBGL(int) VbglR0HGCMInternalCall (VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
    228                                         VBGLHGCMCALLBACK *pAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);
     231                                        PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);
    229232
    230233/** Call a HGCM service. (32 bits packet structure in a 64 bits guest)
     
    232235 * @note This function can deal with cancelled requests.
    233236 *
    234  * @param pCallInfo       The request data.
    235  * @param fFlags          Flags, see VBGLR0_HGCMCALL_F_XXX.
    236  * @param pAsyncCallback  Required pointer to function that is called when
    237  *                        host returns VINF_HGCM_ASYNC_EXECUTE. VBoxGuest
    238  *                        implements waiting for an IRQ in this function.
    239  * @param pvAsyncData     An arbitrary VBoxGuest pointer to be passed to callback.
    240  * @param u32AsyncData    An arbitrary VBoxGuest 32 bit value to be passed to callback.
    241  *
    242  * @return VBox status code.
     237 * @param   pCallInfo           The request data.
     238 * @param   fFlags              Flags, see VBGLR0_HGCMCALL_F_XXX.
     239 * @param   pfnAsyncCallback    Required pointer to function that is called when
     240 *                              host returns VINF_HGCM_ASYNC_EXECUTE. VBoxGuest
     241 *                              implements waiting for an IRQ in this function.
     242 * @param   pvAsyncData         An arbitrary VBoxGuest pointer to be passed to callback.
     243 * @param   u32AsyncData        An arbitrary VBoxGuest 32 bit value to be passed to callback.
     244 *
     245 * @return  VBox status code.
    243246 */
    244247DECLR0VBGL(int) VbglR0HGCMInternalCall32 (VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
    245                                           VBGLHGCMCALLBACK *pAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);
     248                                          PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);
    246249
    247250/** @name VbglR0HGCMInternalCall flags
  • trunk/include/VBox/VMMDev.h

    r21488 r21506  
    151151#endif /* VBOX_WITH_64_BITS_GUESTS */
    152152    VMMDevReq_HGCMCancel                 = 64,
     153    VMMDevReq_HGCMCancel2                = 65,
    153154#endif
    154155    VMMDevReq_VideoAccelEnable           = 70,
     
    953954 * @{
    954955 */
    955 # define VBOX_HGCM_REQ_DONE      (0x1)
     956# define VBOX_HGCM_REQ_DONE      RT_BIT_32(VBOX_HGCM_REQ_DONE_BIT)
     957# define VBOX_HGCM_REQ_DONE_BIT  0
    956958# define VBOX_HGCM_REQ_CANCELLED (0x2)
    957959/** @} */
     
    13321334} VMMDevHGCMCancel;
    13331335AssertCompileSize(VMMDevHGCMCancel, 32);
     1336
     1337/**
     1338 * HGCM cancel request structure, version 2.
     1339 *
     1340 * Used by VMMDevReq_HGCMCancel2.
     1341 *
     1342 * VINF_SUCCESS when cancelled.
     1343 * VERR_NOT_FOUND if the specified request cannot be found.
     1344 * VERR_INVALID_PARAMETER if the address is invalid valid.
     1345 */
     1346typedef struct
     1347{
     1348    /** Header. */
     1349    VMMDevRequestHeader header;
     1350    /** The physical address of the request to cancel. */
     1351    RTGCPHYS32 physReqToCancel;
     1352} VMMDevHGCMCancel2;
     1353AssertCompileSize(VMMDevHGCMCancel2, 24+4);
    13341354
    13351355#endif /* VBOX_WITH_HGCM */
  • trunk/src/VBox/Additions/WINNT/VBoxGuest/VBoxGuest.cpp

    r21456 r21506  
    454454}
    455455
    456 DECLVBGL(void) VBoxHGCMCallback (VMMDevHGCMRequestHeader *pHeader, void *pvData, uint32_t u32Data)
     456DECLVBGL(int) VBoxHGCMCallback (VMMDevHGCMRequestHeader *pHeader, void *pvData, uint32_t u32Data)
    457457{
    458458    PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pvData;
     
    460460    dprintf(("VBoxHGCMCallback\n"));
    461461    VBoxHGCMCallbackWorker (pHeader, pDevExt, u32Data, false, UserMode);
    462 }
    463 
    464 DECLVBGL(void) VBoxHGCMCallbackKernelMode (VMMDevHGCMRequestHeader *pHeader, void *pvData, uint32_t u32Data)
     462    return VINF_SUCCESS;
     463}
     464
     465DECLVBGL(int) VBoxHGCMCallbackKernelMode (VMMDevHGCMRequestHeader *pHeader, void *pvData, uint32_t u32Data)
    465466{
    466467    PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pvData;
     
    468469    dprintf(("VBoxHGCMCallback\n"));
    469470    VBoxHGCMCallbackWorker (pHeader, pDevExt, u32Data, false, KernelMode);
     471    return VINF_SUCCESS;
    470472}
    471473
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp

    r21498 r21506  
    4646*******************************************************************************/
    4747#ifdef VBOX_WITH_HGCM
    48 static DECLCALLBACK(void) VBoxGuestHGCMAsyncWaitCallback(VMMDevHGCMRequestHeader *pHdrNonVolatile, void *pvUser, uint32_t u32User);
     48static DECLCALLBACK(int) VBoxGuestHGCMAsyncWaitCallback(VMMDevHGCMRequestHeader *pHdrNonVolatile, void *pvUser, uint32_t u32User);
    4949#endif
    5050
     
    10491049
    10501050/** Worker for VBoxGuestHGCMAsyncWaitCallback*. */
    1051 static void VBoxGuestHGCMAsyncWaitCallbackWorker(VMMDevHGCMRequestHeader volatile *pHdr, PVBOXGUESTDEVEXT pDevExt,
     1051static int VBoxGuestHGCMAsyncWaitCallbackWorker(VMMDevHGCMRequestHeader volatile *pHdr, PVBOXGUESTDEVEXT pDevExt,
    10521052                                                 bool fInterruptible, uint32_t cMillies)
    10531053{
     
    10681068        {
    10691069            RTSpinlockReleaseNoInts(pDevExt->EventSpinlock, &Tmp);
    1070             return;
     1070            return VINF_SUCCESS;
    10711071        }
    10721072        RTSpinlockReleaseNoInts(pDevExt->EventSpinlock, &Tmp);
     
    10761076            break;
    10771077        if (fInterruptible)
    1078             return;
     1078            return VERR_INTERRUPTED;
    10791079        RTThreadSleep(1);
    10801080    }
     
    10921092        VBoxGuestWaitFreeLocked(pDevExt, pWait);
    10931093        RTSpinlockReleaseNoInts(pDevExt->EventSpinlock, &Tmp);
    1094         return;
     1094        return VINF_SUCCESS;
    10951095    }
    10961096    VBoxGuestWaitAppend(&pDevExt->HGCMWaitList, pWait);
     
    11021102    else
    11031103        rc = RTSemEventMultiWait(pWait->Event, cMillies);
    1104 
    1105     /*
    1106      * This shouldn't ever return failure...
     1104    if (rc == VERR_SEM_DESTROYED)
     1105        return rc;
     1106
     1107    /*
    11071108     * Unlink, free and return.
    11081109     */
    1109     if (rc == VERR_SEM_DESTROYED)
    1110         return;
    1111     if (RT_FAILURE(rc))
     1110    if (    RT_FAILURE(rc)
     1111        &&  rc != VERR_TIMEOUT
     1112        &&  (    !fInterruptible
     1113             ||  rc != VERR_INTERRUPTED))
    11121114        LogRel(("VBoxGuestHGCMAsyncWaitCallback: wait failed! %Rrc\n", rc));
    11131115
     
    11161118    VBoxGuestWaitFreeLocked(pDevExt, pWait);
    11171119    RTSpinlockReleaseNoInts(pDevExt->EventSpinlock, &Tmp);
     1120    return rc;
    11181121}
    11191122
     
    11241127 * It operates in a manner similar to VBoxGuestCommonIOCtl_WaitEvent.
    11251128 */
    1126 static DECLCALLBACK(void) VBoxGuestHGCMAsyncWaitCallback(VMMDevHGCMRequestHeader *pHdr, void *pvUser, uint32_t u32User)
     1129static DECLCALLBACK(int) VBoxGuestHGCMAsyncWaitCallback(VMMDevHGCMRequestHeader *pHdr, void *pvUser, uint32_t u32User)
    11271130{
    11281131    PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pvUser;
    11291132    Log(("VBoxGuestHGCMAsyncWaitCallback: requestType=%d\n", pHdr->header.requestType));
    1130     VBoxGuestHGCMAsyncWaitCallbackWorker((VMMDevHGCMRequestHeader volatile *)pHdr,
    1131                                          pDevExt,
    1132                                          false /* fInterruptible */,
    1133                                          u32User  /* cMillies */);
     1133    return VBoxGuestHGCMAsyncWaitCallbackWorker((VMMDevHGCMRequestHeader volatile *)pHdr,
     1134                                                pDevExt,
     1135                                                false /* fInterruptible */,
     1136                                                u32User  /* cMillies */);
    11341137}
    11351138
     
    11401143 * It operates in a manner similar to VBoxGuestCommonIOCtl_WaitEvent.
    11411144 */
    1142 static DECLCALLBACK(void) VBoxGuestHGCMAsyncWaitCallbackInterruptible(VMMDevHGCMRequestHeader *pHdr,
     1145static DECLCALLBACK(int) VBoxGuestHGCMAsyncWaitCallbackInterruptible(VMMDevHGCMRequestHeader *pHdr,
    11431146                                                                      void *pvUser, uint32_t u32User)
    11441147{
    11451148    PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pvUser;
    11461149    Log(("VBoxGuestHGCMAsyncWaitCallbackInterruptible: requestType=%d\n", pHdr->header.requestType));
    1147     VBoxGuestHGCMAsyncWaitCallbackWorker((VMMDevHGCMRequestHeader volatile *)pHdr,
    1148                                          pDevExt,
    1149                                          true /* fInterruptible */,
    1150                                          u32User /* cMillies */ );
     1150    return VBoxGuestHGCMAsyncWaitCallbackWorker((VMMDevHGCMRequestHeader volatile *)pHdr,
     1151                                                pDevExt,
     1152                                                true /* fInterruptible */,
     1153                                                u32User /* cMillies */ );
     1154
    11511155}
    11521156
  • trunk/src/VBox/Additions/common/VBoxGuest/linux/Makefile

    r21337 r21506  
    9292        r0drv/linux/spinlock-r0drv-linux.o \
    9393        r0drv/linux/thread-r0drv-linux.o \
     94        r0drv/linux/time-r0drv-linux.o \
    9495        r0drv/linux/RTLogWriteDebugger-r0drv-linux.o \
    9596        common/err/RTErrConvertFromErrno.o \
  • trunk/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest

    r21337 r21506  
    125125    ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h=>r0drv/linux/the-linux-kernel.h \
    126126    ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/thread-r0drv-linux.c=>r0drv/linux/thread-r0drv-linux.c \
     127    ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c=>r0drv/linux/time-r0drv-linux.c \
    127128    ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/RTLogWriteDebugger-r0drv-linux.c=>r0drv/linux/RTLogWriteDebugger-r0drv-linux.c \
    128129    ${PATH_ROOT}/src/VBox/Runtime/VBox/log-vbox.cpp=>VBox/log-vbox.c \
     
    134135FILES_VBOXGUEST_BIN=" \
    135136"
     137
  • trunk/src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp

    r21489 r21506  
    2828#include "VBGLInternal.h"
    2929#include <iprt/alloca.h>
     30#include <iprt/asm.h>
    3031#include <iprt/assert.h>
    3132#include <iprt/mem.h>
    3233#include <iprt/memobj.h>
    3334#include <iprt/string.h>
     35#include <iprt/thread.h>
     36#include <iprt/time.h>
     37
    3438
    3539/*******************************************************************************
     
    4650#endif
    4751
     52
    4853/*******************************************************************************
    4954*   Structures and Typedefs                                                    *
     
    7075
    7176DECLVBGL(int) VbglR0HGCMInternalConnect (VBoxGuestHGCMConnectInfo *pConnectInfo,
    72                                          VBGLHGCMCALLBACK *pAsyncCallback, void *pvAsyncData,
    73                                          uint32_t u32AsyncData)
     77                                         PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
    7478{
    7579    VMMDevHGCMConnect *pHGCMConnect;
    7680    int rc;
    7781
    78     if (!pConnectInfo || !pAsyncCallback)
     82    if (!pConnectInfo || !pfnAsyncCallback)
    7983        return VERR_INVALID_PARAMETER;
    8084
     
    101105            {
    102106                /* Wait for request completion interrupt notification from host */
    103                 pAsyncCallback (&pHGCMConnect->header, pvAsyncData, u32AsyncData);
     107                pfnAsyncCallback (&pHGCMConnect->header, pvAsyncData, u32AsyncData);
    104108            }
    105109
     
    118122
    119123DECLR0VBGL(int) VbglR0HGCMInternalDisconnect (VBoxGuestHGCMDisconnectInfo *pDisconnectInfo,
    120                                               VBGLHGCMCALLBACK *pAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
     124                                              PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
    121125{
    122126    VMMDevHGCMDisconnect *pHGCMDisconnect;
    123127    int rc;
    124128
    125     if (!pDisconnectInfo || !pAsyncCallback)
     129    if (!pDisconnectInfo || !pfnAsyncCallback)
    126130        return VERR_INVALID_PARAMETER;
    127131
     
    147151            {
    148152                /* Wait for request completion interrupt notification from host */
    149                 pAsyncCallback (&pHGCMDisconnect->header, pvAsyncData, u32AsyncData);
     153                pfnAsyncCallback (&pHGCMDisconnect->header, pvAsyncData, u32AsyncData);
    150154            }
    151155
     
    609613 * @param   pvAsyncData         Argument for the callback.
    610614 * @param   u32AsyncData        Argument for the callback.
     615 * @param   pfLeakIt            Where to return the leak it / free it,
     616 *                              indicator. Cancellation fun.
    611617 */
    612 static int vbglR0HGCMInternalDoCall(VMMDevHGCMCall *pHGCMCall, VBGLHGCMCALLBACK *pfnAsyncCallback,
    613                                     void *pvAsyncData, uint32_t u32AsyncData)
     618static int vbglR0HGCMInternalDoCall(VMMDevHGCMCall *pHGCMCall, PFNVBGLHGCMCALLBACK pfnAsyncCallback,
     619                                    void *pvAsyncData, uint32_t u32AsyncData, bool *pfLeakIt)
    614620{
    615621    int rc;
     
    634640     * if so, we wait for it to complete using the caller supplied callback.
    635641     */
    636     if (    RT_SUCCESS(rc)
    637         &&  rc == VINF_HGCM_ASYNC_EXECUTE)
     642    *pfLeakIt = false;
     643    if (rc == VINF_HGCM_ASYNC_EXECUTE)
    638644    {
    639645        Log(("Processing HGCM call asynchronously\n"));
    640         /** @todo timeout vs. interrupted. */
    641         pfnAsyncCallback(&pHGCMCall->header, pvAsyncData, u32AsyncData);
    642 
    643         /*
    644          * If the request isn't completed by the time the callback returns
    645          * we will have to try cancel it.
    646          */
    647         if (!(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE))
     646        rc = pfnAsyncCallback(&pHGCMCall->header, pvAsyncData, u32AsyncData);
     647        if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE)
    648648        {
    649             /** @todo use a new request for this! See @bugref{4052}. */
    650             pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED;
    651             pHGCMCall->header.header.requestType = VMMDevReq_HGCMCancel;
    652             VbglGRPerform(&pHGCMCall->header.header);
    653             rc = VERR_INTERRUPTED;
     649            Assert(!(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_CANCELLED));
     650            rc = VINF_SUCCESS;
    654651        }
    655     }
    656 
    657     Log(("GstHGCMCall: rc=%Rrc result=%Rrc fu32Flags=%#x\n", rc, pHGCMCall->header.result, pHGCMCall->header.fu32Flags));
     652        else
     653        {
     654            /*
     655             * The request didn't complete in time or the call was interrupted,
     656             * the RC from the callback indicates which. Try cancel the request.
     657             *
     658             * This is a bit messy because we're racing request completion. Sorry.
     659             */
     660            /** @todo It would be nice if we could use the waiter callback to do further
     661             *  waiting in case of a completion race. If it wasn't for WINNT having its own
     662             *  version of all that stuff, I would've done it already. */
     663            VMMDevHGCMCancel2 *pCancelReq;
     664            int rc2 = VbglGRAlloc((VMMDevRequestHeader **)&pCancelReq, sizeof(*pCancelReq), VMMDevReq_HGCMCancel2);
     665            if (RT_SUCCESS(rc2))
     666            {
     667                pCancelReq->physReqToCancel = VbglPhysHeapGetPhysAddr(pHGCMCall);
     668                rc2 = VbglGRPerform(&pCancelReq->header);
     669                VbglGRFree(&pCancelReq->header);
     670            }
     671#if 1 /** @todo ADDVER: Remove this on next minor version change. */
     672            if (rc2 == VERR_NOT_IMPLEMENTED)
     673            {
     674                /* host is too old, or we're out of heap. */
     675                pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED;
     676                pHGCMCall->header.header.requestType = VMMDevReq_HGCMCancel;
     677                rc2 = VbglGRPerform(&pHGCMCall->header.header);
     678                if (rc2 == VERR_INVALID_PARAMETER)
     679                    rc2 = VERR_NOT_FOUND;
     680                else if (RT_SUCCESS(rc))
     681                    RTThreadSleep(1);
     682            }
     683#endif
     684            if (RT_SUCCESS(rc)) rc = VERR_INTERRUPTED; /** @todo weed this out from the WINNT VBoxGuest code. */
     685            if (RT_SUCCESS(rc2))
     686            {
     687                Log(("vbglR0HGCMInternalDoCall: successfully cancelled\n"));
     688                pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED;
     689            }
     690            else
     691            {
     692                /*
     693                 * Wait for a bit while the host (hopefully) completes it.
     694                 */
     695                uint64_t u64Start       = RTTimeSystemMilliTS();
     696                uint32_t cMilliesToWait = rc2 == VERR_NOT_FOUND || rc2 == VERR_SEM_DESTROYED ? 500 : 2000;
     697                uint64_t cElapsed       = 0;
     698                if (rc2 != VERR_NOT_FOUND)
     699                    LogRel(("vbglR0HGCMInternalDoCall: Failed to cancel the HGCM call on %Rrc: rc2=%Rrc\n", rc, rc2));
     700                else
     701                    Log(("vbglR0HGCMInternalDoCall: Cancel race rc=%Rrc rc2=%Rrc\n", rc, rc2));
     702
     703                do
     704                {
     705                    ASMCompilerBarrier();       /* paranoia */
     706                    if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE)
     707                        break;
     708                    RTThreadSleep(1);
     709                    cElapsed = RTTimeSystemMilliTS() - u64Start;
     710                } while (cElapsed < cMilliesToWait);
     711
     712                ASMCompilerBarrier();           /* paranoia^2 */
     713                if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE)
     714                    rc = VINF_SUCCESS;
     715                else
     716                {
     717                    LogRel(("vbglR0HGCMInternalDoCall: Leaking %u bytes. Pending call to %u with %u parms. (rc2=%Rrc)\n",
     718                            pHGCMCall->header.header.size, pHGCMCall->u32Function, pHGCMCall->cParms, rc2));
     719                    *pfLeakIt = true;
     720                }
     721                Log(("vbglR0HGCMInternalDoCall: Cancel race ended with rc=%Rrc (rc2=%Rrc) after %llu ms\n", rc, rc2, cElapsed));
     722            }
     723        }
     724    }
     725
     726    Log(("GstHGCMCall: rc=%Rrc result=%Rrc fu32Flags=%#x fLeakIt=%d\n",
     727         rc, pHGCMCall->header.result, pHGCMCall->header.fu32Flags, *pfLeakIt));
    658728    return rc;
    659729}
     
    767837
    768838DECLR0VBGL(int) VbglR0HGCMInternalCall(VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
    769                                        VBGLHGCMCALLBACK *pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
     839                                       PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
    770840{
    771841    bool                    fIsUser = (fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER;
     
    806876        if (RT_SUCCESS(rc))
    807877        {
     878            bool fLeakIt;
    808879            vbglR0HGCMInternalInitCall(pHGCMCall, pCallInfo, cbCallInfo, fIsUser, &ParmInfo);
    809880
     
    811882             * Perform the call.
    812883             */
    813             rc = vbglR0HGCMInternalDoCall(pHGCMCall, pfnAsyncCallback, pvAsyncData, u32AsyncData);
     884            rc = vbglR0HGCMInternalDoCall(pHGCMCall, pfnAsyncCallback, pvAsyncData, u32AsyncData, &fLeakIt);
    814885            if (RT_SUCCESS(rc))
    815886            {
     
    820891            }
    821892
    822             VbglGRFree(&pHGCMCall->header.header);
     893            if (!fLeakIt)
     894                VbglGRFree(&pHGCMCall->header.header);
    823895        }
    824896    }
     
    842914#if ARCH_BITS == 64
    843915DECLR0VBGL(int) VbglR0HGCMInternalCall32(VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,
    844                                          VBGLHGCMCALLBACK *pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
     916                                         PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData)
    845917{
    846918    VBoxGuestHGCMCallInfo   *pCallInfo64;
     
    858930                    ||  pCallInfo->cParms > VBOX_HGCM_MAX_PARMS
    859931                    || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK),
    860                     ("pCallInfo=%p pAsyncCallback=%p fFlags=%#x\n", pCallInfo, pfnAsyncCallback, fFlags),
     932                    ("pCallInfo=%p pfnAsyncCallback=%p fFlags=%#x\n", pCallInfo, pfnAsyncCallback, fFlags),
    861933                    VERR_INVALID_PARAMETER);
    862934    AssertReturn(   cbCallInfo >= sizeof(VBoxGuestHGCMCallInfo)
  • trunk/src/VBox/Devices/VMMDev/VMMDev.cpp

    r21460 r21506  
    11371137        }
    11381138
     1139        case VMMDevReq_HGCMCancel2:
     1140        {
     1141            if (pRequestHeader->size != sizeof(VMMDevHGCMCancel2))
     1142            {
     1143                AssertMsgFailed(("VMMDevReq_HGCMCancel structure has invalid size!\n"));
     1144                pRequestHeader->rc = VERR_INVALID_PARAMETER;
     1145            }
     1146            else if (!pThis->pHGCMDrv)
     1147            {
     1148                Log(("VMMDevReq_HGCMCancel HGCM Connector is NULL!\n"));
     1149                pRequestHeader->rc = VERR_NOT_SUPPORTED;
     1150            }
     1151            else
     1152            {
     1153                VMMDevHGCMCancel2 *pHGCMCancel2 = (VMMDevHGCMCancel2 *)pRequestHeader;
     1154
     1155                Log(("VMMDevReq_VMMDevHGCMCancel\n"));
     1156                pRequestHeader->rc = vmmdevHGCMCancel2 (pThis, pHGCMCancel2->physReqToCancel);
     1157            }
     1158            break;
     1159        }
     1160
    11391161        case VMMDevReq_VideoAccelEnable:
    11401162        {
     
    15871609            else
    15881610            {
    1589                 VMMDevReqLogString *pReqLogString = (VMMDevReqLogString*)pRequestHeader;
    1590 #undef LOG_GROUP
    1591 #define LOG_GROUP LOG_GROUP_DEV_VMM_BACKDOOR
    1592 //                Log(("Guest Log: %s", pReqLogString->szString));
    1593                 Log(("DEBUG LOG: %s", pReqLogString->szString));
    1594 
    1595 #undef LOG_GROUP
    1596 #define LOG_GROUP LOG_GROUP_DEV_VMM
     1611                VMMDevReqLogString *pReqLogString = (VMMDevReqLogString *)pRequestHeader;
     1612                LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_LEVEL_1, LOG_GROUP_DEV_VMM_BACKDOOR,
     1613                      ("DEBUG LOG: %s", pReqLogString->szString));
    15971614                pRequestHeader->rc = VINF_SUCCESS;
    15981615            }
  • trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp

    r21458 r21506  
    199199
    200200
    201 static PVBOXHGCMCMD vmmdevHGCMFindCommand (VMMDevState *pVMMDevState, RTGCPHYS GCPhys)
    202 {
    203     PVBOXHGCMCMD pCmd = NULL;
    204 
    205     int rc = vmmdevHGCMCmdListLock (pVMMDevState);
    206 
    207     if (RT_SUCCESS (rc))
    208     {
    209         pCmd = pVMMDevState->pHGCMCmdList;
    210 
    211         while (pCmd)
    212         {
    213             if (pCmd->GCPhys == GCPhys)
    214             {
    215                 break;
    216             }
    217             pCmd = pCmd->pNext;
    218         }
    219 
    220         vmmdevHGCMCmdListUnlock (pVMMDevState);
    221     }
    222 
    223     LogFlowFunc(("%p\n", pCmd));
    224     return pCmd;
     201/**
     202 * Find a HGCM command by its physical address.
     203 *
     204 * The caller is responsible for taking the command list lock before calling
     205 * this function.
     206 *
     207 * @returns Pointer to the command on success, NULL otherwise.
     208 * @param   pThis           The VMMDev instance data.
     209 * @param   GCPhys          The physical address of the command we're looking
     210 *                          for.
     211 */
     212DECLINLINE(PVBOXHGCMCMD) vmmdevHGCMFindCommandLocked (VMMDevState *pThis, RTGCPHYS GCPhys)
     213{
     214    for (PVBOXHGCMCMD pCmd = pThis->pHGCMCmdList;
     215         pCmd;
     216         pCmd = pCmd->pNext)
     217    {
     218         if (pCmd->GCPhys == GCPhys)
     219             return pCmd;
     220    }
     221    return NULL;
    225222}
    226 
    227223
    228224static int vmmdevHGCMSaveLinPtr (PPDMDEVINS pDevIns,
     
    10051001
    10061002        /* Pass the function call to HGCM connector for actual processing */
    1007         rc = pVMMDevState->pHGCMDrv->pfnCall (pVMMDevState->pHGCMDrv, pCmd, pHGCMCall->u32ClientID, pHGCMCall->u32Function, cParms, pCmd->paHostParms);
     1003        rc = pVMMDevState->pHGCMDrv->pfnCall (pVMMDevState->pHGCMDrv, pCmd, pHGCMCall->u32ClientID,
     1004                                              pHGCMCall->u32Function, cParms, pCmd->paHostParms);
    10081005    }
    10091006    else
     
    14481445}
    14491446
    1450 /* @thread EMT */
     1447/**
     1448 * VMMDevReq_HGCMCancel worker.
     1449 *
     1450 * @thread EMT
     1451 */
    14511452int vmmdevHGCMCancel (VMMDevState *pVMMDevState, VMMDevHGCMCancel *pHGCMCancel, RTGCPHYS GCPhys)
    14521453{
    1453     int rc = VINF_SUCCESS;
    1454 
    14551454    NOREF(pHGCMCancel);
    1456 
    1457     Log(("vmmdevHGCMCancel\n"));
    1458 
    1459     /* Find the command in the list. */
    1460     PVBOXHGCMCMD pCmd = vmmdevHGCMFindCommand (pVMMDevState, GCPhys);
    1461 
     1455    int rc = vmmdevHGCMCancel2(pVMMDevState, GCPhys);
     1456    return rc == VERR_NOT_FOUND ? VERR_INVALID_PARAMETER : rc;
     1457}
     1458
     1459/**
     1460 * VMMDevReq_HGCMCancel2 worker.
     1461 *
     1462 * @retval  VINF_SUCCESS on success.
     1463 * @retval  VERR_NOT_FOUND if the request was not found.
     1464 * @retval  VERR_INVALID_PARAMETER if the request address is invalid.
     1465 *
     1466 * @param   pThis       The VMMDev instance data.
     1467 * @param   GCPhys      The address of the request that should be cancelled.
     1468 *
     1469 * @thread EMT
     1470 */
     1471int vmmdevHGCMCancel2 (VMMDevState *pThis, RTGCPHYS GCPhys)
     1472{
     1473    if (    GCPhys == 0
     1474        ||  GCPhys == NIL_RTGCPHYS
     1475        ||  GCPhys == NIL_RTGCPHYS32)
     1476    {
     1477        Log(("vmmdevHGCMCancel2: GCPhys=%#x\n", GCPhys));
     1478        return VERR_INVALID_PARAMETER;
     1479    }
     1480
     1481    /*
     1482     * Locate the command and cancel it while under the protection of
     1483     * the lock. hgcmCompletedWorker makes assumptions about this.
     1484     */
     1485    int rc = vmmdevHGCMCmdListLock (pThis);
     1486    AssertRCReturn(rc, rc);
     1487
     1488    PVBOXHGCMCMD pCmd = vmmdevHGCMFindCommandLocked (pThis, GCPhys);
    14621489    if (pCmd)
    14631490    {
    14641491        pCmd->fCancelled = true;
     1492        Log(("vmmdevHGCMCancel2: Cancelled pCmd=%p / GCPhys=%#x\n", pCmd, GCPhys));
    14651493    }
    14661494    else
    1467     {
    1468         rc = VERR_INVALID_PARAMETER;
    1469     }
    1470 
     1495        rc = VERR_NOT_FOUND;
     1496
     1497    vmmdevHGCMCmdListUnlock (pThis);
    14711498    return rc;
    14721499}
     
    15291556    }
    15301557
    1531     /* Check whether the command has been already cancelled by the guest.
    1532      * If it was cancelled, then the data must not be written back to the
    1533      * guest RAM.
     1558    /*
     1559     * The cancellation protocol requires us to remove the command here
     1560     * and then check the flag. Cancelled commands must not be written
     1561     * back to guest memory.
    15341562     */
     1563    vmmdevHGCMRemoveCommand (pVMMDevState, pCmd);
     1564
    15351565    if (pCmd->fCancelled)
    15361566    {
    1537         /* Just remove the command from the internal list, so the memory can be freed. */
    15381567        LogFlowFunc(("A cancelled command %p\n", pCmd));
    1539         vmmdevHGCMRemoveCommand (pVMMDevState, pCmd);
    15401568    }
    15411569    else
     
    15571585        {
    15581586            pHeader = (VMMDevHGCMRequestHeader *)RTMemAlloc (pCmd->cbSize);
    1559             Assert(pHeader);
    15601587            if (pHeader == NULL)
    15611588            {
    1562                 LogRel(("VMMDev: Failed to allocate %d bytes for HGCM request completion!!!\n", pCmd->cbSize));
    1563 
    1564                 /* Do some cleanup. The command have to be excluded from list of active commands anyway. */
    1565                 vmmdevHGCMRemoveCommand (pVMMDevState, pCmd);
     1589                LogRel(("VMMDev: Failed to allocate %u bytes for HGCM request completion!!!\n", pCmd->cbSize));
     1590
     1591                /* Free it. The command have to be excluded from list of active commands anyway. */
     1592                RTMemFree (pCmd);
    15661593                return;
    15671594            }
     
    15781605         *        didn't have to mess around with PDMDevHlpPhysRead/Write. We're
    15791606         *        reading the header 3 times now and writing the request back twice. */
     1607
    15801608        PDMCritSectEnter(&pVMMDevState->CritSect, VERR_SEM_BUSY);
    15811609        PDMCritSectLeave(&pVMMDevState->CritSect);
     
    16351663                                {
    16361664                                    /* Use the saved page list to write data back to the guest RAM. */
    1637                                     rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr, size, iLinPtr, pCmd->paLinPtrs);
     1665                                    rc = vmmdevHGCMWriteLinPtr (pVMMDevState->pDevIns, i, pHostParm->u.pointer.addr,
     1666                                                                size, iLinPtr, pCmd->paLinPtrs);
    16381667                                    AssertReleaseRC(rc);
    16391668                                }
     
    19161945        /* Write back the request */
    19171946        PDMDevHlpPhysWrite(pVMMDevState->pDevIns, pCmd->GCPhys, pHeader, pCmd->cbSize);
    1918 
    1919         /* The command has been completely processed and can be removed from the list. */
    1920         vmmdevHGCMRemoveCommand (pVMMDevState, pCmd);
    19211947
    19221948        /* Now, when the command was removed from the internal list, notify the guest. */
  • trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.h

    r21456 r21506  
    3030DECLCALLBACK(int) vmmdevHGCMCall (VMMDevState *pVMMDevState, VMMDevHGCMCall *pHGCMCall, uint32_t cbHGCMCall, RTGCPHYS GCPtr, bool f64Bits);
    3131DECLCALLBACK(int) vmmdevHGCMCancel (VMMDevState *pVMMDevState, VMMDevHGCMCancel *pHGCMCancel, RTGCPHYS GCPtr);
     32DECLCALLBACK(int) vmmdevHGCMCancel2 (VMMDevState *pVMMDevState, RTGCPHYS GCPtr);
    3233
    3334DECLCALLBACK(void) hgcmCompleted (PPDMIHGCMPORT pInterface, int32_t result, PVBOXHGCMCMD pCmdPtr);
Note: See TracChangeset for help on using the changeset viewer.

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