VirtualBox

Changeset 28887 in vbox


Ignore:
Timestamp:
Apr 29, 2010 11:19:17 AM (15 years ago)
Author:
vboxsync
Message:

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

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/HostServices/GuestControlSvc.h

    r28800 r28887  
    196196typedef struct _VBoxGuestCtrlHGCMMsgType
    197197{
    198     VBoxGuestHGCMCallInfoTimed hdr;
     198    VBoxGuestHGCMCallInfo hdr;
    199199
    200200    /**
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibGuestCtrl.cpp

    r28800 r28887  
    110110    VBoxGuestCtrlHGCMMsgType Msg;
    111111
    112     Msg.hdr.u32Timeout = u32Timeout;
    113     Msg.hdr.fInterruptible = true;
    114 
    115     Msg.hdr.info.result = VERR_WRONG_ORDER;
    116     Msg.hdr.info.u32ClientID = u32ClientId;
    117     Msg.hdr.info.u32Function = GUEST_GET_HOST_MSG; /* Tell the host we want our next command. */
    118     Msg.hdr.info.cParms = 2;                       /* Just peek for the next message! */
     112    Msg.hdr.result = VERR_WRONG_ORDER;
     113    Msg.hdr.u32ClientID = u32ClientId;
     114    Msg.hdr.u32Function = GUEST_GET_HOST_MSG; /* Tell the host we want our next command. */
     115    Msg.hdr.cParms = 2;                       /* Just peek for the next message! */
    119116
    120117    VbglHGCMParmUInt32Set(&Msg.msg, 0);
    121118    VbglHGCMParmUInt32Set(&Msg.num_parms, 0);
    122119
    123     int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL_TIMED(sizeof(Msg)), &Msg, sizeof(Msg));
     120    int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
    124121    if (RT_SUCCESS(rc))
    125122    {
     
    128125            rc = VbglHGCMParmUInt32Get(&Msg.num_parms, puNumParms);
    129126            if (RT_SUCCESS(rc))
    130                 rc = Msg.hdr.info.result;
     127                rc = Msg.hdr.result;
    131128                /* Ok, so now we know what message type and how much parameters there are. */
    132129    }
  • trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp

    r28800 r28887  
    298298{
    299299    int rc;
    300 
    301300    /*
    302301     * Initialize the services.
     
    314313            }
    315314        }
    316 
    317315    /*
    318316     * Start the service(s).
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp

    r28833 r28887  
    239239        VBoxServiceVerbose(4, "Control: Waiting for host msg ...\n");
    240240        rc = VbglR3GuestCtrlGetHostMsg(g_GuestControlSvcClientID, &uMsg, &uNumParms, 1000 /* 1s timeout */);
    241         if (rc == VERR_TOO_MUCH_DATA)
    242         {
    243             VBoxServiceVerbose(3, "Control: Message requires %ld parameters, but only 2 supplied -- retrying request ...\n", uNumParms);
    244             rc = VINF_SUCCESS;
    245         }
    246         else if (rc == VERR_TIMEOUT)
    247         {
    248             VBoxServiceVerbose(3, "Control: Wait timed out, waiting for next round ...\n");
    249             RTThreadSleep(100);
    250         }
     241        if (RT_FAILURE(rc))
     242        {
     243            if (rc == VERR_TOO_MUCH_DATA)
     244            {
     245                VBoxServiceVerbose(3, "Control: Message requires %ld parameters, but only 2 supplied -- retrying request ...\n", uNumParms);
     246                rc = VINF_SUCCESS; /* Try to get "real" message in next block below. */
     247            }
     248            else
     249                VBoxServiceVerbose(3, "Control: Getting host message failed with %Rrc\n", rc); /* VERR_GEN_IO_FAILURE seems to be normal if ran  into timeout. */
     250        }
     251
    251252        if (RT_SUCCESS(rc))
    252253        {
     
    272273        }
    273274
    274         /*
    275          * Block for a while.
    276          *
    277          * The event semaphore takes care of ignoring interruptions and it
    278          * allows us to implement service wakeup later.
    279          */
     275        /* Do we need to shutdown? */
    280276        if (*pfShutdown)
    281277        {
     
    283279            break;
    284280        }
    285         int rc2 = RTSemEventMultiWait(g_hControlEvent, g_ControlInterval);
    286         if (*pfShutdown)
    287         {
    288             rc = 0;
    289             break;
    290         }
    291         if (rc2 != VERR_TIMEOUT && RT_FAILURE(rc2))
    292         {
    293             VBoxServiceError("Control: RTSemEventMultiWait failed; rc2=%Rrc\n", rc2);
    294             rc = rc2;
    295             break;
    296         }
     281
     282        /* Let's sleep for a bit and let others run ... */
     283        RTThreadYield();
    297284    }
    298285
  • 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
  • trunk/src/VBox/Main/GuestImpl.cpp

    r28837 r28887  
    839839                        unsigned cMsWait;
    840840                        if (aTimeoutMS == RT_INDEFINITE_WAIT)
    841                             cMsWait = 1000;
     841                            cMsWait = 10;
    842842                        else
    843843                        {
     
    845845                            if (cMsElapsed >= aTimeoutMS)
    846846                                break; /* Timed out. */
    847                             cMsWait = RT_MIN(1000, aTimeoutMS - (uint32_t)cMsElapsed);
     847                            cMsWait = RT_MIN(10, aTimeoutMS - (uint32_t)cMsElapsed);
    848848                        }
    849                         RTThreadYield();
     849                        RTThreadSleep(cMsWait);
    850850                    }
    851851                }
     
    10351035                    unsigned cMsWait;
    10361036                    if (aTimeoutMS == RT_INDEFINITE_WAIT)
    1037                         cMsWait = 1000;
     1037                        cMsWait = 10;
    10381038                    else
    10391039                    {
     
    10411041                        if (cMsElapsed >= aTimeoutMS)
    10421042                            break; /* timed out */
    1043                         cMsWait = RT_MIN(1000, aTimeoutMS - (uint32_t)cMsElapsed);
    1044                     }
    1045                     RTThreadYield();
     1043                        cMsWait = RT_MIN(10, aTimeoutMS - (uint32_t)cMsElapsed);
     1044                    }
     1045                    RTThreadSleep(cMsWait);
    10461046                }
    10471047   
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