Changeset 3521 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Jul 10, 2007 11:40:06 AM (17 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DrvTAPOs2.cpp
r3481 r3521 1 /** $Id$ */ 1 2 /** @file 2 * 3 * VBox network devices: 4 * Linux TAP network transport driver 3 * VBox network devices: OS/2 TAP network transport driver. 5 4 */ 6 5 … … 22 21 * 23 22 */ 24 25 #define ASYNC_NET26 23 27 24 /******************************************************************************* … … 38 35 #include <iprt/file.h> 39 36 #include <iprt/string.h> 40 #ifdef ASYNC_NET41 37 #include <iprt/thread.h> 42 38 #include <iprt/asm.h> 43 39 #include <iprt/semaphore.h> 44 #endif45 46 #include <sys/ioctl.h>47 #include <sys/poll.h>48 #include <sys/fcntl.h>49 #include <errno.h>50 #ifdef ASYNC_NET51 #include <unistd.h>52 #endif53 40 54 41 #include "Builtins.h" 42 55 43 56 44 … … 58 46 * Structures and Typedefs * 59 47 *******************************************************************************/ 60 typedef enum ASYNCSTATE61 {62 //ASYNCSTATE_SUSPENDED = 1,63 ASYNCSTATE_RUNNING,64 ASYNCSTATE_TERMINATE65 } ASYNCSTATE;66 48 67 49 /** 68 50 * Block driver instance data. 69 51 */ 70 typedef struct DRVTAP 52 typedef struct DRVTAPOS2 71 53 { 72 54 /** The network interface. */ … … 78 60 /** TAP device file handle. */ 79 61 RTFILE FileDevice; 80 #ifdef ASYNC_NET 81 /** The write end of the control pipe. */ 82 RTFILE PipeWrite; 83 /** The read end of the control pipe. */ 84 RTFILE PipeRead; 85 /** The thread state. */ 86 ASYNCSTATE volatile enmState; 87 /** Reader thread. */ 88 RTTHREAD Thread; 62 /** Receiver thread. */ 63 PPDMTHREAD pThread; 89 64 /** We are waiting for more receive buffers. */ 90 65 uint32_t volatile fOutOfSpace; 91 66 /** Event semaphore for blocking on receive. */ 92 67 RTSEMEVENT EventOutOfSpace; 93 #endif94 68 95 69 #ifdef VBOX_WITH_STATISTICS … … 106 80 /** Profiling packet receive runs. */ 107 81 STAMPROFILEADV StatReceive; 108 #ifdef ASYNC_NET109 82 STAMPROFILE StatRecvOverflows; 110 #endif111 83 #endif /* VBOX_WITH_STATISTICS */ 112 84 … … 117 89 uint64_t u64LastReceiveTS; 118 90 #endif 119 } DRVTAP , *PDRVTAP;91 } DRVTAPOS2, *PDRVTAPOS2; 120 92 121 93 122 94 /** Converts a pointer to TAP::INetworkConnector to a PRDVTAP. */ 123 #define PDMINETWORKCONNECTOR_2_DRVTAP (pInterface) ( (PDRVTAP)((uintptr_t)pInterface - RT_OFFSETOF(DRVTAP, INetworkConnector)) )95 #define PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface) ( (PDRVTAPOS2)((uintptr_t)pInterface - RT_OFFSETOF(DRVTAPOS2, INetworkConnector)) ) 124 96 125 97 … … 133 105 * @thread EMT 134 106 */ 135 static DECLCALLBACK(int) drvTAP Send(PPDMINETWORKCONNECTOR pInterface, const void *pvBuf, size_t cb)136 { 137 PDRVTAP pData = PDMINETWORKCONNECTOR_2_DRVTAP(pInterface);107 static DECLCALLBACK(int) drvTAPOs2Send(PPDMINETWORKCONNECTOR pInterface, const void *pvBuf, size_t cb) 108 { 109 PDRVTAPOS2 pData = PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface); 138 110 STAM_COUNTER_INC(&pData->StatPktSent); 139 111 STAM_COUNTER_ADD(&pData->StatPktSentBytes, cb); … … 142 114 #ifdef LOG_ENABLED 143 115 uint64_t u64Now = RTTimeProgramNanoTS(); 144 LogFlow(("drvTAP Send: %-4d bytes at %llu ns deltas: r=%llu t=%llu\n",116 LogFlow(("drvTAPOs2Send: %-4d bytes at %llu ns deltas: r=%llu t=%llu\n", 145 117 cb, u64Now, u64Now - pData->u64LastReceiveTS, u64Now - pData->u64LastTransferTS)); 146 118 pData->u64LastTransferTS = u64Now; 147 119 #endif 148 Log2(("drvTAP Send: pvBuf=%p cb=%#x\n"120 Log2(("drvTAPOs2Send: pvBuf=%p cb=%#x\n" 149 121 "%.*Vhxd\n", 150 122 pvBuf, cb, cb, pvBuf)); 151 123 152 int rc = RTFileWrite(pData->FileDevice, pvBuf, cb, NULL); 124 ULONG UnusedParms[10] = { 0,0,0,0, 0,0,0,0, 0,0 }; 125 ULONG cbParms = sizeof(UnusedParms); 126 ULONG cbData = cb; 127 int rc = DosDevIOCtl(pData->FileDevice, PROT_CATEGORY, TAP_WRITE_PACKET, 128 &UnusedParms[0], cbParms, &cbParms, 129 pvBuf, cbData, &cbData); 130 if (rc) 131 rc = RTErrConvertFromOS2(rc); 153 132 154 133 STAM_PROFILE_STOP(&pData->StatTransmit, a); … … 168 147 * @thread EMT 169 148 */ 170 static DECLCALLBACK(void) drvTAP SetPromiscuousMode(PPDMINETWORKCONNECTOR pInterface, bool fPromiscuous)171 { 172 LogFlow(("drvTAP SetPromiscuousMode: fPromiscuous=%d\n", fPromiscuous));149 static DECLCALLBACK(void) drvTAPOs2SetPromiscuousMode(PPDMINETWORKCONNECTOR pInterface, bool fPromiscuous) 150 { 151 LogFlow(("drvTAPOs2SetPromiscuousMode: fPromiscuous=%d\n", fPromiscuous)); 173 152 /* nothing to do */ 174 153 } … … 182 161 * @thread EMT 183 162 */ 184 static DECLCALLBACK(void) drvTAP NotifyLinkChanged(PPDMINETWORKCONNECTOR pInterface, PDMNETWORKLINKSTATE enmLinkState)163 static DECLCALLBACK(void) drvTAPOs2NotifyLinkChanged(PPDMINETWORKCONNECTOR pInterface, PDMNETWORKLINKSTATE enmLinkState) 185 164 { 186 165 LogFlow(("drvNATNotifyLinkChanged: enmLinkState=%d\n", enmLinkState)); … … 197 176 * @thread EMT 198 177 */ 199 static DECLCALLBACK(void) drvTAP NotifyCanReceive(PPDMINETWORKCONNECTOR pInterface)200 { 201 PDRVTAP pData = PDMINETWORKCONNECTOR_2_DRVTAP(pInterface);202 203 LogFlow(("drvTAP NotifyCanReceive:\n"));178 static DECLCALLBACK(void) drvTAPOs2NotifyCanReceive(PPDMINETWORKCONNECTOR pInterface) 179 { 180 PDRVTAPOS2 pData = PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface); 181 182 LogFlow(("drvTAPOs2NotifyCanReceive:\n")); 204 183 /* ensure we wake up only once */ 205 184 if (ASMAtomicXchgU32(&pData->fOutOfSpace, false)) … … 208 187 209 188 210 #ifdef ASYNC_NET211 189 /** 212 190 * Asynchronous I/O thread for handling receive. 213 191 * 214 192 * @returns VINF_SUCCESS (ignored). 215 * @param Thread Thread handle. 216 * @param pvUser Pointer to a DRVTAP structure. 217 */ 218 static DECLCALLBACK(int) drvTAPAsyncIoThread(RTTHREAD ThreadSelf, void *pvUser) 219 { 220 PDRVTAP pData = (PDRVTAP)pvUser; 221 LogFlow(("drvTAPAsyncIoThread: pData=%p\n", pData)); 222 STAM_PROFILE_ADV_START(&pData->StatReceive, a); 223 224 int rc = RTSemEventCreate(&pData->EventOutOfSpace); 225 AssertRC(rc); 226 227 /* 228 * Polling loop. 193 * @param pDrvIns The driver instance. 194 * @param pThread The PDM thread structure. 195 */ 196 static DECLCALLBACK(int) drvTAPOs2AsyncIoThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 197 { 198 PDRVTAPOS2 pData = PDMINS2DATA(pDrvIns, PDRVTAPOS2); 199 LogFlow(("drvTAPOs2AsyncIoThread: pData=%p\n", pData)); 200 Assert(pThread->enmState == PDMTHREADSTATE_INITIALIZING); 201 202 203 /* 204 * Outer loop. 229 205 */ 230 206 for (;;) 231 207 { 232 208 /* 233 * Wait for something to become available.209 * 234 210 */ 235 struct pollfd aFDs[2]; 236 aFDs[0].fd = pData->FileDevice; 237 aFDs[0].events = POLLIN | POLLPRI; 238 aFDs[0].revents = 0; 239 aFDs[1].fd = pData->PipeRead; 240 aFDs[1].events = POLLIN | POLLPRI | POLLERR | POLLHUP; 241 aFDs[1].revents = 0; 242 STAM_PROFILE_ADV_STOP(&pData->StatReceive, a); 243 errno=0; 244 rc = poll(&aFDs[0], ELEMENTS(aFDs), -1 /* infinite */); 245 STAM_PROFILE_ADV_START(&pData->StatReceive, a); 246 if ( rc > 0 247 && (aFDs[0].revents & (POLLIN | POLLPRI)) 248 && !aFDs[1].revents) 211 PDMR3ThreadSuspend(pThread); 212 if (pThread->enmState != PDMTHREADSTATE_RESUMING) 213 break; 214 249 215 { 216 } 217 } 218 219 220 221 222 STAM_PROFILE_ADV_START(&pData->StatReceive, a); 223 224 /* 225 * Polling loop. 226 */ 227 for (;;) 228 { 229 /* 230 * Read/wait the frame. 231 */ 232 char achBuf[4096]; 233 ULONG cbParm = ; 234 ULONG cbRead = 0; 235 int LanNumber; 236 237 int rc = DosDevIOCtl(pData->FileDevice, PROT_CATEGORY, TAP_CANCEL_READ, 238 &UnusedParms[0], cbParm, &cbParm, 239 &achBuf[0], cbRead, &cbRead); 240 if (rc == NO_ERROR) 241 { 242 AssertMsg(cbRead <= 1536, ("cbRead=%d\n", cbRead)); 243 250 244 /* 251 * Read theframe.245 * Wait for the device to have space for this frame. 252 246 */ 253 char achBuf[4096]; 254 unsigned cbRead = 0; 255 rc = RTFileRead(pData->FileDevice, achBuf, sizeof(achBuf), &cbRead); 256 if (VBOX_SUCCESS(rc)) 247 size_t cbMax = pData->pPort->pfnCanReceive(pData->pPort); 248 if (cbMax < cbRead) 257 249 { 258 AssertMsg(cbRead <= 1536, ("cbRead=%d\n", cbRead)); 259 260 /* 261 * Wait for the device to have space for this frame. 262 */ 263 size_t cbMax = pData->pPort->pfnCanReceive(pData->pPort); 264 if (cbMax < cbRead) 250 /** @todo receive overflow handling needs serious improving! */ 251 STAM_PROFILE_ADV_STOP(&pData->StatReceive, a); 252 STAM_PROFILE_START(&pData->StatRecvOverflows, b); 253 while ( cbMax < cbRead 254 && pData->enmState != ASYNCSTATE_TERMINATE) 265 255 { 266 /** @todo receive overflow handling needs serious improving! */ 267 STAM_PROFILE_ADV_STOP(&pData->StatReceive, a); 268 STAM_PROFILE_START(&pData->StatRecvOverflows, b); 269 while ( cbMax < cbRead 270 && pData->enmState != ASYNCSTATE_TERMINATE) 271 { 272 LogFlow(("drvTAPAsyncIoThread: cbMax=%d cbRead=%d waiting...\n", cbMax, cbRead)); 256 LogFlow(("drvTAPOs2AsyncIoThread: cbMax=%d cbRead=%d waiting...\n", cbMax, cbRead)); 273 257 #if 1 274 275 276 258 /* We get signalled by the network driver. 50ms is just for sanity */ 259 ASMAtomicXchgU32(&pData->fOutOfSpace, true); 260 RTSemEventWait(pData->EventOutOfSpace, 50); 277 261 #else 278 262 RTThreadSleep(1); 279 263 #endif 280 cbMax = pData->pPort->pfnCanReceive(pData->pPort); 281 } 282 ASMAtomicXchgU32(&pData->fOutOfSpace, false); 283 STAM_PROFILE_STOP(&pData->StatRecvOverflows, b); 284 STAM_PROFILE_ADV_START(&pData->StatReceive, a); 285 if (pData->enmState == ASYNCSTATE_TERMINATE) 286 break; 264 cbMax = pData->pPort->pfnCanReceive(pData->pPort); 287 265 } 288 289 /* 290 * Pass the data up. 291 */ 266 ASMAtomicXchgU32(&pData->fOutOfSpace, false); 267 STAM_PROFILE_STOP(&pData->StatRecvOverflows, b); 268 STAM_PROFILE_ADV_START(&pData->StatReceive, a); 269 if (pData->enmState == ASYNCSTATE_TERMINATE) 270 break; 271 } 272 273 /* 274 * Pass the data up. 275 */ 292 276 #ifdef LOG_ENABLED 293 294 LogFlow(("drvTAPAsyncIoThread: %-4d bytes at %llu ns deltas: r=%llu t=%llu\n",295 296 277 uint64_t u64Now = RTTimeProgramNanoTS(); 278 LogFlow(("drvTAPOs2AsyncIoThread: %-4d bytes at %llu ns deltas: r=%llu t=%llu\n", 279 cbRead, u64Now, u64Now - pData->u64LastReceiveTS, u64Now - pData->u64LastTransferTS)); 280 pData->u64LastReceiveTS = u64Now; 297 281 #endif 298 Log2(("drvTAPAsyncIoThread: cbRead=%#x\n" 299 "%.*Vhxd\n", 300 cbRead, cbRead, achBuf)); 301 STAM_COUNTER_INC(&pData->StatPktRecv); 302 STAM_COUNTER_ADD(&pData->StatPktRecvBytes, cbRead); 303 rc = pData->pPort->pfnReceive(pData->pPort, achBuf, cbRead); 304 AssertRC(rc); 305 } 306 else 307 { 308 LogFlow(("drvTAPAsyncIoThread: RTFileRead -> %Vrc\n", rc)); 309 if (rc == VERR_INVALID_HANDLE) 310 break; 311 RTThreadYield(); 312 } 313 } 314 else if ( rc > 0 315 && aFDs[1].revents) 316 { 317 LogFlow(("drvTAPAsyncIoThread: Control message: enmState=%d revents=%#x\n", pData->enmState, aFDs[1].revents)); 318 if (pData->enmState == ASYNCSTATE_TERMINATE) 319 break; 320 if (aFDs[1].revents & (POLLHUP | POLLERR | POLLNVAL)) 321 break; 322 323 /* drain the pipe */ 324 char ch; 325 unsigned cbRead; 326 RTFileRead(pData->PipeRead, &ch, 1, &cbRead); 282 Log2(("drvTAPOs2AsyncIoThread: cbRead=%#x\n" 283 "%.*Vhxd\n", 284 cbRead, cbRead, achBuf)); 285 STAM_COUNTER_INC(&pData->StatPktRecv); 286 STAM_COUNTER_ADD(&pData->StatPktRecvBytes, cbRead); 287 rc = pData->pPort->pfnReceive(pData->pPort, achBuf, cbRead); 288 AssertRC(rc); 327 289 } 328 290 else 329 291 { 330 /* 331 * poll() failed for some reason. Yield to avoid eating too much CPU. 332 * 333 * EINTR errors have been seen frequently. They should be harmless, even 334 * if they are not supposed to occur in our setup. 335 */ 336 if (errno == EINTR) 337 Log(("rc=%d revents=%#x,%#x errno=%p %s\n", rc, aFDs[0].revents, aFDs[1].revents, errno, strerror(errno))); 338 else 339 AssertMsgFailed(("rc=%d revents=%#x,%#x errno=%p %s\n", rc, aFDs[0].revents, aFDs[1].revents, errno, strerror(errno))); 292 LogFlow(("drvTAPOs2AsyncIoThread: RTFileRead -> %Vrc\n", rc)); 293 if (rc == VERR_INVALID_HANDLE) 294 break; 340 295 RTThreadYield(); 341 296 } 342 297 } 343 298 344 rc = RTSemEventDestroy(pData->EventOutOfSpace); 345 AssertRC(rc); 346 347 LogFlow(("drvTAPAsyncIoThread: returns %Vrc\n", VINF_SUCCESS)); 299 LogFlow(("drvTAPOs2AsyncIoThread: returns %Vrc\n", VINF_SUCCESS)); 348 300 STAM_PROFILE_ADV_STOP(&pData->StatReceive, a); 349 301 return VINF_SUCCESS; 350 302 } 351 352 #else353 /**354 * Poller callback.355 */356 static DECLCALLBACK(void) drvTAPPoller(PPDMDRVINS pDrvIns)357 {358 /* check how much the device/driver can receive now. */359 PDRVTAP pData = PDMINS2DATA(pDrvIns, PDRVTAP);360 STAM_PROFILE_ADV_START(&pData->StatReceive, a);361 362 size_t cbMax = pData->pPort->pfnCanReceive(pData->pPort);363 while (cbMax > 0)364 {365 /* check for data to read */366 struct pollfd aFDs[1];367 aFDs[0].fd = pData->FileDevice;368 aFDs[0].events = POLLIN | POLLPRI;369 aFDs[0].revents = 0;370 if (poll(&aFDs[0], 1, 0) > 0)371 {372 if (aFDs[0].revents & (POLLIN | POLLPRI))373 {374 /* data waiting, read it. */375 char achBuf[4096];376 unsigned cbRead = 0;377 int rc = RTFileRead(pData->FileDevice, achBuf, RT_MIN(sizeof(achBuf), cbMax), &cbRead);378 if (VBOX_SUCCESS(rc))379 {380 STAM_COUNTER_INC(&pData->StatPktRecv);381 STAM_COUNTER_ADD(&pData->StatPktRecvBytes, cbRead);382 383 /* push it up to guy over us. */384 Log2(("drvTAPPoller: cbRead=%#x\n"385 "%.*Vhxd\n",386 cbRead, cbRead, achBuf));387 rc = pData->pPort->pfnReceive(pData->pPort, achBuf, cbRead);388 AssertRC(rc);389 }390 else391 AssertRC(rc);392 if (VBOX_FAILURE(rc) || !cbRead)393 break;394 }395 else396 break;397 }398 else399 break;400 401 cbMax = pData->pPort->pfnCanReceive(pData->pPort);402 }403 404 STAM_PROFILE_ADV_STOP(&pData->StatReceive, a);405 }406 #endif407 303 408 304 … … 416 312 * @thread Any thread. 417 313 */ 418 static DECLCALLBACK(void *) drvTAP QueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)314 static DECLCALLBACK(void *) drvTAPOs2QueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface) 419 315 { 420 316 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); 421 PDRVTAP pData = PDMINS2DATA(pDrvIns, PDRVTAP);317 PDRVTAPOS2 pData = PDMINS2DATA(pDrvIns, PDRVTAPOS2); 422 318 switch (enmInterface) 423 319 { … … 440 336 * @param pDrvIns The driver instance data. 441 337 */ 442 static DECLCALLBACK(void) drvTAPDestruct(PPDMDRVINS pDrvIns) 443 { 444 LogFlow(("drvTAPDestruct\n")); 445 #ifdef ASYNC_NET 446 PDRVTAP pData = PDMINS2DATA(pDrvIns, PDRVTAP); 447 448 /* 449 * Terminate the Async I/O Thread. 450 */ 451 ASMAtomicXchgSize(&pData->enmState, ASYNCSTATE_TERMINATE); 452 if (pData->Thread != NIL_RTTHREAD) 338 static DECLCALLBACK(void) drvTAPOs2Destruct(PPDMDRVINS pDrvIns) 339 { 340 LogFlow(("drvTAPOs2Destruct\n")); 341 PDRVTAPOS2 pData = PDMINS2DATA(pDrvIns, PDRVTAPOS2); 342 343 /* 344 * Destroy the event semaphore. 345 */ 346 if (pData->EventOutOfSpace != NIL_RTSEMEVENTMULTI) 453 347 { 454 /* Ensure that it does not spin in the CanReceive loop */ 455 if (ASMAtomicXchgU32(&pData->fOutOfSpace, false)) 456 RTSemEventSignal(pData->EventOutOfSpace); 457 458 int rc = RTFileWrite(pData->PipeWrite, "", 1, NULL); 348 rc = RTSemEventDestroy(pData->EventOutOfSpace); 459 349 AssertRC(rc); 460 rc = RTThreadWait(pData->Thread, 5000, NULL); 461 AssertRC(rc); 462 pData->Thread = NIL_RTTHREAD; 350 pData->EventOutOfSpace = NIL_RTSEMEVENTMULTI; 463 351 } 464 465 /*466 * Terminate the control pipe.467 */468 if (pData->PipeWrite != NIL_RTFILE)469 {470 int rc = RTFileClose(pData->PipeWrite);471 AssertRC(rc);472 pData->PipeWrite = NIL_RTFILE;473 }474 if (pData->PipeRead != NIL_RTFILE)475 {476 int rc = RTFileClose(pData->PipeRead);477 AssertRC(rc);478 pData->PipeRead = NIL_RTFILE;479 }480 #endif481 352 } 482 353 … … 492 363 * iInstance it's expected to be used a bit in this function. 493 364 */ 494 static DECLCALLBACK(int) drvTAP Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)495 { 496 PDRVTAP pData = PDMINS2DATA(pDrvIns, PDRVTAP);365 static DECLCALLBACK(int) drvTAPOs2Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle) 366 { 367 PDRVTAPOS2 pData = PDMINS2DATA(pDrvIns, PDRVTAPOS2); 497 368 498 369 /* … … 501 372 pData->pDrvIns = pDrvIns; 502 373 pData->FileDevice = NIL_RTFILE; 503 #ifdef ASYNC_NET504 374 pData->Thread = NIL_RTTHREAD; 505 375 pData->enmState = ASYNCSTATE_RUNNING; 506 #endif507 376 /* IBase */ 508 pDrvIns->IBase.pfnQueryInterface = drvTAP QueryInterface;377 pDrvIns->IBase.pfnQueryInterface = drvTAPOs2QueryInterface; 509 378 /* INetwork */ 510 pData->INetworkConnector.pfnSend = drvTAP Send;511 pData->INetworkConnector.pfnSetPromiscuousMode = drvTAP SetPromiscuousMode;512 pData->INetworkConnector.pfnNotifyLinkChanged = drvTAP NotifyLinkChanged;513 pData->INetworkConnector.pfnNotifyCanReceive = drvTAP NotifyCanReceive;379 pData->INetworkConnector.pfnSend = drvTAPOs2Send; 380 pData->INetworkConnector.pfnSetPromiscuousMode = drvTAPOs2SetPromiscuousMode; 381 pData->INetworkConnector.pfnNotifyLinkChanged = drvTAPOs2NotifyLinkChanged; 382 pData->INetworkConnector.pfnNotifyCanReceive = drvTAPOs2NotifyCanReceive; 514 383 515 384 /* … … 557 426 return PDMDrvHlpVMSetError(pDrvIns, VERR_HOSTIF_IOCTL, RT_SRC_POS, 558 427 N_("Configuration error: Failed to configure /dev/net/tun. errno=%d"), errno); 559 /** @todo determine device name. This can be done by reading the link /proc/<pid>/fd/<fd> */ 560 Log(("drvTAPContruct: %d (from fd)\n", pData->FileDevice)); 428 Log(("drvTAPOs2Contruct: %d (from fd)\n", pData->FileDevice)); 561 429 rc = VINF_SUCCESS; 562 430 563 #ifdef ASYNC_NET 564 /* 565 * Create the control pipe. 566 */ 567 int fds[2]; 568 if (pipe(&fds[0]) != 0) /** @todo RTPipeCreate() or something... */ 569 { 570 int rc = RTErrConvertFromErrno(errno); 571 AssertRC(rc); 572 return rc; 573 } 574 pData->PipeRead = fds[0]; 575 pData->PipeWrite = fds[1]; 576 577 /* 578 * Create the async I/O thread. 579 */ 580 rc = RTThreadCreate(&pData->Thread, drvTAPAsyncIoThread, pData, 128*_1K, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "TAP"); 431 /* 432 * Create the out-of-space semaphore and the async receiver thread. 433 */ 434 rc = RTSemEventCreate(&pData->EventOutOfSpace); 581 435 AssertRCReturn(rc, rc); 582 #else 583 /* 584 * Register poller 585 */ 586 rc = pDrvIns->pDrvHlp->pfnPDMPollerRegister(pDrvIns, drvTAPPoller); 436 437 rc = PDMDrvHlpThreadCreate(pDrvIns, &pData->pThread, pData, drvTAPOs2AsyncIoThread, drvTAPOs2WakeupThread, 438 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "TAP"); 587 439 AssertRCReturn(rc, rc); 588 #endif589 440 590 441 #ifdef VBOX_WITH_STATISTICS … … 598 449 PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatTransmit, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling packet transmit runs.", "/Drivers/TAP%d/Transmit", pDrvIns->iInstance); 599 450 PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatReceive, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling packet receive runs.", "/Drivers/TAP%d/Receive", pDrvIns->iInstance); 600 # ifdef ASYNC_NET601 451 PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatRecvOverflows, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, "Profiling packet receive overflows.", "/Drivers/TAP%d/RecvOverflows", pDrvIns->iInstance); 602 # endif603 452 #endif /* VBOX_WITH_STATISTICS */ 604 453 … … 625 474 ~0, 626 475 /* cbInstance */ 627 sizeof(DRVTAP ),476 sizeof(DRVTAPOS2), 628 477 /* pfnConstruct */ 629 drvTAP Construct,478 drvTAPOs2Construct, 630 479 /* pfnDestruct */ 631 drvTAP Destruct,480 drvTAPOs2Destruct, 632 481 /* pfnIOCtl */ 633 482 NULL, … … 637 486 NULL, 638 487 /* pfnSuspend */ 639 NULL, /** @todo Do power on, suspend and resume handlers! */488 NULL, 640 489 /* pfnResume */ 641 490 NULL,
Note:
See TracChangeset
for help on using the changeset viewer.