VirtualBox

Changeset 58390 in vbox for trunk/src/VBox/Devices/GIMDev


Ignore:
Timestamp:
Oct 23, 2015 12:35:35 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
103627
Message:

VMM/GIM: Implement Hyper-V debug receive thread optimization. Added a few statistics to GIM.
Fixed a bug in Windows guests' debug DHCP handling.

Location:
trunk/src/VBox/Devices/GIMDev
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/GIMDev/DrvUDP.cpp

    r57989 r58390  
    8080    {
    8181        size_t cbReallyRead = 0;
    82         rc = RTSocketReadNB(pThis->hSocket, pvBuf, *pcbRead, &cbReallyRead);
     82        rc = RTSocketRead(pThis->hSocket, pvBuf, *pcbRead, &cbReallyRead);
    8383        if (RT_SUCCESS(rc))
    8484            *pcbRead = cbReallyRead;
     
    103103    if (pThis->hSocket != NIL_RTSOCKET)
    104104    {
    105         size_t cbReallyWritten = 0;
    106         rc = RTSocketWriteNB(pThis->hSocket, pvBuf, *pcbWrite, &cbReallyWritten);
     105        size_t cbBuf = *pcbWrite;
     106        rc = RTSocketWriteToNB(pThis->hSocket, pvBuf, cbBuf, NULL /*pDstAddr*/);
    107107        if (RT_SUCCESS(rc))
    108             *pcbWrite = cbReallyWritten;
     108            *pcbWrite = cbBuf;
    109109    }
    110110    else
     
    147147    if (pThis->hSocket != NIL_RTSOCKET)
    148148    {
     149        RTSocketRetain(pThis->hSocket);
     150        RTSocketShutdown(pThis->hSocket, true, true);
    149151        RTSocketClose(pThis->hSocket);
    150152        pThis->hSocket = NIL_RTSOCKET;
  • trunk/src/VBox/Devices/GIMDev/GIMDev.cpp

    r57989 r58390  
    2626
    2727#include "VBoxDD.h"
     28#include <iprt/alloc.h>
     29#include <iprt/semaphore.h>
    2830#include <iprt/uuid.h>
    2931
     
    5052    /** Pointer to the attached base debug driver. */
    5153    R3PTRTYPE(PPDMIBASE)            pDbgDrvBase;
    52     /** Pointer to the attached debug stream driver. */
    53     R3PTRTYPE(PPDMISTREAM)          pDbgDrvStream;
     54    /** The debug receive thread. */
     55    RTTHREAD                        hDbgRecvThread;
     56    /** Flag to indicate shutdown of the debug receive thread. */
     57    bool volatile                   fDbgRecvThreadShutdown;
     58    /** The debug setup parameters. */
     59    GIMDEBUGSETUP                   DbgSetup;
     60    /** The debug transfer struct. */
     61    GIMDEBUG                        Dbg;
    5462} GIMDEV;
    5563/** Pointer to the GIM device state. */
     
    7684
    7785
     86static DECLCALLBACK(int) gimDevR3DbgRecvThread(RTTHREAD ThreadSelf, void *pvUser)
     87{
     88    /*
     89     * Validate.
     90     */
     91    PPDMDEVINS pDevIns = (PPDMDEVINS)pvUser;
     92    AssertReturn(pDevIns, VERR_INVALID_PARAMETER);
     93    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
     94
     95    PGIMDEV pThis = PDMINS_2_DATA(pDevIns, PGIMDEV);
     96    AssertReturn(pThis, VERR_INVALID_POINTER);
     97    AssertReturn(pThis->DbgSetup.cbDbgRecvBuf, VERR_INTERNAL_ERROR);
     98    AssertReturn(pThis->Dbg.hDbgRecvThreadSem != NIL_RTSEMEVENTMULTI, VERR_INTERNAL_ERROR_2);
     99    AssertReturn(pThis->Dbg.pvDbgRecvBuf, VERR_INTERNAL_ERROR_3);
     100
     101    PVM pVM = PDMDevHlpGetVM(pDevIns);
     102    AssertReturn(pVM, VERR_INVALID_POINTER);
     103
     104    PPDMISTREAM pDbgDrvStream = pThis->Dbg.pDbgDrvStream;
     105    AssertReturn(pDbgDrvStream, VERR_INVALID_POINTER);
     106
     107    for (;;)
     108    {
     109        /*
     110         * Read incoming debug data.
     111         */
     112        size_t cbRead = pThis->DbgSetup.cbDbgRecvBuf;
     113        int rc = pDbgDrvStream->pfnRead(pDbgDrvStream, pThis->Dbg.pvDbgRecvBuf, &cbRead);
     114        if (   RT_SUCCESS(rc)
     115            && cbRead > 0)
     116        {
     117            /*
     118             * Notify the consumer thread.
     119             */
     120            if (ASMAtomicReadBool(&pThis->Dbg.fDbgRecvBufRead) == false)
     121            {
     122                if (pThis->DbgSetup.pfnDbgRecvBufAvail)
     123                    pThis->DbgSetup.pfnDbgRecvBufAvail(pVM);
     124                pThis->Dbg.cbDbgRecvBufRead = cbRead;
     125                RTSemEventMultiReset(pThis->Dbg.hDbgRecvThreadSem);
     126                ASMAtomicWriteBool(&pThis->Dbg.fDbgRecvBufRead, true);
     127            }
     128
     129            /*
     130             * Wait until the consumer thread has acknowledged reading of the
     131             * current buffer or we're asked to shut down.
     132             *
     133             * It is important that we do NOT re-invoke 'pfnRead' before the
     134             * current buffer is consumed, otherwise we risk data corruption.
     135             */
     136            while (   ASMAtomicReadBool(&pThis->Dbg.fDbgRecvBufRead) == true
     137                   && !pThis->fDbgRecvThreadShutdown)
     138            {
     139                RTSemEventMultiWait(pThis->Dbg.hDbgRecvThreadSem, RT_INDEFINITE_WAIT);
     140            }
     141        }
     142        else if (   rc != VINF_TRY_AGAIN
     143                 && rc != VERR_TRY_AGAIN)
     144        {
     145            LogRel(("GIMDev: Debug thread terminating with rc=%Rrc\n", rc));
     146            break;
     147        }
     148
     149        if (pThis->fDbgRecvThreadShutdown)
     150        {
     151            LogRel(("GIMDev: Debug thread shutting down\n"));
     152            break;
     153        }
     154    }
     155
     156    return VINF_SUCCESS;
     157}
     158
     159
    78160/**
    79161 * @interface_method_impl{PDMDEVREG,pfnConstruct}
     
    93175
    94176    /*
    95      * Attach the stream driver for the debug connection.
    96      */
    97     pThis->IDbgBase.pfnQueryInterface = gimdevR3QueryInterface;
    98     int rc = PDMDevHlpDriverAttach(pDevIns, GIMDEV_DEBUG_LUN, &pThis->IDbgBase, &pThis->pDbgDrvBase, "GIM Debug Port");
    99     if (RT_SUCCESS(rc))
    100     {
    101         pThis->pDbgDrvStream = PDMIBASE_QUERY_INTERFACE(pThis->pDbgDrvBase, PDMISTREAM);
    102         if (pThis->pDbgDrvStream)
    103             LogRel(("GIMDev: LUN#%u: Debug port configured\n", GIMDEV_DEBUG_LUN));
     177     * Get debug setup requirements from GIM.
     178     */
     179    PVM pVM = PDMDevHlpGetVM(pDevIns);
     180    int rc = GIMR3GetDebugSetup(pVM, &pThis->DbgSetup);
     181    if (   RT_SUCCESS(rc)
     182        && pThis->DbgSetup.cbDbgRecvBuf > 0)
     183    {
     184        /*
     185         * Attach the stream driver for the debug connection.
     186         */
     187        PPDMISTREAM pDbgDrvStream = NULL;
     188        pThis->IDbgBase.pfnQueryInterface = gimdevR3QueryInterface;
     189        rc = PDMDevHlpDriverAttach(pDevIns, GIMDEV_DEBUG_LUN, &pThis->IDbgBase, &pThis->pDbgDrvBase, "GIM Debug Port");
     190        if (RT_SUCCESS(rc))
     191        {
     192            pDbgDrvStream = PDMIBASE_QUERY_INTERFACE(pThis->pDbgDrvBase, PDMISTREAM);
     193            if (pDbgDrvStream)
     194                LogRel(("GIMDev: LUN#%u: Debug port configured\n", GIMDEV_DEBUG_LUN));
     195            else
     196                LogRel(("GIMDev: LUN#%u: No unit\n", GIMDEV_DEBUG_LUN));
     197        }
     198        else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
     199        {
     200            pThis->pDbgDrvBase = NULL;
     201            LogRel(("GIMDev: LUN#%u: No debug port configured\n", GIMDEV_DEBUG_LUN));
     202        }
    104203        else
    105             LogRel(("GIMDev: LUN#%u: No unit\n", GIMDEV_DEBUG_LUN));
    106     }
    107     else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
    108     {
    109         pThis->pDbgDrvBase   = NULL;
    110         pThis->pDbgDrvStream = NULL;
    111         LogRel(("GIMDev: LUN#%u: No debug port configured\n", GIMDEV_DEBUG_LUN));
    112     }
    113     else
    114     {
    115         AssertLogRelMsgFailed(("GIMDev: LUN#%u: Failed to attach to driver on debug port. rc=%Rrc\n", GIMDEV_DEBUG_LUN, rc));
    116         /* Don't call VMSetError here as we assume that the driver already set an appropriate error */
    117         return rc;
    118     }
    119 
    120     /*
    121      * Register ourselves with the GIM VMM component.
    122      */
    123     PVM pVM = PDMDevHlpGetVM(pDevIns);
    124     GIMR3GimDeviceRegister(pVM, pDevIns, pThis->pDbgDrvStream);
     204        {
     205            AssertLogRelMsgFailed(("GIMDev: LUN#%u: Failed to attach to driver on debug port. rc=%Rrc\n", GIMDEV_DEBUG_LUN, rc));
     206            /* Don't call VMSetError here as we assume that the driver already set an appropriate error */
     207            return rc;
     208        }
     209
     210        void *pvDbgRecvBuf = RTMemAllocZ(pThis->DbgSetup.cbDbgRecvBuf);
     211        if (RT_UNLIKELY(!pvDbgRecvBuf))
     212        {
     213            LogRel(("GIMDev: Failed to alloc %u bytes for debug receive buffer\n", pThis->DbgSetup.cbDbgRecvBuf));
     214            return VERR_NO_MEMORY;
     215        }
     216
     217        /*
     218         * Update the shared debug struct.
     219         */
     220        pThis->Dbg.pDbgDrvStream    = pDbgDrvStream;
     221        pThis->Dbg.pvDbgRecvBuf     = pvDbgRecvBuf;
     222        pThis->Dbg.cbDbgRecvBufRead = 0;
     223        pThis->Dbg.fDbgRecvBufRead  = false;
     224
     225        /*
     226         * Create the sempahore and the debug receive thread itself.
     227         */
     228        rc = RTSemEventMultiCreate(&pThis->Dbg.hDbgRecvThreadSem);
     229        if (RT_SUCCESS(rc))
     230        {
     231            rc = RTThreadCreate(&pThis->hDbgRecvThread, gimDevR3DbgRecvThread, pDevIns, 0 /*cbStack*/, RTTHREADTYPE_IO,
     232                                RTTHREADFLAGS_WAITABLE, "GIMDebugRecv");
     233            if (RT_FAILURE(rc))
     234            {
     235                RTSemEventMultiDestroy(pThis->Dbg.hDbgRecvThreadSem);
     236                pThis->Dbg.hDbgRecvThreadSem = NIL_RTSEMEVENTMULTI;
     237
     238                RTMemFree(pThis->Dbg.pvDbgRecvBuf);
     239                pThis->Dbg.pvDbgRecvBuf = NULL;
     240                return rc;
     241            }
     242        }
     243        else
     244            return rc;
     245    }
     246
     247    /*
     248     * Register this device with the GIM component.
     249     */
     250    GIMR3GimDeviceRegister(pVM, pDevIns, pThis->DbgSetup.cbDbgRecvBuf ? &pThis->Dbg : NULL);
    125251
    126252    /*
     
    197323        if (RT_FAILURE(rc))
    198324            return rc;
     325    }
     326
     327    /*
     328     * Signal and wait for the debug thread to terminate.
     329     */
     330    if (pThis->hDbgRecvThread != NIL_RTTHREAD)
     331    {
     332        pThis->fDbgRecvThreadShutdown = true;
     333        if (pThis->Dbg.hDbgRecvThreadSem != NIL_RTSEMEVENT)
     334            RTSemEventMultiSignal(pThis->Dbg.hDbgRecvThreadSem);
     335
     336        int rc = RTThreadWait(pThis->hDbgRecvThread, 20000, NULL /*prc*/);
     337        if (RT_SUCCESS(rc))
     338            pThis->hDbgRecvThread = NIL_RTTHREAD;
     339        else
     340        {
     341            LogRel(("GIMDev: Debug thread did not terminate, rc=%Rrc!\n", rc));
     342            return VERR_RESOURCE_BUSY;
     343        }
     344    }
     345
     346    /*
     347     * Now clean up the semaphore & buffer now that the thread is gone.
     348     */
     349    if (pThis->Dbg.hDbgRecvThreadSem != NIL_RTSEMEVENT)
     350    {
     351        RTSemEventMultiDestroy(pThis->Dbg.hDbgRecvThreadSem);
     352        pThis->Dbg.hDbgRecvThreadSem = NIL_RTSEMEVENTMULTI;
     353    }
     354    if (pThis->Dbg.pvDbgRecvBuf)
     355    {
     356        RTMemFree(pThis->Dbg.pvDbgRecvBuf);
     357        pThis->Dbg.pvDbgRecvBuf = NULL;
    199358    }
    200359
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