Changeset 44469 in vbox for trunk/src/VBox/Runtime/r3/poll.cpp
- Timestamp:
- Jan 30, 2013 3:37:55 PM (12 years ago)
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/poll.cpp
r44420 r44469 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - Polling I/O Handles, Windows Implementation. 4 * 5 * @todo merge poll-win.cpp and poll-posix.cpp, there is lots of common code. 3 * IPRT - Polling I/O Handles, Windows+Posix Implementation. 6 4 */ 7 5 8 6 /* 9 * Copyright (C) 2010 Oracle Corporation7 * Copyright (C) 2010-2013 Oracle Corporation 10 8 * 11 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 31 29 * Header Files * 32 30 *******************************************************************************/ 33 #include <Windows.h> 31 #include <iprt/cdefs.h> 32 #ifdef RT_OS_WINDOWS 33 # include <Windows.h> 34 #else 35 # include <limits.h> 36 # include <errno.h> 37 # include <sys/poll.h> 38 #endif 34 39 35 40 #include <iprt/poll.h> … … 41 46 #include <iprt/mem.h> 42 47 #include <iprt/pipe.h> 48 #include <iprt/socket.h> 43 49 #include <iprt/string.h> 44 50 #include <iprt/thread.h> … … 49 55 #include "internal/socket.h" 50 56 #include "internal/magics.h" 57 58 59 /******************************************************************************* 60 * Defined Constants And Macros * 61 *******************************************************************************/ 62 /** The maximum poll set size. 63 * @remarks To help portability, we set this to the Windows limit. We can lift 64 * this restriction later if it becomes necessary. */ 65 #define RTPOLL_SET_MAX 64 66 51 67 52 68 … … 77 93 78 94 /** 79 * Poll set data , Windows.95 * Poll set data. 80 96 */ 81 97 typedef struct RTPOLLSETINTERNAL … … 88 104 /** The number of valid handles in the set. */ 89 105 uint32_t cHandles; 90 /** The native handles. */ 91 HANDLE ahNative[MAXIMUM_WAIT_OBJECTS]; 92 /** Array of handles and IDs. */ 93 RTPOLLSETHNDENT aHandles[MAXIMUM_WAIT_OBJECTS]; 106 /** The number of allocated handles. */ 107 uint32_t cHandlesAllocated; 108 109 #ifdef RT_OS_WINDOWS 110 /** Pointer to an array of native handles. */ 111 HANDLE *pahNative; 112 #else 113 /** Pointer to an array of pollfd structures. */ 114 struct pollfd *paPollFds; 115 #endif 116 /** Pointer to an array of handles and IDs. */ 117 RTPOLLSETHNDENT *paHandles; 94 118 } RTPOLLSETINTERNAL; 119 95 120 96 121 … … 117 142 } 118 143 144 #ifdef RT_OS_WINDOWS 119 145 /* 120 146 * Check + prepare the handles before waiting. … … 125 151 for (i = 0; i < cHandles; i++) 126 152 { 127 switch (pThis-> aHandles[i].enmType)153 switch (pThis->paHandles[i].enmType) 128 154 { 129 155 case RTHANDLETYPE_PIPE: 130 fEvents = rtPipePollStart(pThis-> aHandles[i].u.hPipe, pThis, pThis->aHandles[i].fEvents,131 pThis-> aHandles[i].fFinalEntry, fNoWait);156 fEvents = rtPipePollStart(pThis->paHandles[i].u.hPipe, pThis, pThis->paHandles[i].fEvents, 157 pThis->paHandles[i].fFinalEntry, fNoWait); 132 158 break; 133 159 134 160 case RTHANDLETYPE_SOCKET: 135 fEvents = rtSocketPollStart(pThis-> aHandles[i].u.hSocket, pThis, pThis->aHandles[i].fEvents,136 pThis-> aHandles[i].fFinalEntry, fNoWait);161 fEvents = rtSocketPollStart(pThis->paHandles[i].u.hSocket, pThis, pThis->paHandles[i].fEvents, 162 pThis->paHandles[i].fFinalEntry, fNoWait); 137 163 break; 138 164 … … 150 176 151 177 if (pid) 152 *pid = pThis-> aHandles[i].id;178 *pid = pThis->paHandles[i].id; 153 179 if (pfEvents) 154 180 *pfEvents = fEvents; … … 163 189 while (i-- > 0) 164 190 { 165 switch (pThis-> aHandles[i].enmType)191 switch (pThis->paHandles[i].enmType) 166 192 { 167 193 case RTHANDLETYPE_PIPE: 168 rtPipePollDone(pThis-> aHandles[i].u.hPipe, pThis->aHandles[i].fEvents,169 pThis-> aHandles[i].fFinalEntry, false);194 rtPipePollDone(pThis->paHandles[i].u.hPipe, pThis->paHandles[i].fEvents, 195 pThis->paHandles[i].fFinalEntry, false); 170 196 break; 171 197 172 198 case RTHANDLETYPE_SOCKET: 173 rtSocketPollDone(pThis-> aHandles[i].u.hSocket, pThis->aHandles[i].fEvents,174 pThis-> aHandles[i].fFinalEntry, false);199 rtSocketPollDone(pThis->paHandles[i].u.hSocket, pThis->paHandles[i].fEvents, 200 pThis->paHandles[i].fFinalEntry, false); 175 201 break; 176 202 … … 187 213 * Wait. 188 214 */ 189 DWORD dwRc = WaitForMultipleObjectsEx(cHandles, &pThis->ahNative[0],215 DWORD dwRc = WaitForMultipleObjectsEx(cHandles, pThis->pahNative, 190 216 FALSE /*fWaitAll */, 191 217 cMillies == RT_INDEFINITE_WAIT ? INFINITE : cMillies, … … 213 239 { 214 240 fEvents = 0; 215 switch (pThis-> aHandles[i].enmType)241 switch (pThis->paHandles[i].enmType) 216 242 { 217 243 case RTHANDLETYPE_PIPE: 218 fEvents = rtPipePollDone(pThis-> aHandles[i].u.hPipe, pThis->aHandles[i].fEvents,219 pThis-> aHandles[i].fFinalEntry, fHarvestEvents);244 fEvents = rtPipePollDone(pThis->paHandles[i].u.hPipe, pThis->paHandles[i].fEvents, 245 pThis->paHandles[i].fFinalEntry, fHarvestEvents); 220 246 break; 221 247 222 248 case RTHANDLETYPE_SOCKET: 223 fEvents = rtSocketPollDone(pThis-> aHandles[i].u.hSocket, pThis->aHandles[i].fEvents,224 pThis-> aHandles[i].fFinalEntry, fHarvestEvents);249 fEvents = rtSocketPollDone(pThis->paHandles[i].u.hSocket, pThis->paHandles[i].fEvents, 250 pThis->paHandles[i].fFinalEntry, fHarvestEvents); 225 251 break; 226 252 … … 237 263 *pfEvents = fEvents; 238 264 if (pid) 239 *pid = pThis-> aHandles[i].id;265 *pid = pThis->paHandles[i].id; 240 266 rc = VINF_SUCCESS; 241 267 } 242 268 } 269 270 #else /* POSIX */ 271 272 /* clear the revents. */ 273 uint32_t i = pThis->cHandles; 274 while (i-- > 0) 275 pThis->paPollFds[i].revents = 0; 276 277 int rc = poll(&pThis->paPollFds[0], pThis->cHandles, 278 cMillies == RT_INDEFINITE_WAIT || cMillies >= INT_MAX 279 ? -1 280 : (int)cMillies); 281 if (rc == 0) 282 return VERR_TIMEOUT; 283 if (rc < 0) 284 return RTErrConvertFromErrno(errno); 285 for (i = 0; i < pThis->cHandles; i++) 286 if (pThis->paPollFds[i].revents) 287 { 288 if (pfEvents) 289 { 290 *pfEvents = 0; 291 if (pThis->paPollFds[i].revents & (POLLIN 292 # ifdef POLLRDNORM 293 | POLLRDNORM /* just in case */ 294 # endif 295 # ifdef POLLRDBAND 296 | POLLRDBAND /* ditto */ 297 # endif 298 # ifdef POLLPRI 299 | POLLPRI /* ditto */ 300 # endif 301 # ifdef POLLMSG 302 | POLLMSG /* ditto */ 303 # endif 304 # ifdef POLLWRITE 305 | POLLWRITE /* ditto */ 306 # endif 307 # ifdef POLLEXTEND 308 | POLLEXTEND /* ditto */ 309 # endif 310 ) 311 ) 312 *pfEvents |= RTPOLL_EVT_READ; 313 314 if (pThis->paPollFds[i].revents & (POLLOUT 315 # ifdef POLLWRNORM 316 | POLLWRNORM /* just in case */ 317 # endif 318 # ifdef POLLWRBAND 319 | POLLWRBAND /* ditto */ 320 # endif 321 ) 322 ) 323 *pfEvents |= RTPOLL_EVT_WRITE; 324 325 if (pThis->paPollFds[i].revents & (POLLERR | POLLHUP | POLLNVAL 326 # ifdef POLLRDHUP 327 | POLLRDHUP 328 # endif 329 ) 330 ) 331 *pfEvents |= RTPOLL_EVT_ERROR; 332 } 333 if (pid) 334 *pid = pThis->paHandles[i].id; 335 return VINF_SUCCESS; 336 } 337 338 AssertFailed(); 339 RTThreadYield(); 340 rc = VERR_INTERRUPTED; 341 342 #endif /* POSIX */ 243 343 244 344 return rc; … … 310 410 { 311 411 AssertPtrReturn(phPollSet, VERR_INVALID_POINTER); 312 RTPOLLSETINTERNAL *pThis = (RTPOLLSETINTERNAL *)RTMemAlloc Z(sizeof(RTPOLLSETINTERNAL));412 RTPOLLSETINTERNAL *pThis = (RTPOLLSETINTERNAL *)RTMemAlloc(sizeof(RTPOLLSETINTERNAL)); 313 413 if (!pThis) 314 414 return VERR_NO_MEMORY; … … 317 417 pThis->fBusy = false; 318 418 pThis->cHandles = 0; 319 for (size_t i = 0; i < RT_ELEMENTS(pThis->ahNative); i++) 320 pThis->ahNative[i] = INVALID_HANDLE_VALUE; 419 pThis->cHandlesAllocated = 0; 420 #ifdef RT_OS_WINDOWS 421 pThis->pahNative = NULL; 422 #else 423 pThis->paPollFds = NULL; 424 #endif 425 pThis->paHandles = NULL; 321 426 322 427 *phPollSet = pThis; … … 335 440 336 441 ASMAtomicWriteU32(&pThis->u32Magic, ~RTPOLLSET_MAGIC); 442 #ifdef RT_OS_WINDOWS 443 RTMemFree(pThis->pahNative); 444 pThis->pahNative = NULL; 445 #else 446 RTMemFree(pThis->paPollFds); 447 pThis->paPollFds = NULL; 448 #endif 449 RTMemFree(pThis->paHandles); 450 pThis->paHandles = NULL; 337 451 RTMemFree(pThis); 338 452 … … 361 475 * Set the busy flag and do the job. 362 476 */ 363 AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS);364 477 365 478 int rc = VINF_SUCCESS; 366 HANDLE hNative = INVALID_HANDLE_VALUE;479 RTHCINTPTR hNative = -1; 367 480 RTHANDLEUNION uh; 368 481 uh.uInt = 0; … … 371 484 case RTHANDLETYPE_PIPE: 372 485 uh.hPipe = pHandle->u.hPipe; 373 if (uh.hPipe != NIL_RTPIPE) 374 rc = rtPipePollGetHandle(uh.hPipe, fEvents, &hNative); 486 if (uh.hPipe == NIL_RTPIPE) 487 return VINF_SUCCESS; 488 rc = rtPipePollGetHandle(uh.hPipe, fEvents, &hNative); 375 489 break; 376 490 377 491 case RTHANDLETYPE_SOCKET: 378 492 uh.hSocket = pHandle->u.hSocket; 379 if (uh.hSocket != NIL_RTSOCKET) 380 rc = rtSocketPollGetHandle(uh.hSocket, fEvents, &hNative); 493 if (uh.hSocket == NIL_RTSOCKET) 494 return VINF_SUCCESS; 495 rc = rtSocketPollGetHandle(uh.hSocket, fEvents, &hNative); 381 496 break; 382 497 … … 396 511 break; 397 512 } 398 if ( RT_SUCCESS(rc) 399 && hNative != INVALID_HANDLE_VALUE) 400 { 513 if (RT_SUCCESS(rc)) 514 { 515 AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS); 516 401 517 uint32_t const i = pThis->cHandles; 402 518 … … 406 522 while (j-- > 0) 407 523 { 408 if (pThis-> aHandles[j].id == id)524 if (pThis->paHandles[j].id == id) 409 525 { 410 526 rc = VERR_POLL_HANDLE_ID_EXISTS; 411 527 break; 412 528 } 413 if ( pThis-> aHandles[j].enmType == pHandle->enmType414 && pThis-> aHandles[j].u.uInt == uh.uInt)529 if ( pThis->paHandles[j].enmType == pHandle->enmType 530 && pThis->paHandles[j].u.uInt == uh.uInt) 415 531 iPrev = j; 416 532 } … … 418 534 /* Check that we won't overflow the poll set now. */ 419 535 if ( RT_SUCCESS(rc) 420 && i + 1 > RT _ELEMENTS(pThis->ahNative))536 && i + 1 > RTPOLL_SET_MAX) 421 537 rc = VERR_POLL_SET_IS_FULL; 538 539 /* Grow the tables if necessary. */ 540 if (RT_SUCCESS(rc) && i + 1 > pThis->cHandlesAllocated) 541 { 542 uint32_t const c = pThis->cHandlesAllocated + 32; 543 void *pvNew; 544 pvNew = RTMemRealloc(pThis->paHandles, c * sizeof(pThis->paHandles[0])); 545 if (pvNew) 546 { 547 pThis->paHandles = (PRTPOLLSETHNDENT)pvNew; 548 #ifdef RT_OS_WINDOWS 549 pvNew = RTMemRealloc(pThis->pahNative, c * sizeof(pThis->pahNative[0])); 550 #else 551 pvNew = RTMemRealloc(pThis->paPollFds, c * sizeof(pThis->paPollFds[0])); 552 #endif 553 if (pvNew) 554 { 555 #ifdef RT_OS_WINDOWS 556 pThis->pahNative = (HANDLE *)pvNew; 557 #else 558 pThis->paPollFds = (struct pollfd *)pvNew; 559 #endif 560 pThis->cHandlesAllocated = c; 561 } 562 else 563 rc = VERR_NO_MEMORY; 564 } 565 else 566 rc = VERR_NO_MEMORY; 567 } 568 422 569 if (RT_SUCCESS(rc)) 423 570 { 424 571 /* Add the handles to the two parallel arrays. */ 425 pThis->ahNative[i] = hNative; 426 pThis->aHandles[i].enmType = pHandle->enmType; 427 pThis->aHandles[i].u = uh; 428 pThis->aHandles[i].id = id; 429 pThis->aHandles[i].fEvents = fEvents; 430 pThis->aHandles[i].fFinalEntry = true; 431 pThis->cHandles = i + 1; 572 #ifdef RT_OS_WINDOWS 573 pThis->pahNative[i] = (HANDLE)hNative; 574 #else 575 pThis->paPollFds[i].fd = (int)hNative; 576 pThis->paPollFds[i].revents = 0; 577 pThis->paPollFds[i].events = 0; 578 if (fEvents & RTPOLL_EVT_READ) 579 pThis->paPollFds[i].events |= POLLIN; 580 if (fEvents & RTPOLL_EVT_WRITE) 581 pThis->paPollFds[i].events |= POLLOUT; 582 if (fEvents & RTPOLL_EVT_ERROR) 583 pThis->paPollFds[i].events |= POLLERR; 584 #endif 585 pThis->paHandles[i].enmType = pHandle->enmType; 586 pThis->paHandles[i].u = uh; 587 pThis->paHandles[i].id = id; 588 pThis->paHandles[i].fEvents = fEvents; 589 pThis->paHandles[i].fFinalEntry = true; 432 590 433 591 if (iPrev != UINT32_MAX) 434 592 { 435 Assert(pThis->aHandles[i].fFinalEntry); 436 pThis->aHandles[i].fFinalEntry = false; 437 } 438 439 rc = VINF_SUCCESS; 593 Assert(pThis->paHandles[i].fFinalEntry); 594 pThis->paHandles[i].fFinalEntry = false; 595 } 596 597 #if !defined(RT_OS_WINDOWS) 598 /* Validate the handle by calling poll() */ 599 if (poll(&pThis->paPollFds[i], 1, 0) >= 0) 600 { 601 /* Add the handle info and close the transaction. */ 602 pThis->paHandles[i].enmType = pHandle->enmType; 603 pThis->paHandles[i].u = pHandle->u; 604 pThis->paHandles[i].id = id; 605 } 606 else 607 { 608 rc = RTErrConvertFromErrno(errno); 609 pThis->paPollFds[i].fd = -1; 610 } 611 #endif 612 613 if (RT_SUCCESS(rc)) 614 { 615 /* Commit */ 616 pThis->cHandles = i + 1; 617 rc = VINF_SUCCESS; 618 } 440 619 } 441 620 } … … 464 643 uint32_t i = pThis->cHandles; 465 644 while (i-- > 0) 466 if (pThis-> aHandles[i].id == id)645 if (pThis->paHandles[i].id == id) 467 646 { 468 647 /* Save some details for the duplicate searching. */ 469 bool fFinalEntry = pThis-> aHandles[i].fFinalEntry;470 RTHANDLETYPE enmType = pThis-> aHandles[i].enmType;471 RTHANDLEUNION uh = pThis-> aHandles[i].u;648 bool fFinalEntry = pThis->paHandles[i].fFinalEntry; 649 RTHANDLETYPE enmType = pThis->paHandles[i].enmType; 650 RTHANDLEUNION uh = pThis->paHandles[i].u; 472 651 473 652 /* Remove the entry. */ … … 476 655 if (cToMove) 477 656 { 478 memmove(&pThis->aHandles[i], &pThis->aHandles[i + 1], cToMove * sizeof(pThis->aHandles[i])); 479 memmove(&pThis->ahNative[i], &pThis->ahNative[i + 1], cToMove * sizeof(pThis->ahNative[i])); 657 memmove(&pThis->paHandles[i], &pThis->paHandles[i + 1], cToMove * sizeof(pThis->paHandles[i])); 658 #ifdef RT_OS_WINDOWS 659 memmove(&pThis->pahNative[i], &pThis->pahNative[i + 1], cToMove * sizeof(pThis->pahNative[i])); 660 #else 661 memmove(&pThis->paPollFds[i], &pThis->paPollFds[i + 1], cToMove * sizeof(pThis->paPollFds[i])); 662 #endif 480 663 } 481 664 … … 483 666 if (fFinalEntry) 484 667 while (i-- > 0) 485 if ( pThis-> aHandles[i].u.uInt == uh.uInt486 && pThis-> aHandles[i].enmType == enmType)668 if ( pThis->paHandles[i].u.uInt == uh.uInt 669 && pThis->paHandles[i].enmType == enmType) 487 670 { 488 Assert(!pThis-> aHandles[i].fFinalEntry);489 pThis-> aHandles[i].fFinalEntry = true;671 Assert(!pThis->paHandles[i].fFinalEntry); 672 pThis->paHandles[i].fFinalEntry = true; 490 673 break; 491 674 } … … 519 702 uint32_t i = pThis->cHandles; 520 703 while (i-- > 0) 521 if (pThis-> aHandles[i].id == id)704 if (pThis->paHandles[i].id == id) 522 705 { 523 706 if (pHandle) 524 707 { 525 pHandle->enmType = pThis-> aHandles[i].enmType;526 pHandle->u = pThis-> aHandles[i].u;708 pHandle->enmType = pThis->paHandles[i].enmType; 709 pHandle->u = pThis->paHandles[i].u; 527 710 } 528 711 rc = VINF_SUCCESS; … … 574 757 uint32_t i = pThis->cHandles; 575 758 while (i-- > 0) 576 if (pThis->aHandles[i].id == id) 577 { 578 pThis->aHandles[i].fEvents = fEvents; 759 if (pThis->paHandles[i].id == id) 760 { 761 pThis->paHandles[i].fEvents = fEvents; 762 #if !defined(RT_OS_WINDOWS) 763 pThis->paPollFds[i].events = 0; 764 if (fEvents & RTPOLL_EVT_READ) 765 pThis->paPollFds[i].events |= POLLIN; 766 if (fEvents & RTPOLL_EVT_WRITE) 767 pThis->paPollFds[i].events |= POLLOUT; 768 if (fEvents & RTPOLL_EVT_ERROR) 769 pThis->paPollFds[i].events |= POLLERR; 770 #endif 579 771 rc = VINF_SUCCESS; 580 772 break;
Note:
See TracChangeset
for help on using the changeset viewer.