Changeset 28887 in vbox
- Timestamp:
- Apr 29, 2010 11:19:17 AM (15 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/HostServices/GuestControlSvc.h
r28800 r28887 196 196 typedef struct _VBoxGuestCtrlHGCMMsgType 197 197 { 198 VBoxGuestHGCMCallInfo Timedhdr;198 VBoxGuestHGCMCallInfo hdr; 199 199 200 200 /** -
trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibGuestCtrl.cpp
r28800 r28887 110 110 VBoxGuestCtrlHGCMMsgType Msg; 111 111 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! */ 119 116 120 117 VbglHGCMParmUInt32Set(&Msg.msg, 0); 121 118 VbglHGCMParmUInt32Set(&Msg.num_parms, 0); 122 119 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)); 124 121 if (RT_SUCCESS(rc)) 125 122 { … … 128 125 rc = VbglHGCMParmUInt32Get(&Msg.num_parms, puNumParms); 129 126 if (RT_SUCCESS(rc)) 130 rc = Msg.hdr. info.result;127 rc = Msg.hdr.result; 131 128 /* Ok, so now we know what message type and how much parameters there are. */ 132 129 } -
trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp
r28800 r28887 298 298 { 299 299 int rc; 300 301 300 /* 302 301 * Initialize the services. … … 314 313 } 315 314 } 316 317 315 /* 318 316 * Start the service(s). -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp
r28833 r28887 239 239 VBoxServiceVerbose(4, "Control: Waiting for host msg ...\n"); 240 240 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 251 252 if (RT_SUCCESS(rc)) 252 253 { … … 272 273 } 273 274 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? */ 280 276 if (*pfShutdown) 281 277 { … … 283 279 break; 284 280 } 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(); 297 284 } 298 285 -
trunk/src/VBox/HostServices/GuestControl/service.cpp
r28800 r28887 55 55 VBOXGUESTCTRPARAMBUFFER parmBuf; 56 56 }; 57 /** The host cmd list type */ 58 typedef std::list <HostCmd> HostCmdList; 57 /** The host cmd list + iterator type */ 58 typedef std::list< HostCmd > HostCmdList; 59 typedef std::list< HostCmd >::iterator HostCmdListIter; 60 typedef std::list< HostCmd >::const_iterator HostCmdListIterConst; 59 61 60 62 /** … … 65 67 /** The call handle */ 66 68 VBOXHGCMCALLHANDLE mHandle; 67 /** The function that was requested */68 uint32_t mFunction;69 69 /** The call parameters */ 70 70 VBOXHGCMSVCPARM *mParms; 71 71 /** Number of parameters */ 72 72 uint32_t mNumParms; 73 /** The default return value, used for passing warnings */74 int mRc;75 73 76 74 /** The standard constructor */ 77 GuestCall() : m Function(0) {}75 GuestCall() : mHandle(0), mParms(NULL), mNumParms(0) {} 78 76 /** 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) {} 83 79 }; 84 80 /** The guest call list type */ … … 110 106 void *mpvHostData; 111 107 /** The deferred calls list */ 112 CallList m GuestWaiters;108 CallList mClientList; 113 109 /** The host command list */ 114 110 HostCmdList mHostCmds; … … 238 234 int clientConnect(uint32_t u32ClientID, void *pvClient); 239 235 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[]); 242 238 int notifyHost(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 243 int process Cmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);239 int processHostCmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 244 240 void call(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, 245 241 void *pvClient, uint32_t eFunction, uint32_t cParms, … … 399 395 } 400 396 397 int 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 401 422 /* 402 423 * Either fills in parameters from a pending host command into our guest context or 403 424 * defer the guest call until we have something from the host. 404 425 */ 405 int Service:: processHostMsg(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[])426 int Service::retrieveNextHostCmd(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 406 427 { 407 428 int rc = VINF_SUCCESS; 408 429 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; 413 439 } 414 440 else 415 441 { 416 442 /* 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. 420 444 */ 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 } 479 455 return rc; 480 456 } … … 523 499 } 524 500 525 int Service::process Cmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])501 int Service::processHostCmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 526 502 { 527 503 int rc = VINF_SUCCESS; 528 504 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) 535 537 { 536 538 mHostCmds.push_back(newCmd); … … 539 541 if (mHostCmds.size() > 256) /** @todo Use a define! */ 540 542 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 } 549 545 return rc; 550 546 } … … 573 569 case GUEST_GET_HOST_MSG: 574 570 LogFlowFunc(("GUEST_GET_HOST_MSG\n")); 575 rc = processHostMsg(callHandle, cParms, paParms);571 rc = retrieveNextHostCmd(callHandle, cParms, paParms); 576 572 break; 577 573 … … 592 588 break; 593 589 } 594 /*595 * If current call is not deferred, call the completion function.596 */597 590 if (rc != VINF_HGCM_ASYNC_EXECUTE) 598 591 { 592 /* Tell the client that the call is complete (unblocks waiting). */ 599 593 mpHelpers->pfnCallComplete(callHandle, rc); 600 594 } … … 624 618 case HOST_EXEC_CMD: 625 619 LogFlowFunc(("HOST_EXEC_CMD\n")); 626 rc = process Cmd(eFunction, cParms, paParms);620 rc = processHostCmd(eFunction, cParms, paParms); 627 621 break; 628 622 … … 634 628 case HOST_EXEC_GET_OUTPUT: 635 629 LogFlowFunc(("HOST_EXEC_GET_OUTPUT\n")); 636 rc = process Cmd(eFunction, cParms, paParms);630 rc = processHostCmd(eFunction, cParms, paParms); 637 631 break; 638 632 … … 653 647 int Service::uninit() 654 648 { 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; 657 656 } 658 657 -
trunk/src/VBox/Main/GuestImpl.cpp
r28837 r28887 839 839 unsigned cMsWait; 840 840 if (aTimeoutMS == RT_INDEFINITE_WAIT) 841 cMsWait = 10 00;841 cMsWait = 10; 842 842 else 843 843 { … … 845 845 if (cMsElapsed >= aTimeoutMS) 846 846 break; /* Timed out. */ 847 cMsWait = RT_MIN(10 00, aTimeoutMS - (uint32_t)cMsElapsed);847 cMsWait = RT_MIN(10, aTimeoutMS - (uint32_t)cMsElapsed); 848 848 } 849 RTThread Yield();849 RTThreadSleep(cMsWait); 850 850 } 851 851 } … … 1035 1035 unsigned cMsWait; 1036 1036 if (aTimeoutMS == RT_INDEFINITE_WAIT) 1037 cMsWait = 10 00;1037 cMsWait = 10; 1038 1038 else 1039 1039 { … … 1041 1041 if (cMsElapsed >= aTimeoutMS) 1042 1042 break; /* timed out */ 1043 cMsWait = RT_MIN(10 00, aTimeoutMS - (uint32_t)cMsElapsed);1044 } 1045 RTThread Yield();1043 cMsWait = RT_MIN(10, aTimeoutMS - (uint32_t)cMsElapsed); 1044 } 1045 RTThreadSleep(cMsWait); 1046 1046 } 1047 1047
Note:
See TracChangeset
for help on using the changeset viewer.