Changeset 14221 in vbox
- Timestamp:
- Nov 14, 2008 3:06:59 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp
r13305 r14221 919 919 } 920 920 921 #ifdef HGCM_TIMEOUT 922 /** 923 * This is a callback for dealing with async waits with a timeout. 924 * 925 * It operates in a manner similar to VBoxGuestCommonIOCtl_WaitEvent. 926 */ 927 static DECLCALLBACK(void) 928 VBoxGuestHGCMAsyncWaitCallbackTimeout(VMMDevHGCMRequestHeader *pHdrNonVolatile, void *pvUser, 929 uint32_t u32User) 930 { 931 VMMDevHGCMRequestHeader volatile *pHdr = (VMMDevHGCMRequestHeader volatile *)pHdrNonVolatile; 932 PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pvUser; 933 Log(("VBoxGuestHGCMAsyncWaitCallback: requestType=%d\n", pHdr->header.requestType)); 934 935 /* 936 * Check to see if the condition was met by the time we got here. 937 * 938 * We create a simple poll loop here for dealing with out-of-memory 939 * conditions since the caller isn't necessarily able to deal with 940 * us returning too early. 941 */ 942 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; 943 PVBOXGUESTWAIT pWait; 944 for (;;) 945 { 946 RTSpinlockAcquireNoInts(pDevExt->WaitSpinlock, &Tmp); 947 if ((pHdr->fu32Flags & VBOX_HGCM_REQ_DONE) != 0) 948 { 949 RTSpinlockReleaseNoInts(pDevExt->WaitSpinlock, &Tmp); 950 return; 951 } 952 RTSpinlockReleaseNoInts(pDevExt->WaitSpinlock, &Tmp); 953 954 pWait = VBoxGuestWaitAlloc(pDevExt); 955 if (pWait) 956 break; 957 return; 958 } 959 pWait->fReqEvents = VMMDEV_EVENT_HGCM; 960 pWait->pHGCMReq = pHdr; 961 962 /* 963 * Re-enter the spinlock and re-check for the condition. 964 * If the condition is met, return. 965 * Otherwise link us into the HGCM wait list and go to sleep. 966 */ 967 RTSpinlockAcquireNoInts(pDevExt->WaitSpinlock, &Tmp); 968 if ((pHdr->fu32Flags & VBOX_HGCM_REQ_DONE) != 0) 969 { 970 VBoxGuestWaitFreeLocked(pDevExt, pWait); 971 RTSpinlockReleaseNoInts(pDevExt->WaitSpinlock, &Tmp); 972 return; 973 } 974 VBoxGuestWaitAppend(&pDevExt->HGCMWaitList, pWait); 975 RTSpinlockReleaseNoInts(pDevExt->WaitSpinlock, &Tmp); 976 977 int rc = RTSemEventMultiWaitNoResume(pWait->Event, u32User); 978 979 /* 980 * This shouldn't ever return failure... 981 * Unlink, free and return. 982 */ 983 if (rc == VERR_SEM_DESTROYED) 984 return; 985 if (RT_FAILURE(rc)) 986 LogRel(("VBoxGuestHGCMAsyncWaitCallback: wait failed! %Rrc\n", rc)); 987 988 RTSpinlockAcquireNoInts(pDevExt->WaitSpinlock, &Tmp); 989 VBoxGuestWaitUnlink(&pDevExt->HGCMWaitList, pWait); 990 VBoxGuestWaitFreeLocked(pDevExt, pWait); 991 RTSpinlockReleaseNoInts(pDevExt->WaitSpinlock, &Tmp); 992 } 993 #endif /* HGCM_TIMEOUT */ 994 921 995 922 996 static int VBoxGuestCommonIOCtl_HGCMConnect(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, VBoxGuestHGCMConnectInfo *pInfo, … … 1079 1153 1080 1154 1155 #ifdef /* HGCM_TIMEOUT */ 1156 static int VBoxGuestCommonIOCtl_HGCMCallTimeout(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, VBoxGuestHGCMCallInfoTimeout *pInfoTimeout, 1157 size_t cbData, size_t *pcbDataReturned) 1158 { 1159 VBoxGuestHGCMCallInfo *pInfo = &pInfoTimeout->info; 1160 /* 1161 * Some more validations. 1162 */ 1163 if (pInfo->cParms > 4096) /* (Just make sure it doesn't overflow the next check.) */ 1164 { 1165 Log(("VBoxGuestCommonIOCtl: HGCM_CALL: cParm=%RX32 is not sane\n", pInfo->cParms)); 1166 return VERR_INVALID_PARAMETER; 1167 } 1168 const size_t cbActual = sizeof(*pInfoTimeout) + pInfo->cParms * sizeof(HGCMFunctionParameter); 1169 if (cbData < cbActual) 1170 { 1171 Log(("VBoxGuestCommonIOCtl: HGCM_CALL: cbData=%#zx (%zu) required size is %#zx (%zu)\n", 1172 cbData, cbActual)); 1173 return VERR_INVALID_PARAMETER; 1174 } 1175 1176 /* 1177 * Validate the client id. 1178 */ 1179 const uint32_t u32ClientId = pInfo->u32ClientID; 1180 unsigned i; 1181 RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; 1182 RTSpinlockAcquireNoInts(pDevExt->SessionSpinlock, &Tmp); 1183 for (i = 0; i < RT_ELEMENTS(pSession->aHGCMClientIds); i++) 1184 if (pSession->aHGCMClientIds[i] == u32ClientId) 1185 break; 1186 RTSpinlockReleaseNoInts(pDevExt->SessionSpinlock, &Tmp); 1187 if (RT_UNLIKELY(i >= RT_ELEMENTS(pSession->aHGCMClientIds))) 1188 { 1189 static unsigned s_cErrors = 0; 1190 if (s_cErrors++ > 32) 1191 LogRel(("VBoxGuestCommonIOCtl: HGCM_CALL: Invalid handle. u32Client=%RX32\n", u32ClientId)); 1192 return VERR_INVALID_HANDLE; 1193 } 1194 1195 /* 1196 * The VbglHGCMCall call will invoke the callback if the HGCM 1197 * call is performed in an ASYNC fashion. This function can 1198 * deal with cancelled requests, so we let user more requests 1199 * be interruptible (should add a flag for this later I guess). 1200 */ 1201 Log(("VBoxGuestCommonIOCtl: HGCM_CALL: u32Client=%RX32\n", pInfo->u32ClientID)); 1202 int rc = VbglHGCMCall(pInfo, VBoxGuestHGCMAsyncWaitCallbackTimeout, pDevExt, pInfoTimeout->u32Timeout); 1203 if (RT_SUCCESS(rc)) 1204 { 1205 Log(("VBoxGuestCommonIOCtl: HGCM_CALL: result=%Rrc\n", pInfo->result)); 1206 if (pcbDataReturned) 1207 *pcbDataReturned = cbActual; 1208 } 1209 Log(("VBoxGuestCommonIOCtl: HGCM_CALL: Failed. rc=%Rrc.\n", rc)); 1210 return rc; 1211 } 1212 #endif /* HGCM_TIMEOUT */ 1213 1214 1081 1215 /** 1082 1216 * @returns VBox status code. Unlike the other HGCM IOCtls this will combine … … 1223 1357 #ifdef VBOX_WITH_HGCM 1224 1358 /* 1225 * Th is one istricky and can be done later.1359 * These ones are tricky and can be done later. 1226 1360 */ 1227 1361 else if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_HGCM_CALL(0))) … … 1230 1364 rc = VBoxGuestCommonIOCtl_HGCMCall(pDevExt, pSession, (VBoxGuestHGCMCallInfo *)pvData, cbData, pcbDataReturned); 1231 1365 } 1366 #ifdef HGCM_TIMEOUT 1367 else if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_HGCM_CALL_TIMEOUT(0))) 1368 { 1369 CHECKRET_MIN_SIZE("HGCM_CALL", sizeof(VBoxGuestHGCMCallInfoTimeout)); 1370 rc = VBoxGuestCommonIOCtl_HGCMCallTimeout(pDevExt, pSession, (VBoxGuestHGCMCallInfoTimeout *)pvData, cbData, pcbDataReturned); 1371 } 1372 #endif /* HGCM_TIMEOUT */ 1232 1373 #endif /* VBOX_WITH_HGCM */ 1233 1374 else if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_LOG(0)))
Note:
See TracChangeset
for help on using the changeset viewer.