VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/poll.cpp@ 44485

Last change on this file since 44485 was 44472, checked in by vboxsync, 12 years ago

IPRT: Merging poll-win.cpp and poll-posix.cpp, part 2.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.9 KB
Line 
1/* $Id: poll.cpp 44472 2013-01-30 15:55:32Z vboxsync $ */
2/** @file
3 * IPRT - Polling I/O Handles, Windows+Posix Implementation.
4 */
5
6/*
7 * Copyright (C) 2010-2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
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
39
40#include <iprt/poll.h>
41#include "internal/iprt.h"
42
43#include <iprt/asm.h>
44#include <iprt/assert.h>
45#include <iprt/err.h>
46#include <iprt/mem.h>
47#include <iprt/pipe.h>
48#include <iprt/socket.h>
49#include <iprt/string.h>
50#include <iprt/thread.h>
51#include <iprt/time.h>
52
53#include "internal/pipe.h"
54#define IPRT_INTERNAL_SOCKET_POLLING_ONLY
55#include "internal/socket.h"
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
67
68
69/*******************************************************************************
70* Structures and Typedefs *
71*******************************************************************************/
72/**
73 * Handle entry in a poll set.
74 */
75typedef struct RTPOLLSETHNDENT
76{
77 /** The handle type. */
78 RTHANDLETYPE enmType;
79 /** The handle ID. */
80 uint32_t id;
81 /** The events we're waiting for here. */
82 uint32_t fEvents;
83 /** Set if this is the final entry for this handle.
84 * If the handle is entered more than once, this will be clear for all but
85 * the last entry. */
86 bool fFinalEntry;
87 /** The handle union. */
88 RTHANDLEUNION u;
89} RTPOLLSETHNDENT;
90/** Pointer to a handle entry. */
91typedef RTPOLLSETHNDENT *PRTPOLLSETHNDENT;
92
93
94/**
95 * Poll set data.
96 */
97typedef struct RTPOLLSETINTERNAL
98{
99 /** The magic value (RTPOLLSET_MAGIC). */
100 uint32_t u32Magic;
101 /** Set when someone is polling or making changes. */
102 bool volatile fBusy;
103
104 /** The number of valid handles in the set. */
105 uint32_t cHandles;
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;
118} RTPOLLSETINTERNAL;
119
120
121
122/**
123 * Common worker for RTPoll and RTPollNoResume
124 */
125static int rtPollNoResumeWorker(RTPOLLSETINTERNAL *pThis, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid)
126{
127 int rc;
128
129 if (RT_UNLIKELY(pThis->cHandles == 0 && cMillies == RT_INDEFINITE_WAIT))
130 return VERR_DEADLOCK;
131
132 /*
133 * Check for special case, RTThreadSleep...
134 */
135 uint32_t const cHandles = pThis->cHandles;
136 if (cHandles == 0)
137 {
138 rc = RTThreadSleep(cMillies);
139 if (RT_SUCCESS(rc))
140 rc = VERR_TIMEOUT;
141 return rc;
142 }
143
144#ifdef RT_OS_WINDOWS
145 /*
146 * Check + prepare the handles before waiting.
147 */
148 uint32_t fEvents = 0;
149 bool const fNoWait = cMillies == 0;
150 uint32_t i;
151 for (i = 0; i < cHandles; i++)
152 {
153 switch (pThis->paHandles[i].enmType)
154 {
155 case RTHANDLETYPE_PIPE:
156 fEvents = rtPipePollStart(pThis->paHandles[i].u.hPipe, pThis, pThis->paHandles[i].fEvents,
157 pThis->paHandles[i].fFinalEntry, fNoWait);
158 break;
159
160 case RTHANDLETYPE_SOCKET:
161 fEvents = rtSocketPollStart(pThis->paHandles[i].u.hSocket, pThis, pThis->paHandles[i].fEvents,
162 pThis->paHandles[i].fFinalEntry, fNoWait);
163 break;
164
165 default:
166 AssertFailed();
167 fEvents = UINT32_MAX;
168 break;
169 }
170 if (fEvents)
171 break;
172 }
173 if ( fEvents
174 || fNoWait)
175 {
176
177 if (pid)
178 *pid = pThis->paHandles[i].id;
179 if (pfEvents)
180 *pfEvents = fEvents;
181 rc = !fEvents
182 ? VERR_TIMEOUT
183 : fEvents != UINT32_MAX
184 ? VINF_SUCCESS
185 : VERR_INTERNAL_ERROR_4;
186
187 /* clean up */
188 if (!fNoWait)
189 while (i-- > 0)
190 {
191 switch (pThis->paHandles[i].enmType)
192 {
193 case RTHANDLETYPE_PIPE:
194 rtPipePollDone(pThis->paHandles[i].u.hPipe, pThis->paHandles[i].fEvents,
195 pThis->paHandles[i].fFinalEntry, false);
196 break;
197
198 case RTHANDLETYPE_SOCKET:
199 rtSocketPollDone(pThis->paHandles[i].u.hSocket, pThis->paHandles[i].fEvents,
200 pThis->paHandles[i].fFinalEntry, false);
201 break;
202
203 default:
204 AssertFailed();
205 break;
206 }
207 }
208
209 return rc;
210 }
211
212 /*
213 * Wait.
214 */
215 DWORD dwRc = WaitForMultipleObjectsEx(cHandles, pThis->pahNative,
216 FALSE /*fWaitAll */,
217 cMillies == RT_INDEFINITE_WAIT ? INFINITE : cMillies,
218 TRUE /*fAlertable*/);
219 if ( dwRc >= WAIT_OBJECT_0
220 && dwRc < WAIT_OBJECT_0 + cHandles)
221 rc = VERR_INTERRUPTED;
222 else if (dwRc == WAIT_TIMEOUT)
223 rc = VERR_TIMEOUT;
224 else if (dwRc == WAIT_IO_COMPLETION)
225 rc = VERR_INTERRUPTED;
226 else if (dwRc == WAIT_FAILED)
227 rc = RTErrConvertFromWin32(GetLastError());
228 else
229 {
230 AssertMsgFailed(("%u (%#x)\n", dwRc, dwRc));
231 rc = VERR_INTERNAL_ERROR_5;
232 }
233
234 /*
235 * Get event (if pending) and do wait cleanup.
236 */
237 bool fHarvestEvents = true;
238 for (i = 0; i < cHandles; i++)
239 {
240 fEvents = 0;
241 switch (pThis->paHandles[i].enmType)
242 {
243 case RTHANDLETYPE_PIPE:
244 fEvents = rtPipePollDone(pThis->paHandles[i].u.hPipe, pThis->paHandles[i].fEvents,
245 pThis->paHandles[i].fFinalEntry, fHarvestEvents);
246 break;
247
248 case RTHANDLETYPE_SOCKET:
249 fEvents = rtSocketPollDone(pThis->paHandles[i].u.hSocket, pThis->paHandles[i].fEvents,
250 pThis->paHandles[i].fFinalEntry, fHarvestEvents);
251 break;
252
253 default:
254 AssertFailed();
255 break;
256 }
257 if ( fEvents
258 && fHarvestEvents)
259 {
260 Assert(fEvents != UINT32_MAX);
261 fHarvestEvents = false;
262 if (pfEvents)
263 *pfEvents = fEvents;
264 if (pid)
265 *pid = pThis->paHandles[i].id;
266 rc = VINF_SUCCESS;
267 }
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 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 */
343
344 return rc;
345}
346
347
348RTDECL(int) RTPoll(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid)
349{
350 RTPOLLSETINTERNAL *pThis = hPollSet;
351 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
352 AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
353 AssertPtrNull(pfEvents);
354 AssertPtrNull(pid);
355
356 /*
357 * Set the busy flag and do the job.
358 */
359 AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS);
360
361 int rc;
362 if (cMillies == RT_INDEFINITE_WAIT || cMillies == 0)
363 {
364 do rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid);
365 while (rc == VERR_INTERRUPTED);
366 }
367 else
368 {
369 uint64_t MsStart = RTTimeMilliTS();
370 rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid);
371 while (RT_UNLIKELY(rc == VERR_INTERRUPTED))
372 {
373 if (RTTimeMilliTS() - MsStart >= cMillies)
374 {
375 rc = VERR_TIMEOUT;
376 break;
377 }
378 rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid);
379 }
380 }
381
382 ASMAtomicWriteBool(&pThis->fBusy, false);
383
384 return rc;
385}
386
387
388RTDECL(int) RTPollNoResume(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid)
389{
390 RTPOLLSETINTERNAL *pThis = hPollSet;
391 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
392 AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
393 AssertPtrNull(pfEvents);
394 AssertPtrNull(pid);
395
396 /*
397 * Set the busy flag and do the job.
398 */
399 AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS);
400
401 int rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid);
402
403 ASMAtomicWriteBool(&pThis->fBusy, false);
404
405 return rc;
406}
407
408
409RTDECL(int) RTPollSetCreate(PRTPOLLSET phPollSet)
410{
411 AssertPtrReturn(phPollSet, VERR_INVALID_POINTER);
412 RTPOLLSETINTERNAL *pThis = (RTPOLLSETINTERNAL *)RTMemAlloc(sizeof(RTPOLLSETINTERNAL));
413 if (!pThis)
414 return VERR_NO_MEMORY;
415
416 pThis->u32Magic = RTPOLLSET_MAGIC;
417 pThis->fBusy = false;
418 pThis->cHandles = 0;
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;
426
427 *phPollSet = pThis;
428 return VINF_SUCCESS;
429}
430
431
432RTDECL(int) RTPollSetDestroy(RTPOLLSET hPollSet)
433{
434 RTPOLLSETINTERNAL *pThis = hPollSet;
435 if (pThis == NIL_RTPOLLSET)
436 return VINF_SUCCESS;
437 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
438 AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
439 AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS);
440
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;
451 RTMemFree(pThis);
452
453 return VINF_SUCCESS;
454}
455
456
457RTDECL(int) RTPollSetAdd(RTPOLLSET hPollSet, PCRTHANDLE pHandle, uint32_t fEvents, uint32_t id)
458{
459 /*
460 * Validate the input (tedious).
461 */
462 RTPOLLSETINTERNAL *pThis = hPollSet;
463 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
464 AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
465 AssertReturn(!(fEvents & ~RTPOLL_EVT_VALID_MASK), VERR_INVALID_PARAMETER);
466 AssertReturn(fEvents, VERR_INVALID_PARAMETER);
467 AssertReturn(id != UINT32_MAX, VERR_INVALID_PARAMETER);
468
469 if (!pHandle)
470 return VINF_SUCCESS;
471 AssertPtrReturn(pHandle, VERR_INVALID_POINTER);
472 AssertReturn(pHandle->enmType > RTHANDLETYPE_INVALID && pHandle->enmType < RTHANDLETYPE_END, VERR_INVALID_PARAMETER);
473
474 /*
475 * Set the busy flag and do the job.
476 */
477
478 int rc = VINF_SUCCESS;
479 RTHCINTPTR hNative = -1;
480 RTHANDLEUNION uh;
481 uh.uInt = 0;
482 switch (pHandle->enmType)
483 {
484 case RTHANDLETYPE_PIPE:
485 uh.hPipe = pHandle->u.hPipe;
486 if (uh.hPipe == NIL_RTPIPE)
487 return VINF_SUCCESS;
488 rc = rtPipePollGetHandle(uh.hPipe, fEvents, &hNative);
489 break;
490
491 case RTHANDLETYPE_SOCKET:
492 uh.hSocket = pHandle->u.hSocket;
493 if (uh.hSocket == NIL_RTSOCKET)
494 return VINF_SUCCESS;
495 rc = rtSocketPollGetHandle(uh.hSocket, fEvents, &hNative);
496 break;
497
498 case RTHANDLETYPE_FILE:
499 AssertMsgFailed(("Files are always ready for reading/writing and thus not pollable. Use native APIs for special devices.\n"));
500 rc = VERR_POLL_HANDLE_NOT_POLLABLE;
501 break;
502
503 case RTHANDLETYPE_THREAD:
504 AssertMsgFailed(("Thread handles are currently not pollable\n"));
505 rc = VERR_POLL_HANDLE_NOT_POLLABLE;
506 break;
507
508 default:
509 AssertMsgFailed(("\n"));
510 rc = VERR_POLL_HANDLE_NOT_POLLABLE;
511 break;
512 }
513 if (RT_SUCCESS(rc))
514 {
515 AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS);
516
517 uint32_t const i = pThis->cHandles;
518
519 /* Check that the handle ID doesn't exist already. */
520 uint32_t iPrev = UINT32_MAX;
521 uint32_t j = i;
522 while (j-- > 0)
523 {
524 if (pThis->paHandles[j].id == id)
525 {
526 rc = VERR_POLL_HANDLE_ID_EXISTS;
527 break;
528 }
529 if ( pThis->paHandles[j].enmType == pHandle->enmType
530 && pThis->paHandles[j].u.uInt == uh.uInt)
531 iPrev = j;
532 }
533
534 /* Check that we won't overflow the poll set now. */
535 if ( RT_SUCCESS(rc)
536 && i + 1 > RTPOLL_SET_MAX)
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
569 if (RT_SUCCESS(rc))
570 {
571 /* Add the handles to the two parallel arrays. */
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;
590
591 if (iPrev != UINT32_MAX)
592 {
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 }
619 }
620 }
621
622 ASMAtomicWriteBool(&pThis->fBusy, false);
623 return rc;
624}
625
626
627RTDECL(int) RTPollSetRemove(RTPOLLSET hPollSet, uint32_t id)
628{
629 /*
630 * Validate the input.
631 */
632 RTPOLLSETINTERNAL *pThis = hPollSet;
633 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
634 AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
635 AssertReturn(id != UINT32_MAX, VERR_INVALID_PARAMETER);
636
637 /*
638 * Set the busy flag and do the job.
639 */
640 AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS);
641
642 int rc = VERR_POLL_HANDLE_ID_NOT_FOUND;
643 uint32_t i = pThis->cHandles;
644 while (i-- > 0)
645 if (pThis->paHandles[i].id == id)
646 {
647 /* Save some details for the duplicate searching. */
648 bool fFinalEntry = pThis->paHandles[i].fFinalEntry;
649 RTHANDLETYPE enmType = pThis->paHandles[i].enmType;
650 RTHANDLEUNION uh = pThis->paHandles[i].u;
651
652 /* Remove the entry. */
653 pThis->cHandles--;
654 size_t const cToMove = pThis->cHandles - i;
655 if (cToMove)
656 {
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
663 }
664
665 /* Check for duplicate and set the fFinalEntry flag. */
666 if (fFinalEntry)
667 while (i-- > 0)
668 if ( pThis->paHandles[i].u.uInt == uh.uInt
669 && pThis->paHandles[i].enmType == enmType)
670 {
671 Assert(!pThis->paHandles[i].fFinalEntry);
672 pThis->paHandles[i].fFinalEntry = true;
673 break;
674 }
675
676 rc = VINF_SUCCESS;
677 break;
678 }
679
680 ASMAtomicWriteBool(&pThis->fBusy, false);
681 return rc;
682}
683
684
685RTDECL(int) RTPollSetQueryHandle(RTPOLLSET hPollSet, uint32_t id, PRTHANDLE pHandle)
686{
687 /*
688 * Validate the input.
689 */
690 RTPOLLSETINTERNAL *pThis = hPollSet;
691 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
692 AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
693 AssertReturn(id != UINT32_MAX, VERR_INVALID_PARAMETER);
694 AssertPtrNullReturn(pHandle, VERR_INVALID_POINTER);
695
696 /*
697 * Set the busy flag and do the job.
698 */
699 AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS);
700
701 int rc = VERR_POLL_HANDLE_ID_NOT_FOUND;
702 uint32_t i = pThis->cHandles;
703 while (i-- > 0)
704 if (pThis->paHandles[i].id == id)
705 {
706 if (pHandle)
707 {
708 pHandle->enmType = pThis->paHandles[i].enmType;
709 pHandle->u = pThis->paHandles[i].u;
710 }
711 rc = VINF_SUCCESS;
712 break;
713 }
714
715 ASMAtomicWriteBool(&pThis->fBusy, false);
716 return rc;
717}
718
719
720RTDECL(uint32_t) RTPollSetGetCount(RTPOLLSET hPollSet)
721{
722 /*
723 * Validate the input.
724 */
725 RTPOLLSETINTERNAL *pThis = hPollSet;
726 AssertPtrReturn(pThis, UINT32_MAX);
727 AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, UINT32_MAX);
728
729 /*
730 * Set the busy flag and do the job.
731 */
732 AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), UINT32_MAX);
733 uint32_t cHandles = pThis->cHandles;
734 ASMAtomicWriteBool(&pThis->fBusy, false);
735
736 return cHandles;
737}
738
739RTDECL(int) RTPollSetEventsChange(RTPOLLSET hPollSet, uint32_t id, uint32_t fEvents)
740{
741 /*
742 * Validate the input.
743 */
744 RTPOLLSETINTERNAL *pThis = hPollSet;
745 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
746 AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
747 AssertReturn(id != UINT32_MAX, VERR_INVALID_PARAMETER);
748 AssertReturn(!(fEvents & ~RTPOLL_EVT_VALID_MASK), VERR_INVALID_PARAMETER);
749 AssertReturn(fEvents, VERR_INVALID_PARAMETER);
750
751 /*
752 * Set the busy flag and do the job.
753 */
754 AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS);
755
756 int rc = VERR_POLL_HANDLE_ID_NOT_FOUND;
757 uint32_t i = pThis->cHandles;
758 while (i-- > 0)
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
771 rc = VINF_SUCCESS;
772 break;
773 }
774
775 ASMAtomicWriteBool(&pThis->fBusy, false);
776 return rc;
777}
778
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette