VirtualBox

Ignore:
Timestamp:
Apr 29, 2010 11:19:17 AM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
60826
Message:

Guest Control/Main: Faster (no polling on guest side), free data on shutdown.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/GuestControl/service.cpp

    r28800 r28887  
    5555    VBOXGUESTCTRPARAMBUFFER parmBuf;
    5656};
    57 /** The host cmd list type */
    58 typedef std::list <HostCmd> HostCmdList;
     57/** The host cmd list + iterator type */
     58typedef std::list< HostCmd > HostCmdList;
     59typedef std::list< HostCmd >::iterator HostCmdListIter;
     60typedef std::list< HostCmd >::const_iterator HostCmdListIterConst;
    5961
    6062/**
     
    6567    /** The call handle */
    6668    VBOXHGCMCALLHANDLE mHandle;
    67     /** The function that was requested */
    68     uint32_t mFunction;
    6969    /** The call parameters */
    7070    VBOXHGCMSVCPARM *mParms;
    7171    /** Number of parameters */
    7272    uint32_t mNumParms;
    73     /** The default return value, used for passing warnings */
    74     int mRc;
    7573
    7674    /** The standard constructor */
    77     GuestCall() : mFunction(0) {}
     75    GuestCall() : mHandle(0), mParms(NULL), mNumParms(0) {}
    7876    /** The normal contructor */
    79     GuestCall(VBOXHGCMCALLHANDLE aHandle, uint32_t aFunction,
    80               VBOXHGCMSVCPARM aParms[], int cParms, int aRc)
    81               : mHandle(aHandle), mFunction(aFunction), mParms(aParms),
    82                 mNumParms(cParms), mRc(aRc) {}
     77    GuestCall(VBOXHGCMCALLHANDLE aHandle, VBOXHGCMSVCPARM aParms[], int cParms)
     78              : mHandle(aHandle), mParms(aParms), mNumParms(cParms) {}
    8379};
    8480/** The guest call list type */
     
    110106    void *mpvHostData;
    111107    /** The deferred calls list */
    112     CallList mGuestWaiters;
     108    CallList mClientList;
    113109    /** The host command list */
    114110    HostCmdList mHostCmds;
     
    238234    int clientConnect(uint32_t u32ClientID, void *pvClient);
    239235    int clientDisconnect(uint32_t u32ClientID, void *pvClient);
    240     int processHostMsg(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    241     int notifyGuest(GuestCall *pCall, uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     236    int sendHostCmdToGuest(HostCmd *pCmd, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     237    int retrieveNextHostCmd(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    242238    int notifyHost(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    243     int processCmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     239    int processHostCmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    244240    void call(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID,
    245241              void *pvClient, uint32_t eFunction, uint32_t cParms,
     
    399395}
    400396
     397int Service::sendHostCmdToGuest(HostCmd *pCmd, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     398{
     399    AssertPtr(pCmd);
     400    int rc;
     401 
     402    /* Sufficient parameter space? */
     403    if (pCmd->parmBuf.uParmCount > cParms)
     404    {
     405        paParms[0].setUInt32(pCmd->parmBuf.uMsg);       /* Message ID */
     406        paParms[1].setUInt32(pCmd->parmBuf.uParmCount); /* Required parameters for message */
     407       
     408        /*
     409        * So this call apparently failed because the guest wanted to peek
     410        * how much parameters it has to supply in order to successfully retrieve
     411        * this command. Let's tell him so!
     412        */
     413        rc = VERR_TOO_MUCH_DATA;
     414    }
     415    else
     416    {
     417        rc = paramBufferAssign(&pCmd->parmBuf, cParms, paParms);
     418    }
     419    return rc;
     420}
     421
    401422/*
    402423 * Either fills in parameters from a pending host command into our guest context or
    403424 * defer the guest call until we have something from the host.
    404425 */
    405 int Service::processHostMsg(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     426int Service::retrieveNextHostCmd(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    406427{
    407428    int rc = VINF_SUCCESS;
    408429
    409     if (cParms < 2)
    410     {
    411         LogFlowFunc(("Guest parameter buffer is too small!\n"));
    412         rc = VERR_INVALID_PARAMETER;
     430    /*
     431     * If host command list is empty (nothing to do right now) just
     432     * defer the call until we got something to do (makes the client
     433     * wait, depending on the flags set).
     434     */
     435    if (mHostCmds.empty()) /* If command list is empty, defer ... */
     436    {
     437        mClientList.push_back(GuestCall(callHandle, paParms, cParms));
     438        rc = VINF_HGCM_ASYNC_EXECUTE;
    413439    }
    414440    else
    415441    {
    416442        /*
    417          * If host command list is empty (nothing to do right now) just
    418          * defer the call until we got something to do (makes the client
    419          * wait, depending on the flags set).
     443         * Get the next unassigned host command in the list.
    420444         */
    421         if (mHostCmds.empty()) /* Command list is empty, defer ... */
    422             rc = VINF_HGCM_ASYNC_EXECUTE;
    423 
    424         if (rc != VINF_HGCM_ASYNC_EXECUTE)
    425         {
    426             /*
    427              * Get the next unassigned host command in the list.
    428              */
    429              HostCmd curCmd = mHostCmds.front();
    430              uint32_t uParmCount = curCmd.parmBuf.uParmCount;
    431 
    432              /* Sufficient parameter space? */
    433              if (uParmCount > cParms)
    434              {
    435                  paParms[0].setUInt32(curCmd.parmBuf.uMsg); /* Message ID */
    436                  paParms[1].setUInt32(uParmCount); /* Required parameters for message */
    437 
    438                  /*
    439                   * So this call apparently failed because the guest wanted to peek
    440                   * how much parameters it has to supply in order to successfully retrieve
    441                   * this command. Let's tell him so!
    442                   */
    443                  rc = VERR_TOO_MUCH_DATA;
    444              }
    445              else
    446              {
    447                  rc = paramBufferAssign(&curCmd.parmBuf, cParms, paParms);
    448                  if (RT_SUCCESS(rc))
    449                  {
    450                      paramBufferFree(&curCmd.parmBuf);
    451                      mHostCmds.pop_front();
    452                  }
    453              }
    454         }
    455         else
    456         {
    457             /* Call is deferred because of reasons above. */
    458             mGuestWaiters.push_back(GuestCall(callHandle, GUEST_GET_HOST_MSG,
    459                                               paParms, cParms, rc));
    460         }
    461     }
    462     return rc;
    463 }
    464 
    465 /*
    466  * Sends a command notification to the first waiting (deferred) client/guest in line in
    467  * order to wake up and do some work.
    468  */
    469 int Service::notifyGuest(GuestCall *pCall, uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    470 {
    471     AssertPtr(pCall);
    472     int rc = VINF_SUCCESS;
    473 
    474     int rc2 = processHostMsg(pCall->mHandle, pCall->mNumParms, pCall->mParms);
    475     if (RT_SUCCESS(rc2))
    476         rc2 = pCall->mRc;
    477     AssertPtr(mpHelpers);
    478     mpHelpers->pfnCallComplete(pCall->mHandle, rc2);
     445         HostCmd curCmd = mHostCmds.front();
     446         rc = sendHostCmdToGuest(&curCmd, callHandle, cParms, paParms);
     447         if (RT_SUCCESS(rc))
     448         {
     449             /* Only if the guest really got and understood the message
     450              * remove it from the list. */
     451             paramBufferFree(&curCmd.parmBuf);
     452             mHostCmds.pop_front();
     453         }
     454    }
    479455    return rc;
    480456}
     
    523499}
    524500
    525 int Service::processCmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     501int Service::processHostCmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    526502{
    527503    int rc = VINF_SUCCESS;
    528504
    529     /* Some lazy guests to wake up which can process this command right now? */
    530     if (!mGuestWaiters.empty())
    531     {
    532         HostCmd newCmd;
    533         rc = paramBufferAllocate(&newCmd.parmBuf, eFunction, cParms, paParms);
    534         if (RT_SUCCESS(rc))
     505    HostCmd newCmd;
     506    bool fProcessed = false;
     507    rc = paramBufferAllocate(&newCmd.parmBuf, eFunction, cParms, paParms);
     508    if (RT_SUCCESS(rc))
     509    {
     510        /* Can we wake up a waiting client on guest? */
     511        if (!mClientList.empty())
     512        {
     513            GuestCall guest = mClientList.front();
     514            rc = sendHostCmdToGuest(&newCmd,
     515                             guest.mHandle, guest.mNumParms, guest.mParms);
     516
     517            /* In any case the client did something, so wake up and remove from list. */
     518            mpHelpers->pfnCallComplete(guest.mHandle, rc);
     519            mClientList.pop_front();                       
     520
     521            /* If command was understood by client, free and remove from host commands list. */
     522            if (RT_SUCCESS(rc))
     523            {
     524                paramBufferFree(&newCmd.parmBuf);
     525                fProcessed = true;
     526            }
     527            else if (rc == VERR_TOO_MUCH_DATA)
     528            {
     529                /* If we got VERR_TOO_MUCH_DATA we buffer the host command in the next block
     530                 * and return success to the host. */
     531                rc = VINF_SUCCESS;
     532            }
     533        }
     534
     535        /* If not processed, buffer it ... */
     536        if (!fProcessed)
    535537        {
    536538            mHostCmds.push_back(newCmd);
     
    539541            if (mHostCmds.size() > 256) /** @todo Use a define! */
    540542                mHostCmds.pop_front();
    541 
    542             GuestCall curCall = mGuestWaiters.front();
    543             rc = notifyGuest(&curCall, eFunction, cParms, paParms);
    544             mGuestWaiters.pop_front();
    545         }
    546     }
    547     else /* No guest waiting, don't bother ... */
    548         rc = VERR_TIMEOUT;
     543        }
     544    }
    549545    return rc;
    550546}
     
    573569            case GUEST_GET_HOST_MSG:
    574570                LogFlowFunc(("GUEST_GET_HOST_MSG\n"));
    575                 rc = processHostMsg(callHandle, cParms, paParms);
     571                rc = retrieveNextHostCmd(callHandle, cParms, paParms);
    576572                break;
    577573
     
    592588                break;
    593589        }
    594         /*
    595          * If current call is not deferred, call the completion function.
    596          */
    597590        if (rc != VINF_HGCM_ASYNC_EXECUTE)
    598591        {
     592            /* Tell the client that the call is complete (unblocks waiting). */
    599593            mpHelpers->pfnCallComplete(callHandle, rc);
    600594        }
     
    624618            case HOST_EXEC_CMD:
    625619                LogFlowFunc(("HOST_EXEC_CMD\n"));
    626                 rc = processCmd(eFunction, cParms, paParms);
     620                rc = processHostCmd(eFunction, cParms, paParms);
    627621                break;
    628622
     
    634628            case HOST_EXEC_GET_OUTPUT:
    635629                LogFlowFunc(("HOST_EXEC_GET_OUTPUT\n"));
    636                 rc = processCmd(eFunction, cParms, paParms);
     630                rc = processHostCmd(eFunction, cParms, paParms);
    637631                break;
    638632
     
    653647int Service::uninit()
    654648{
    655     int rc = VINF_SUCCESS;
    656     return rc;
     649    /* Free allocated buffered host commands. */
     650    HostCmdListIter it;
     651    for (it = mHostCmds.begin(); it != mHostCmds.end(); it++)
     652        paramBufferFree(&it->parmBuf);
     653    mHostCmds.clear();
     654
     655    return VINF_SUCCESS;
    657656}
    658657
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