Changeset 32277 in vbox
- Timestamp:
- Sep 7, 2010 11:34:55 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/VBoxHDD.h
r31776 r32277 1031 1031 /** Error condition, hangup, exception or similar. */ 1032 1032 #define VD_INTERFACETCPNET_EVT_ERROR RT_BIT_32(2) 1033 /** Hint for the select that getting interrupted while waiting is more likely. 1034 * The interface implementation can optimize the waiting strategy based on this. 1035 * It is assumed that it is more likely to get one of the above socket events 1036 * instead of being interrupted if the flag is not set. */ 1037 #define VD_INTERFACETCPNET_HINT_INTERRUPT RT_BIT_32(3) 1033 1038 /** Mask of the valid bits. */ 1034 #define VD_INTERFACETCPNET_EVT_VALID_MASK UINT32_C(0x0000000 7)1039 #define VD_INTERFACETCPNET_EVT_VALID_MASK UINT32_C(0x0000000f) 1035 1040 /** @} */ 1036 1041 -
trunk/src/VBox/Devices/Storage/DrvVD.cpp
r31578 r32277 35 35 #include <iprt/poll.h> 36 36 #include <iprt/pipe.h> 37 #include <iprt/system.h> 37 38 38 39 #ifdef VBOX_WITH_INIP … … 1002 1003 } 1003 1004 } 1005 else 1006 { 1007 *pSock = pSockInt; 1008 return VINF_SUCCESS; 1009 } 1004 1010 1005 1011 RTMemFree(pSockInt); … … 1020 1026 { 1021 1027 rc = RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_SOCKET); 1022 Assert RC(rc);1028 Assert(RT_SUCCESS(rc) || rc == VERR_POLL_HANDLE_ID_NOT_FOUND); 1023 1029 } 1024 1030 rc = RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_PIPE); … … 1056 1062 rc = RTPollSetAddSocket(pSockInt->hPollSet, pSockInt->hSocket, 1057 1063 pSockInt->fEventsOld, VDSOCKET_POLL_ID_SOCKET); 1058 1059 if (RT_SUCCESS(rc)) 1060 return VINF_SUCCESS;1061 }1064 } 1065 1066 if (RT_SUCCESS(rc)) 1067 return VINF_SUCCESS; 1062 1068 1063 1069 rc = RTTcpClientClose(pSockInt->hSocket); … … 1181 1187 } 1182 1188 1183 /** @copydoc VDINTERFACETCPNET::pfnSelectOneEx */ 1184 static DECLCALLBACK(int) drvvdTcpSelectOneEx(VDSOCKET Sock, uint32_t fEvents, 1185 uint32_t *pfEvents, RTMSINTERVAL cMillies) 1189 static int drvvdTcpSelectOneExPoll(VDSOCKET Sock, uint32_t fEvents, 1190 uint32_t *pfEvents, RTMSINTERVAL cMillies) 1186 1191 { 1187 1192 int rc = VINF_SUCCESS; … … 1252 1257 } 1253 1258 } 1259 1260 return rc; 1261 } 1262 1263 /** @copydoc VDINTERFACETCPNET::pfnSelectOneEx */ 1264 static DECLCALLBACK(int) drvvdTcpSelectOneExNoPoll(VDSOCKET Sock, uint32_t fEvents, 1265 uint32_t *pfEvents, RTMSINTERVAL cMillies) 1266 { 1267 int rc = VINF_SUCCESS; 1268 PVDSOCKETINT pSockInt = (PVDSOCKETINT)Sock; 1269 1270 *pfEvents = 0; 1271 1272 ASMAtomicXchgBool(&pSockInt->fWaiting, true); 1273 if (ASMAtomicXchgBool(&pSockInt->fWokenUp, false)) 1274 { 1275 ASMAtomicXchgBool(&pSockInt->fWaiting, false); 1276 return VERR_INTERRUPTED; 1277 } 1278 1279 if ( pSockInt->hSocket == NIL_RTSOCKET 1280 || !fEvents) 1281 { 1282 /* 1283 * Only the pipe is configured or the caller doesn't wait for a socket event, 1284 * wait until there is something to read from the pipe. 1285 */ 1286 size_t cbRead = 0; 1287 char ch = 0; 1288 rc = RTPipeReadBlocking(pSockInt->hPipeR, &ch, 1, &cbRead); 1289 if (RT_SUCCESS(rc)) 1290 { 1291 Assert(cbRead == 1); 1292 rc = VERR_INTERRUPTED; 1293 ASMAtomicXchgBool(&pSockInt->fWokenUp, false); 1294 } 1295 } 1296 else 1297 { 1298 uint32_t fSelectEvents = 0; 1299 1300 if (fEvents & VD_INTERFACETCPNET_EVT_READ) 1301 fSelectEvents |= RTSOCKET_EVT_READ; 1302 if (fEvents & VD_INTERFACETCPNET_EVT_WRITE) 1303 fSelectEvents |= RTSOCKET_EVT_WRITE; 1304 if (fEvents & VD_INTERFACETCPNET_EVT_ERROR) 1305 fSelectEvents |= RTSOCKET_EVT_ERROR; 1306 1307 if (fEvents & VD_INTERFACETCPNET_HINT_INTERRUPT) 1308 { 1309 uint32_t fEventsRecv = 0; 1310 1311 /* Make sure the socket is not in the pollset. */ 1312 rc = RTPollSetRemove(pSockInt->hPollSet, VDSOCKET_POLL_ID_SOCKET); 1313 Assert(RT_SUCCESS(rc) || rc == VERR_POLL_HANDLE_ID_NOT_FOUND); 1314 1315 for (;;) 1316 { 1317 uint32_t id = 0; 1318 rc = RTPoll(pSockInt->hPollSet, 5, &fEvents, &id); 1319 if (rc == VERR_TIMEOUT) 1320 { 1321 /* Check the socket. */ 1322 rc = RTTcpSelectOneEx(pSockInt->hSocket, fSelectEvents, &fEventsRecv, 0); 1323 if (RT_SUCCESS(rc)) 1324 { 1325 if (fEventsRecv & RTSOCKET_EVT_READ) 1326 *pfEvents |= VD_INTERFACETCPNET_EVT_READ; 1327 if (fEventsRecv & RTSOCKET_EVT_WRITE) 1328 *pfEvents |= VD_INTERFACETCPNET_EVT_WRITE; 1329 if (fEventsRecv & RTSOCKET_EVT_ERROR) 1330 *pfEvents |= VD_INTERFACETCPNET_EVT_ERROR; 1331 break; /* Quit */ 1332 } 1333 else if (rc != VERR_TIMEOUT) 1334 break; 1335 } 1336 else if (RT_SUCCESS(rc)) 1337 { 1338 size_t cbRead = 0; 1339 uint8_t abBuf[10]; 1340 Assert(id == VDSOCKET_POLL_ID_PIPE); 1341 Assert((fEventsRecv & RTPOLL_EVT_VALID_MASK) == RTPOLL_EVT_READ); 1342 1343 /* We got interrupted, drain the pipe. */ 1344 rc = RTPipeRead(pSockInt->hPipeR, abBuf, sizeof(abBuf), &cbRead); 1345 AssertRC(rc); 1346 1347 ASMAtomicXchgBool(&pSockInt->fWokenUp, false); 1348 1349 rc = VERR_INTERRUPTED; 1350 break; 1351 } 1352 else 1353 break; 1354 } 1355 } 1356 else /* The caller waits for a socket event. */ 1357 { 1358 uint32_t fEventsRecv = 0; 1359 1360 /* Loop until we got woken up or a socket event occurred. */ 1361 for (;;) 1362 { 1363 /** @todo find an adaptive wait algorithm based on the 1364 * number of wakeups in the past. */ 1365 rc = RTTcpSelectOneEx(pSockInt->hSocket, fSelectEvents, &fEventsRecv, 5); 1366 if (rc == VERR_TIMEOUT) 1367 { 1368 /* Check if there is an event pending. */ 1369 size_t cbRead = 0; 1370 char ch = 0; 1371 rc = RTPipeRead(pSockInt->hPipeR, &ch, 1, &cbRead); 1372 if (RT_SUCCESS(rc) && rc != VINF_TRY_AGAIN) 1373 { 1374 Assert(cbRead == 1); 1375 rc = VERR_INTERRUPTED; 1376 ASMAtomicXchgBool(&pSockInt->fWokenUp, false); 1377 break; /* Quit */ 1378 } 1379 else 1380 Assert(rc == VINF_TRY_AGAIN); 1381 } 1382 else if (RT_SUCCESS(rc)) 1383 { 1384 if (fEventsRecv & RTSOCKET_EVT_READ) 1385 *pfEvents |= VD_INTERFACETCPNET_EVT_READ; 1386 if (fEventsRecv & RTSOCKET_EVT_WRITE) 1387 *pfEvents |= VD_INTERFACETCPNET_EVT_WRITE; 1388 if (fEventsRecv & RTSOCKET_EVT_ERROR) 1389 *pfEvents |= VD_INTERFACETCPNET_EVT_ERROR; 1390 break; /* Quit */ 1391 } 1392 else 1393 break; 1394 } 1395 } 1396 } 1397 1398 ASMAtomicXchgBool(&pSockInt->fWaiting, false); 1254 1399 1255 1400 return rc; … … 1892 2037 pThis->VDITcpNetCallbacks.pfnGetLocalAddress = drvvdTcpGetLocalAddress; 1893 2038 pThis->VDITcpNetCallbacks.pfnGetPeerAddress = drvvdTcpGetPeerAddress; 1894 pThis->VDITcpNetCallbacks.pfnSelectOneEx = drvvdTcpSelectOneEx; 2039 2040 /* 2041 * There is a 15ms delay between receiving the data and marking the socket 2042 * as readable on Windows XP which hurts async I/O performance of 2043 * TCP backends badly. Provide a different select method without 2044 * using poll on XP. 2045 * This is only used on XP because it is not as efficient as the one using poll 2046 * and all other Windows versions are working fine. 2047 */ 2048 char szOS[64]; 2049 memset(szOS, 0, sizeof(szOS)); 2050 rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, &szOS[0], sizeof(szOS)); 2051 2052 if (RT_SUCCESS(rc) && !strncmp(szOS, "Windows XP", 10)) 2053 { 2054 LogRel(("VD: Detected Windows XP, disabled poll based waiting for TCP\n")); 2055 pThis->VDITcpNetCallbacks.pfnSelectOneEx = drvvdTcpSelectOneExNoPoll; 2056 } 2057 else 2058 pThis->VDITcpNetCallbacks.pfnSelectOneEx = drvvdTcpSelectOneExPoll; 2059 1895 2060 pThis->VDITcpNetCallbacks.pfnPoke = drvvdTcpPoke; 1896 2061 }
Note:
See TracChangeset
for help on using the changeset viewer.