diff options
Diffstat (limited to 'src/VBox/HostServices/HostChannel')
| -rw-r--r-- | src/VBox/HostServices/HostChannel/HostChannel.cpp | 388 | ||||
| -rw-r--r-- | src/VBox/HostServices/HostChannel/HostChannel.h | 28 | ||||
| -rw-r--r-- | src/VBox/HostServices/HostChannel/service.cpp | 102 |
3 files changed, 362 insertions, 156 deletions
diff --git a/src/VBox/HostServices/HostChannel/HostChannel.cpp b/src/VBox/HostServices/HostChannel/HostChannel.cpp index 989b0796..5b07aa48 100644 --- a/src/VBox/HostServices/HostChannel/HostChannel.cpp +++ b/src/VBox/HostServices/HostChannel/HostChannel.cpp @@ -21,8 +21,10 @@ #include "HostChannel.h" + static DECLCALLBACK(void) HostChannelCallbackEvent(void *pvCallbacks, void *pvInstance, uint32_t u32Id, const void *pvEvent, uint32_t cbEvent); +static DECLCALLBACK(void) HostChannelCallbackDeleted(void *pvCallbacks, void *pvChannel); /* A registered provider of channels. */ @@ -62,12 +64,23 @@ struct VBOXHOSTCHCTX RTLISTANCHOR listProviders; }; +/* The channel callbacks context. The provider passes the pointer as a callback parameter. + * Created for the provider and deleted when the provider says so. + */ +typedef struct VBOXHOSTCHCALLBACKCTX +{ + RTLISTNODE nodeClient; /* In the client, for cleanup when a client disconnects. */ + + VBOXHOSTCHCLIENT *pClient; /* The client which uses the channel, NULL when the client does not exist. */ +} VBOXHOSTCHCALLBACKCTX; + /* Only one service instance is supported. */ static VBOXHOSTCHCTX g_ctx = { false }; -static VBOXHOSTCHANNELCALLBACKS g_callbacks = +static VBOXHOSTCHANNELCALLBACKS g_callbacks = { - HostChannelCallbackEvent + HostChannelCallbackEvent, + HostChannelCallbackDeleted }; @@ -215,17 +228,19 @@ static int vhcHandleCreate(VBOXHOSTCHCLIENT *pClient, uint32_t *pu32Handle) static void vhcInstanceDestroy(VBOXHOSTCHINSTANCE *pInstance) { - /* @todo free u32Handle? */ + HOSTCHLOG(("HostChannel: destroy %p\n", pInstance)); } static int32_t vhcInstanceAddRef(VBOXHOSTCHINSTANCE *pInstance) { + HOSTCHLOG(("INST: %p %d addref\n", pInstance, pInstance->cRefs)); return ASMAtomicIncS32(&pInstance->cRefs); } static void vhcInstanceRelease(VBOXHOSTCHINSTANCE *pInstance) { int32_t c = ASMAtomicDecS32(&pInstance->cRefs); + HOSTCHLOG(("INST: %p %d release\n", pInstance, pInstance->cRefs)); Assert(c >= 0); if (c == 0) { @@ -250,8 +265,13 @@ static int vhcInstanceCreate(VBOXHOSTCHCLIENT *pClient, VBOXHOSTCHINSTANCE **ppI if (RT_SUCCESS(rc)) { + /* Used by the client, that is in the list of channels. */ vhcInstanceAddRef(pInstance); + /* Add to the list of created channel instances. It is inactive while pClient is 0. */ + RTListAppend(&pClient->listChannels, &pInstance->nodeClient); + /* Return to the caller. */ + vhcInstanceAddRef(pInstance); *ppInstance = pInstance; } @@ -282,7 +302,8 @@ static VBOXHOSTCHINSTANCE *vhcInstanceFind(VBOXHOSTCHCLIENT *pClient, uint32_t u VBOXHOSTCHINSTANCE *pIter; RTListForEach(&pClient->listChannels, pIter, VBOXHOSTCHINSTANCE, nodeClient) { - if (pIter->u32Handle == u32Handle) + if ( pIter->pClient + && pIter->u32Handle == u32Handle) { pInstance = pIter; @@ -302,6 +323,11 @@ static VBOXHOSTCHINSTANCE *vhcInstanceFindByChannelPtr(VBOXHOSTCHCLIENT *pClient { VBOXHOSTCHINSTANCE *pInstance = NULL; + if (pvChannel == NULL) + { + return NULL; + } + int rc = vboxHostChannelLock(); if (RT_SUCCESS(rc)) @@ -309,7 +335,8 @@ static VBOXHOSTCHINSTANCE *vhcInstanceFindByChannelPtr(VBOXHOSTCHCLIENT *pClient VBOXHOSTCHINSTANCE *pIter; RTListForEach(&pClient->listChannels, pIter, VBOXHOSTCHINSTANCE, nodeClient) { - if (pIter->pvChannel == pvChannel) + if ( pIter->pClient + && pIter->pvChannel == pvChannel) { pInstance = pIter; @@ -327,18 +354,118 @@ static VBOXHOSTCHINSTANCE *vhcInstanceFindByChannelPtr(VBOXHOSTCHCLIENT *pClient static void vhcInstanceDetach(VBOXHOSTCHINSTANCE *pInstance) { + HOSTCHLOG(("HostChannel: detach %p\n", pInstance)); + if (pInstance->pProvider) { pInstance->pProvider->iface.HostChannelDetach(pInstance->pvChannel); RTListNodeRemove(&pInstance->nodeProvider); vhcProviderRelease(pInstance->pProvider); - vhcInstanceRelease(pInstance); /* Not in the list anymore. */ + pInstance->pProvider = NULL; + vhcInstanceRelease(pInstance); /* Not in the provider's list anymore. */ + } + + int rc = vboxHostChannelLock(); + + if (RT_SUCCESS(rc)) + { + RTListNodeRemove(&pInstance->nodeClient); + + vboxHostChannelUnlock(); + + vhcInstanceRelease(pInstance); /* Not used by the client anymore. */ + } +} + +/* + * Channel callback contexts. + */ +static int vhcCallbackCtxCreate(VBOXHOSTCHCLIENT *pClient, VBOXHOSTCHCALLBACKCTX **ppCallbackCtx) +{ + int rc = VINF_SUCCESS; + + VBOXHOSTCHCALLBACKCTX *pCallbackCtx = (VBOXHOSTCHCALLBACKCTX *)RTMemAllocZ(sizeof(VBOXHOSTCHCALLBACKCTX)); + + if (pCallbackCtx != NULL) + { + /* The callback context is accessed by the providers threads. */ + rc = vboxHostChannelLock(); + if (RT_SUCCESS(rc)) + { + RTListAppend(&pClient->listContexts, &pCallbackCtx->nodeClient); + pCallbackCtx->pClient = pClient; + + vboxHostChannelUnlock(); + } + else + { + RTMemFree(pCallbackCtx); + } + } + else + { + rc = VERR_NO_MEMORY; + } + + if (RT_SUCCESS(rc)) + { + *ppCallbackCtx = pCallbackCtx; } - RTListNodeRemove(&pInstance->nodeClient); - vhcInstanceRelease(pInstance); /* Not in the list anymore. */ + return rc; } +static int vhcCallbackCtxDelete(VBOXHOSTCHCALLBACKCTX *pCallbackCtx) +{ + int rc = vboxHostChannelLock(); + if (RT_SUCCESS(rc)) + { + VBOXHOSTCHCLIENT *pClient = pCallbackCtx->pClient; + + if (pClient != NULL) + { + /* The callback is associated with a client. + * Check that the callback is in the list and remove it from the list. + */ + bool fFound = false; + + VBOXHOSTCHCALLBACKCTX *pIter; + RTListForEach(&pClient->listContexts, pIter, VBOXHOSTCHCALLBACKCTX, nodeClient) + { + if (pIter == pCallbackCtx) + { + fFound = true; + break; + } + } + + if (fFound) + { + RTListNodeRemove(&pCallbackCtx->nodeClient); + } + else + { + AssertFailed(); + rc = VERR_INVALID_PARAMETER; + } + } + else + { + /* It is not in the clients anymore. May be the client has been disconnected. + * Just free the memory. + */ + } + + vboxHostChannelUnlock(); + } + + if (RT_SUCCESS(rc)) + { + RTMemFree(pCallbackCtx); + } + + return rc; +} /* * Host channel service functions. @@ -382,12 +509,28 @@ int vboxHostChannelClientConnect(VBOXHOSTCHCLIENT *pClient) RTListInit(&pClient->listChannels); RTListInit(&pClient->listEvents); + RTListInit(&pClient->listContexts); return VINF_SUCCESS; } void vboxHostChannelClientDisconnect(VBOXHOSTCHCLIENT *pClient) { + /* Clear the list of contexts and prevent acceess to the client. */ + int rc = vboxHostChannelLock(); + if (RT_SUCCESS(rc)) + { + VBOXHOSTCHCALLBACKCTX *pIter; + VBOXHOSTCHCALLBACKCTX *pNext; + RTListForEachSafe(&pClient->listContexts, pIter, pNext, VBOXHOSTCHCALLBACKCTX, nodeClient) + { + pIter->pClient = NULL; + RTListNodeRemove(&pIter->nodeClient); + } + + vboxHostChannelUnlock(); + } + /* If there are attached channels, detach them. */ VBOXHOSTCHINSTANCE *pIter; VBOXHOSTCHINSTANCE *pIterNext; @@ -417,28 +560,44 @@ int vboxHostChannelAttach(VBOXHOSTCHCLIENT *pClient, if (RT_SUCCESS(rc)) { - void *pvChannel = NULL; - rc = pProvider->iface.HostChannelAttach(pProvider->iface.pvProvider, - &pvChannel, - u32Flags, - &g_callbacks, pClient); + VBOXHOSTCHCALLBACKCTX *pCallbackCtx = NULL; + rc = vhcCallbackCtxCreate(pClient, &pCallbackCtx); + if (RT_SUCCESS(rc)) { - vhcProviderAddRef(pProvider); - pInstance->pProvider = pProvider; + void *pvChannel = NULL; + rc = pProvider->iface.HostChannelAttach(pProvider->iface.pvProvider, + &pvChannel, + u32Flags, + &g_callbacks, pCallbackCtx); - pInstance->pClient = pClient; - pInstance->pvChannel = pvChannel; + if (RT_SUCCESS(rc)) + { + vhcProviderAddRef(pProvider); + pInstance->pProvider = pProvider; - vhcInstanceAddRef(pInstance); /* Referenced by the list client's channels. */ - RTListAppend(&pClient->listChannels, &pInstance->nodeClient); + pInstance->pClient = pClient; + pInstance->pvChannel = pvChannel; + + /* It is already in the channels list of the client. */ + + vhcInstanceAddRef(pInstance); /* Referenced by the list of provider's channels. */ + RTListAppend(&pProvider->listChannels, &pInstance->nodeProvider); - vhcInstanceAddRef(pInstance); /* Referenced by the list of provider's channels. */ - RTListAppend(&pProvider->listChannels, &pInstance->nodeProvider); + *pu32Handle = pInstance->u32Handle; - *pu32Handle = pInstance->u32Handle; + HOSTCHLOG(("HostChannel: Attach: (%d) handle %d\n", pClient->u32ClientID, pInstance->u32Handle)); + } - HOSTCHLOG(("HostChannel: Attach: (%d) handle %d\n", pClient->u32ClientID, pInstance->u32Handle)); + if (RT_FAILURE(rc)) + { + vhcCallbackCtxDelete(pCallbackCtx); + } + } + + if (RT_FAILURE(rc)) + { + vhcInstanceDetach(pInstance); } vhcInstanceRelease(pInstance); @@ -488,10 +647,12 @@ int vboxHostChannelSend(VBOXHOSTCHCLIENT *pClient, VBOXHOSTCHINSTANCE *pInstance = vhcInstanceFind(pClient, u32Handle); - if ( pInstance - && pInstance->pProvider) + if (pInstance) { - pInstance->pProvider->iface.HostChannelSend(pInstance->pvChannel, pvData, cbData); + if (pInstance->pProvider) + { + pInstance->pProvider->iface.HostChannelSend(pInstance->pvChannel, pvData, cbData); + } vhcInstanceRelease(pInstance); } @@ -516,14 +677,16 @@ int vboxHostChannelRecv(VBOXHOSTCHCLIENT *pClient, VBOXHOSTCHINSTANCE *pInstance = vhcInstanceFind(pClient, u32Handle); - if ( pInstance - && pInstance->pProvider) + if (pInstance) { - rc = pInstance->pProvider->iface.HostChannelRecv(pInstance->pvChannel, pvData, cbData, - pu32SizeReceived, pu32SizeRemaining); + if (pInstance->pProvider) + { + rc = pInstance->pProvider->iface.HostChannelRecv(pInstance->pvChannel, pvData, cbData, + pu32SizeReceived, pu32SizeRemaining); - HOSTCHLOG(("HostChannel: Recv: (%d) handle %d, rc %Rrc, recv %d, rem %d\n", - pClient->u32ClientID, u32Handle, rc, cbData, *pu32SizeReceived, *pu32SizeRemaining)); + HOSTCHLOG(("HostChannel: Recv: (%d) handle %d, rc %Rrc, recv %d, rem %d\n", + pClient->u32ClientID, u32Handle, rc, cbData, *pu32SizeReceived, *pu32SizeRemaining)); + } vhcInstanceRelease(pInstance); } @@ -550,12 +713,14 @@ int vboxHostChannelControl(VBOXHOSTCHCLIENT *pClient, VBOXHOSTCHINSTANCE *pInstance = vhcInstanceFind(pClient, u32Handle); - if ( pInstance - && pInstance->pProvider) + if (pInstance) { - pInstance->pProvider->iface.HostChannelControl(pInstance->pvChannel, u32Code, - pvParm, cbParm, - pvData, cbData, pu32SizeDataReturned); + if (pInstance->pProvider) + { + pInstance->pProvider->iface.HostChannelControl(pInstance->pvChannel, u32Code, + pvParm, cbParm, + pvData, cbData, pu32SizeDataReturned); + } vhcInstanceRelease(pInstance); } @@ -578,17 +743,25 @@ typedef struct VBOXHOSTCHANNELEVENT uint32_t cbEvent; } VBOXHOSTCHANNELEVENT; -/* This is called under the lock. */ -int vboxHostChannelQueryEvent(VBOXHOSTCHCLIENT *pClient, - bool *pfEvent, - uint32_t *pu32Handle, - uint32_t *pu32Id, - void *pvParm, - uint32_t cbParm, - uint32_t *pcbParmOut) +int vboxHostChannelEventWait(VBOXHOSTCHCLIENT *pClient, + bool *pfEvent, + VBOXHGCMCALLHANDLE callHandle, + VBOXHGCMSVCPARM *paParms) { - /* Check if there is something in the client's event queue. */ + int rc = vboxHostChannelLock(); + if (RT_FAILURE(rc)) + { + return rc; + } + if (pClient->fAsync) + { + /* If there is a wait request already, cancel it. */ + vboxHostChannelReportAsync(pClient, 0, VBOX_HOST_CHANNEL_EVENT_CANCELLED, NULL, 0); + pClient->fAsync = false; + } + + /* Check if there is something in the client's event queue. */ VBOXHOSTCHANNELEVENT *pEvent = RTListGetFirst(&pClient->listEvents, VBOXHOSTCHANNELEVENT, NodeEvent); HOSTCHLOG(("HostChannel: QueryEvent: (%d), event %p\n", pClient->u32ClientID, pEvent)); @@ -598,61 +771,119 @@ int vboxHostChannelQueryEvent(VBOXHOSTCHCLIENT *pClient, /* Report the event. */ RTListNodeRemove(&pEvent->NodeEvent); - *pfEvent = true; - *pu32Handle = pEvent->u32ChannelHandle; - *pu32Id = pEvent->u32Id; - - uint32_t cbToCopy = RT_MIN(cbParm, pEvent->cbEvent); - - HOSTCHLOG(("HostChannel: QueryEvent: (%d), cbParm %d, cbEvent %d\n", - pClient->u32ClientID, cbParm, pEvent->cbEvent)); + HOSTCHLOG(("HostChannel: QueryEvent: (%d), cbEvent %d\n", + pClient->u32ClientID, pEvent->cbEvent)); - if (cbToCopy > 0) - { - memcpy(pvParm, pEvent->pvEvent, cbToCopy); - } + vboxHostChannelEventParmsSet(paParms, pEvent->u32ChannelHandle, + pEvent->u32Id, pEvent->pvEvent, pEvent->cbEvent); - *pcbParmOut = cbToCopy; + *pfEvent = true; RTMemFree(pEvent); } else { + /* No event available at the time. Process asynchronously. */ + pClient->fAsync = true; + pClient->async.callHandle = callHandle; + pClient->async.paParms = paParms; + /* Tell the caller that there is no event. */ *pfEvent = false; } - return VINF_SUCCESS; + vboxHostChannelUnlock(); + return rc; +} + +int vboxHostChannelEventCancel(VBOXHOSTCHCLIENT *pClient) +{ + int rc = vboxHostChannelLock(); + + if (RT_SUCCESS(rc)) + { + if (pClient->fAsync) + { + /* If there is a wait request alredy, cancel it. */ + vboxHostChannelReportAsync(pClient, 0, VBOX_HOST_CHANNEL_EVENT_CANCELLED, NULL, 0); + + pClient->fAsync = false; + } + + vboxHostChannelUnlock(); + } + + return rc; } +/* @thread provider */ static DECLCALLBACK(void) HostChannelCallbackEvent(void *pvCallbacks, void *pvChannel, uint32_t u32Id, const void *pvEvent, uint32_t cbEvent) { - VBOXHOSTCHCLIENT *pClient = (VBOXHOSTCHCLIENT *)pvCallbacks; + VBOXHOSTCHCALLBACKCTX *pCallbackCtx = (VBOXHOSTCHCALLBACKCTX *)pvCallbacks; - VBOXHOSTCHINSTANCE *pInstance = vhcInstanceFindByChannelPtr(pClient, pvChannel); + int rc = vboxHostChannelLock(); + if (RT_FAILURE(rc)) + { + return; + } - HOSTCHLOG(("HostChannel: CallbackEvent: (%d) instance %p\n", - pClient->u32ClientID, pInstance)); + /* Check that the structure is still associated with a client. + * The client can disconnect and will be invalid. + */ + VBOXHOSTCHCLIENT *pClient = pCallbackCtx->pClient; - if (!pInstance) + if (pClient == NULL) + { + vboxHostChannelUnlock(); + + HOSTCHLOG(("HostChannel: CallbackEvent[%p]: client gone.\n")); + + /* The client does not exist anymore, skip the event. */ + return; + } + + bool fFound = false; + + VBOXHOSTCHCALLBACKCTX *pIter; + RTListForEach(&pClient->listContexts, pIter, VBOXHOSTCHCALLBACKCTX, nodeClient) + { + if (pIter == pCallbackCtx) + { + fFound = true; + break; + } + } + + if (!fFound) { -#ifdef DEBUG_sunlover AssertFailed(); -#endif + + vboxHostChannelUnlock(); + + HOSTCHLOG(("HostChannel: CallbackEvent[%p]: client does not have the context.\n")); + + /* The context is not in the list of contexts. Skip the event. */ return; } - int rc = vboxHostChannelLock(); - if (RT_FAILURE(rc)) + VBOXHOSTCHINSTANCE *pInstance = vhcInstanceFindByChannelPtr(pClient, pvChannel); + + HOSTCHLOG(("HostChannel: CallbackEvent[%p]: (%d) instance %p\n", + pCallbackCtx, pClient->u32ClientID, pInstance)); + + if (!pInstance) { + /* Instance was already detached. Skip the event. */ + vboxHostChannelUnlock(); + return; } uint32_t u32ChannelHandle = pInstance->u32Handle; HOSTCHLOG(("HostChannel: CallbackEvent: (%d) handle %d, async %d, cbEvent %d\n", - pClient->u32ClientID, u32ChannelHandle, pClient->fAsync, cbEvent)); + pClient->u32ClientID, u32ChannelHandle, pClient->fAsync, cbEvent)); /* Check whether the event is waited. */ if (pClient->fAsync) @@ -684,18 +915,19 @@ static DECLCALLBACK(void) HostChannelCallbackEvent(void *pvCallbacks, void *pvCh pEvent->cbEvent = cbEvent; - if (RT_SUCCESS(rc)) - { - RTListAppend(&pClient->listEvents, &pEvent->NodeEvent); - } - else - { - RTMemFree(pEvent); - } + RTListAppend(&pClient->listEvents, &pEvent->NodeEvent); } } vboxHostChannelUnlock(); + + vhcInstanceRelease(pInstance); +} + +/* @thread provider */ +static DECLCALLBACK(void) HostChannelCallbackDeleted(void *pvCallbacks, void *pvChannel) +{ + vhcCallbackCtxDelete((VBOXHOSTCHCALLBACKCTX *)pvCallbacks); } int vboxHostChannelQuery(VBOXHOSTCHCLIENT *pClient, diff --git a/src/VBox/HostServices/HostChannel/HostChannel.h b/src/VBox/HostServices/HostChannel/HostChannel.h index 173faf2c..190f4b98 100644 --- a/src/VBox/HostServices/HostChannel/HostChannel.h +++ b/src/VBox/HostServices/HostChannel/HostChannel.h @@ -45,6 +45,8 @@ typedef struct VBOXHOSTCHCLIENT RTLISTANCHOR listChannels; uint32_t volatile u32HandleSrc; + RTLISTANCHOR listContexts; /* Callback contexts. */ + RTLISTANCHOR listEvents; bool fAsync; /* Guest is waiting for a message. */ @@ -95,13 +97,12 @@ int vboxHostChannelControl(VBOXHOSTCHCLIENT *pClient, uint32_t cbData, uint32_t *pu32SizeDataReturned); -int vboxHostChannelQueryEvent(VBOXHOSTCHCLIENT *pClient, - bool *pfEvent, - uint32_t *pu32Handle, - uint32_t *pu32Id, - void *pvParm, - uint32_t cbParm, - uint32_t *pcbParmOut); +int vboxHostChannelEventWait(VBOXHOSTCHCLIENT *pClient, + bool *pfEvent, + VBOXHGCMCALLHANDLE callHandle, + VBOXHGCMSVCPARM *paParms); + +int vboxHostChannelEventCancel(VBOXHOSTCHCLIENT *pClient); int vboxHostChannelQuery(VBOXHOSTCHCLIENT *pClient, const char *pszName, @@ -118,7 +119,16 @@ int vboxHostChannelRegister(const char *pszName, int vboxHostChannelUnregister(const char *pszName); -void vboxHostChannelReportAsync(VBOXHOSTCHCLIENT *pClient, uint32_t u32ChannelHandle, - uint32_t u32Id, const void *pvEvent, uint32_t cbEvent); +void vboxHostChannelEventParmsSet(VBOXHGCMSVCPARM *paParms, + uint32_t u32ChannelHandle, + uint32_t u32Id, + const void *pvEvent, + uint32_t cbEvent); + +void vboxHostChannelReportAsync(VBOXHOSTCHCLIENT *pClient, + uint32_t u32ChannelHandle, + uint32_t u32Id, + const void *pvEvent, + uint32_t cbEvent); #endif /* __VBOXHOSTCHANNEL__H */ diff --git a/src/VBox/HostServices/HostChannel/service.cpp b/src/VBox/HostServices/HostChannel/service.cpp index c632d9d0..a2042985 100644 --- a/src/VBox/HostServices/HostChannel/service.cpp +++ b/src/VBox/HostServices/HostChannel/service.cpp @@ -106,30 +106,46 @@ void vboxHostChannelUnlock(void) RTCritSectLeave(&g_critsect); } -/* This is called under the lock. */ -void vboxHostChannelReportAsync(VBOXHOSTCHCLIENT *pClient, - uint32_t u32ChannelHandle, - uint32_t u32Id, - const void *pvEvent, - uint32_t cbEvent) +void vboxHostChannelEventParmsSet(VBOXHGCMSVCPARM *paParms, + uint32_t u32ChannelHandle, + uint32_t u32Id, + const void *pvEvent, + uint32_t cbEvent) { if (cbEvent > 0) { void *pvParm = NULL; uint32_t cbParm = 0; - VBoxHGCMParmPtrGet(&pClient->async.paParms[2], &pvParm, &cbParm); + VBoxHGCMParmPtrGet(&paParms[2], &pvParm, &cbParm); uint32_t cbToCopy = RT_MIN(cbParm, cbEvent); if (cbToCopy > 0) { + Assert(pvParm); memcpy(pvParm, pvEvent, cbToCopy); } } - VBoxHGCMParmUInt32Set(&pClient->async.paParms[0], u32ChannelHandle); - VBoxHGCMParmUInt32Set(&pClient->async.paParms[1], u32Id); - VBoxHGCMParmUInt32Set(&pClient->async.paParms[3], cbEvent); + VBoxHGCMParmUInt32Set(&paParms[0], u32ChannelHandle); + VBoxHGCMParmUInt32Set(&paParms[1], u32Id); + VBoxHGCMParmUInt32Set(&paParms[3], cbEvent); +} + +/* This is called under the lock. */ +void vboxHostChannelReportAsync(VBOXHOSTCHCLIENT *pClient, + uint32_t u32ChannelHandle, + uint32_t u32Id, + const void *pvEvent, + uint32_t cbEvent) +{ + Assert(RTCritSectIsOwner(&g_critsect)); + + vboxHostChannelEventParmsSet(pClient->async.paParms, + u32ChannelHandle, + u32Id, + pvEvent, + cbEvent); LogRelFlow(("svcCall: CallComplete for pending\n")); @@ -437,56 +453,18 @@ static DECLCALLBACK(void) svcCall(void *pvService, } else { - void *pvParm; - uint32_t cbParm; + bool fEvent = false; - rc = VBoxHGCMParmPtrGet(&paParms[2], &pvParm, &cbParm); + rc = vboxHostChannelEventWait(pClient, &fEvent, callHandle, paParms); if (RT_SUCCESS(rc)) { - /* This is accessed from the SVC thread and other threads. */ - rc = vboxHostChannelLock(); - - if (RT_SUCCESS(rc)) + if (!fEvent) { - if (pClient->fAsync) - { - /* If there is a wait request already, cancel it. */ - vboxHostChannelReportAsync(pClient, 0, VBOX_HOST_CHANNEL_EVENT_CANCELLED, NULL, 0); - - pClient->fAsync = false; - } - - bool fEvent = false; - uint32_t u32Handle = 0; - uint32_t u32Id = 0; - uint32_t cbParmOut = 0; - - rc = vboxHostChannelQueryEvent(pClient, &fEvent, &u32Handle, &u32Id, - pvParm, cbParm, &cbParmOut); - - if (RT_SUCCESS(rc)) - { - if (fEvent) - { - VBoxHGCMParmUInt32Set(&paParms[0], u32Handle); - VBoxHGCMParmUInt32Set(&paParms[1], u32Id); - VBoxHGCMParmUInt32Set(&paParms[3], cbParmOut); - } - else - { - /* No event available at the time. Process asynchronously. */ - fAsynchronousProcessing = true; - - pClient->fAsync = true; - pClient->async.callHandle = callHandle; - pClient->async.paParms = paParms; + /* No event available at the time. Process asynchronously. */ + fAsynchronousProcessing = true; - LogRel2(("svcCall: async.\n")); - } - } - - vboxHostChannelUnlock(); + LogRel2(("svcCall: async.\n")); } } } @@ -502,21 +480,7 @@ static DECLCALLBACK(void) svcCall(void *pvService, } else { - /* This is accessed from the SVC thread and other threads. */ - rc = vboxHostChannelLock(); - - if (RT_SUCCESS(rc)) - { - if (pClient->fAsync) - { - /* If there is a wait request alredy, cancel it. */ - vboxHostChannelReportAsync(pClient, 0, VBOX_HOST_CHANNEL_EVENT_CANCELLED, NULL, 0); - - pClient->fAsync = false; - } - - vboxHostChannelUnlock(); - } + rc = vboxHostChannelEventCancel(pClient); } } break; |
