Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(208)

Side by Side Diff: third_party/libusb/libusb/os/poll_windows.c

Issue 9826025: Import libusb 1.0.9-rc3 into third_party (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Cleaning up import instructions Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * poll_windows: poll compatibility wrapper for Windows
3 * Copyright (C) 2009-2010 Pete Batard <pbatard@gmail.com>
4 * With contributions from Michael Plante, Orin Eman et al.
5 * Parts of poll implementation from libusb-win32, by Stephan Meyer et al.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22
23 /*
24 * poll() and pipe() Windows compatibility layer for libusb 1.0
25 *
26 * The way this layer works is by using OVERLAPPED with async I/O transfers, as
27 * OVERLAPPED have an associated event which is flagged for I/O completion.
28 *
29 * For USB pollable async I/O, you would typically:
30 * - obtain a Windows HANDLE to a file or device that has been opened in
31 * OVERLAPPED mode
32 * - call usbi_create_fd with this handle to obtain a custom fd.
33 * Note that if you need simultaneous R/W access, you need to call create_fd
34 * twice, once in _O_RDONLY and once in _O_WRONLY mode to obtain 2 separate
35 * pollable fds
36 * - leave the core functions call the poll routine and flag POLLIN/POLLOUT
37 *
38 * The pipe pollable synchronous I/O works using the overlapped event associated
39 * with a fake pipe. The read/write functions are only meant to be used in that
40 * context.
41 */
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <io.h>
47
48 #include <libusbi.h>
49
50 // Uncomment to debug the polling layer
51 //#define DEBUG_POLL_WINDOWS
52 #if defined(DEBUG_POLL_WINDOWS)
53 #define poll_dbg usbi_dbg
54 #else
55 // MSVC6 cannot use a variadic argument and non MSVC
56 // compilers produce warnings if parenthesis are ommitted.
57 #if defined(_MSC_VER)
58 #define poll_dbg
59 #else
60 #define poll_dbg(...)
61 #endif
62 #endif
63
64 #if defined(_PREFAST_)
65 #pragma warning(disable:28719)
66 #endif
67
68 #if defined(__CYGWIN__)
69 // cygwin produces a warning unless these prototypes are defined
70 extern int _open(char* name, int flags);
71 extern int _close(int fd);
72 extern int _snprintf(char *buffer, size_t count, const char *format, ...);
73 #define NUL_DEVICE "/dev/null"
74 #else
75 #define NUL_DEVICE "NUL"
76 #endif
77
78 #define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0)
79
80 // public fd data
81 const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, RW_NONE};
82 struct winfd poll_fd[MAX_FDS];
83 // internal fd data
84 struct {
85 CRITICAL_SECTION mutex; // lock for fds
86 // Additional variables for XP CancelIoEx partial emulation
87 HANDLE original_handle;
88 DWORD thread_id;
89 } _poll_fd[MAX_FDS];
90
91 // globals
92 BOOLEAN is_polling_set = FALSE;
93 #if defined(DYNAMIC_FDS)
94 HANDLE fd_update = INVALID_HANDLE_VALUE; // event to notify poll of fd up date
95 HANDLE new_fd[MAX_FDS]; // overlapped event handles for fds created sinc e last poll
96 unsigned nb_new_fds = 0; // nb new fds created since last poll
97 usbi_mutex_t new_fd_mutex; // mutex required for the above
98 #endif
99 LONG pipe_number = 0;
100 static volatile LONG compat_spinlock = 0;
101
102 // CancelIoEx, available on Vista and later only, provides the ability to cancel
103 // a single transfer (OVERLAPPED) when used. As it may not be part of any of the
104 // platform headers, we hook into the Kernel32 system DLL directly to seek it.
105 static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL;
106 #define CancelIoEx_Available (pCancelIoEx != NULL)
107 static __inline BOOL cancel_io(int _index)
108 {
109 if ((_index < 0) || (_index >= MAX_FDS)) {
110 return FALSE;
111 }
112
113 if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HAND LE_VALUE)
114 || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NUL L) ) {
115 return TRUE;
116 }
117 if (CancelIoEx_Available) {
118 return (*pCancelIoEx)(poll_fd[_index].handle, poll_fd[_index].ov erlapped);
119 }
120 if (_poll_fd[_index].thread_id == GetCurrentThreadId()) {
121 return CancelIo(poll_fd[_index].handle);
122 }
123 usbi_warn(NULL, "Unable to cancel I/O that was started from another thre ad");
124 return FALSE;
125 }
126
127 // Init
128 void init_polling(void)
129 {
130 int i;
131
132 while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
133 SleepEx(0, TRUE);
134 }
135 if (!is_polling_set) {
136 pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED))
137 GetProcAddress(GetModuleHandleA("KERNEL32"), "CancelIoEx ");
138 usbi_dbg("Will use CancelIo%s for I/O cancellation",
139 CancelIoEx_Available?"Ex":"");
140 for (i=0; i<MAX_FDS; i++) {
141 poll_fd[i] = INVALID_WINFD;
142 _poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
143 _poll_fd[i].thread_id = 0;
144 InitializeCriticalSection(&_poll_fd[i].mutex);
145 }
146 #if defined(DYNAMIC_FDS)
147 // We need to create an update event so that poll is warned when there
148 // are new/deleted fds during a timeout wait operation
149 fd_update = CreateEvent(NULL, TRUE, FALSE, NULL);
150 if (fd_update == NULL) {
151 usbi_err(NULL, "unable to create update event");
152 }
153 usbi_mutex_init(&new_fd_mutex, NULL);
154 nb_new_fds = 0;
155 #endif
156 is_polling_set = TRUE;
157 }
158 compat_spinlock = 0;
159 }
160
161 // Internal function to retrieve the table index (and lock the fd mutex)
162 int _fd_to_index_and_lock(int fd)
163 {
164 int i;
165
166 if (fd <= 0)
167 return -1;
168
169 for (i=0; i<MAX_FDS; i++) {
170 if (poll_fd[i].fd == fd) {
171 EnterCriticalSection(&_poll_fd[i].mutex);
172 // fd might have changed before we got to critical
173 if (poll_fd[i].fd != fd) {
174 LeaveCriticalSection(&_poll_fd[i].mutex);
175 continue;
176 }
177 return i;
178 }
179 }
180 return -1;
181 }
182
183 OVERLAPPED *create_overlapped(void)
184 {
185 OVERLAPPED *overlapped = calloc(1, sizeof(OVERLAPPED));
186 if (overlapped == NULL) {
187 return NULL;
188 }
189 overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
190 if(overlapped->hEvent == NULL) {
191 free (overlapped);
192 return NULL;
193 }
194 return overlapped;
195 }
196
197 void free_overlapped(OVERLAPPED *overlapped)
198 {
199 if (overlapped == NULL)
200 return;
201
202 if ( (overlapped->hEvent != 0)
203 && (overlapped->hEvent != INVALID_HANDLE_VALUE) ) {
204 CloseHandle(overlapped->hEvent);
205 }
206 free(overlapped);
207 }
208
209 void reset_overlapped(OVERLAPPED *overlapped)
210 {
211 HANDLE event_handle;
212 if (overlapped == NULL)
213 return;
214
215 event_handle = overlapped->hEvent;
216 if (event_handle != NULL) {
217 ResetEvent(event_handle);
218 }
219 memset(overlapped, 0, sizeof(OVERLAPPED));
220 overlapped->hEvent = event_handle;
221 }
222
223 void exit_polling(void)
224 {
225 int i;
226
227 while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
228 SleepEx(0, TRUE);
229 }
230 if (is_polling_set) {
231 is_polling_set = FALSE;
232
233 for (i=0; i<MAX_FDS; i++) {
234 // Cancel any async I/O (handle can be invalid)
235 cancel_io(i);
236 // If anything was pending on that I/O, it should be
237 // terminating, and we should be able to access the fd
238 // mutex lock before too long
239 EnterCriticalSection(&_poll_fd[i].mutex);
240 if ( (poll_fd[i].fd > 0) && (poll_fd[i].handle != INVALI D_HANDLE_VALUE) && (poll_fd[i].handle != 0)
241 && (GetFileType(poll_fd[i].handle) == FILE_TYPE_UNKNOW N) ) {
242 _close(poll_fd[i].fd);
243 }
244 free_overlapped(poll_fd[i].overlapped);
245 if (!CancelIoEx_Available) {
246 // Close duplicate handle
247 if (_poll_fd[i].original_handle != INVALID_HANDL E_VALUE) {
248 CloseHandle(poll_fd[i].handle);
249 }
250 }
251 poll_fd[i] = INVALID_WINFD;
252 #if defined(DYNAMIC_FDS)
253 usbi_mutex_destroy(&new_fd_mutex);
254 CloseHandle(fd_update);
255 fd_update = INVALID_HANDLE_VALUE;
256 #endif
257 LeaveCriticalSection(&_poll_fd[i].mutex);
258 DeleteCriticalSection(&_poll_fd[i].mutex);
259 }
260 }
261 compat_spinlock = 0;
262 }
263
264 /*
265 * Create a fake pipe.
266 * As libusb only uses pipes for signaling, all we need from a pipe is an
267 * event. To that extent, we create a single wfd and overlapped as a means
268 * to access that event.
269 */
270 int usbi_pipe(int filedes[2])
271 {
272 int i;
273 OVERLAPPED* overlapped;
274
275 CHECK_INIT_POLLING;
276
277 overlapped = calloc(1, sizeof(OVERLAPPED));
278 if (overlapped == NULL) {
279 return -1;
280 }
281 // The overlapped must have status pending for signaling to work in poll
282 overlapped->Internal = STATUS_PENDING;
283 overlapped->InternalHigh = 0;
284
285 // Read end of the "pipe"
286 filedes[0] = _open(NUL_DEVICE, _O_WRONLY);
287 if (filedes[0] < 0) {
288 usbi_err(NULL, "could not create pipe: errno %d", errno);
289 goto out1;
290 }
291 // We can use the same handle for both ends
292 filedes[1] = filedes[0];
293 poll_dbg("pipe filedes = %d", filedes[0]);
294
295 // Note: manual reset must be true (second param) as the reset occurs in read
296 overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
297 if(!overlapped->hEvent) {
298 goto out2;
299 }
300
301 for (i=0; i<MAX_FDS; i++) {
302 if (poll_fd[i].fd < 0) {
303 EnterCriticalSection(&_poll_fd[i].mutex);
304 // fd might have been allocated before we got to critica l
305 if (poll_fd[i].fd >= 0) {
306 LeaveCriticalSection(&_poll_fd[i].mutex);
307 continue;
308 }
309
310 poll_fd[i].fd = filedes[0];
311 poll_fd[i].handle = DUMMY_HANDLE;
312 poll_fd[i].overlapped = overlapped;
313 // There's no polling on the write end, so we just use R EAD for our needs
314 poll_fd[i].rw = RW_READ;
315 _poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
316 LeaveCriticalSection(&_poll_fd[i].mutex);
317 return 0;
318 }
319 }
320
321 CloseHandle(overlapped->hEvent);
322 out2:
323 _close(filedes[0]);
324 out1:
325 free(overlapped);
326 return -1;
327 }
328
329 /*
330 * Create both an fd and an OVERLAPPED from an open Windows handle, so that
331 * it can be used with our polling function
332 * The handle MUST support overlapped transfers (usually requires CreateFile
333 * with FILE_FLAG_OVERLAPPED)
334 * Return a pollable file descriptor struct, or INVALID_WINFD on error
335 *
336 * Note that the fd returned by this function is a per-transfer fd, rather
337 * than a per-session fd and cannot be used for anything else but our
338 * custom functions (the fd itself points to the NUL: device)
339 * if you plan to do R/W on the same handle, you MUST create 2 fds: one for
340 * read and one for write. Using a single R/W fd is unsupported and will
341 * produce unexpected results
342 */
343 struct winfd usbi_create_fd(HANDLE handle, int access_mode)
344 {
345 int i, fd;
346 struct winfd wfd = INVALID_WINFD;
347 OVERLAPPED* overlapped = NULL;
348
349 CHECK_INIT_POLLING;
350
351 if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) {
352 return INVALID_WINFD;
353 }
354
355 if ((access_mode != _O_RDONLY) && (access_mode != _O_WRONLY)) {
356 usbi_warn(NULL, "only one of _O_RDONLY or _O_WRONLY are supporte d.\n"
357 "If you want to poll for R/W simultaneously, create mult iple fds from the same handle.");
358 return INVALID_WINFD;
359 }
360 if (access_mode == _O_RDONLY) {
361 wfd.rw = RW_READ;
362 } else {
363 wfd.rw = RW_WRITE;
364 }
365
366 // Ensure that we get a non system conflicting unique fd, using
367 // the same fd attribution system as the pipe ends
368 fd = _open(NUL_DEVICE, _O_WRONLY);
369 if (fd < 0) {
370 return INVALID_WINFD;
371 }
372
373 overlapped = create_overlapped();
374 if(overlapped == NULL) {
375 _close(fd);
376 return INVALID_WINFD;
377 }
378
379 for (i=0; i<MAX_FDS; i++) {
380 if (poll_fd[i].fd < 0) {
381 EnterCriticalSection(&_poll_fd[i].mutex);
382 // fd might have been removed before we got to critical
383 if (poll_fd[i].fd >= 0) {
384 LeaveCriticalSection(&_poll_fd[i].mutex);
385 continue;
386 }
387 wfd.fd = fd;
388 // Attempt to emulate some of the CancelIoEx behaviour o n platforms
389 // that don't have it
390 if (!CancelIoEx_Available) {
391 _poll_fd[i].thread_id = GetCurrentThreadId();
392 if (!DuplicateHandle(GetCurrentProcess(), handle , GetCurrentProcess(),
393 &wfd.handle, 0, TRUE, DUPLICATE_SAME_ACC ESS)) {
394 usbi_dbg("could not duplicate handle for CancelIo - using original one");
395 wfd.handle = handle;
396 // Make sure we won't close the original handle on fd deletion then
397 _poll_fd[i].original_handle = INVALID_HA NDLE_VALUE;
398 } else {
399 _poll_fd[i].original_handle = handle;
400 }
401 } else {
402 wfd.handle = handle;
403 }
404 wfd.overlapped = overlapped;
405 memcpy(&poll_fd[i], &wfd, sizeof(struct winfd));
406 LeaveCriticalSection(&_poll_fd[i].mutex);
407 #if defined(DYNAMIC_FDS)
408 usbi_mutex_lock(&new_fd_mutex);
409 new_fd[nb_new_fds++] = overlapped->hEvent;
410 usbi_mutex_unlock(&new_fd_mutex);
411 // Notify poll that fds have been updated
412 SetEvent(fd_update);
413 #endif
414 return wfd;
415 }
416 }
417 free_overlapped(overlapped);
418 _close(fd);
419 return INVALID_WINFD;
420 }
421
422 void _free_index(int _index)
423 {
424 // Cancel any async IO (Don't care about the validity of our handles for this)
425 cancel_io(_index);
426 // close fake handle for devices
427 if ( (poll_fd[_index].handle != INVALID_HANDLE_VALUE) && (poll_fd[_index ].handle != 0)
428 && (GetFileType(poll_fd[_index].handle) == FILE_TYPE_UNKNOWN) ) {
429 _close(poll_fd[_index].fd);
430 }
431 // close the duplicate handle (if we have an actual duplicate)
432 if (!CancelIoEx_Available) {
433 if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) {
434 CloseHandle(poll_fd[_index].handle);
435 }
436 _poll_fd[_index].original_handle = INVALID_HANDLE_VALUE;
437 _poll_fd[_index].thread_id = 0;
438 }
439 free_overlapped(poll_fd[_index].overlapped);
440 poll_fd[_index] = INVALID_WINFD;
441 }
442
443 /*
444 * Release a pollable file descriptor.
445 *
446 * Note that the associated Windows handle is not closed by this call
447 */
448 void usbi_free_fd(int fd)
449 {
450 int _index;
451
452 CHECK_INIT_POLLING;
453
454 _index = _fd_to_index_and_lock(fd);
455 if (_index < 0) {
456 return;
457 }
458 _free_index(_index);
459 LeaveCriticalSection(&_poll_fd[_index].mutex);
460 }
461
462 /*
463 * The functions below perform various conversions between fd, handle and OVERLA PPED
464 */
465 struct winfd fd_to_winfd(int fd)
466 {
467 int i;
468 struct winfd wfd;
469
470 CHECK_INIT_POLLING;
471
472 if (fd <= 0)
473 return INVALID_WINFD;
474
475 for (i=0; i<MAX_FDS; i++) {
476 if (poll_fd[i].fd == fd) {
477 EnterCriticalSection(&_poll_fd[i].mutex);
478 // fd might have been deleted before we got to critical
479 if (poll_fd[i].fd != fd) {
480 LeaveCriticalSection(&_poll_fd[i].mutex);
481 continue;
482 }
483 memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
484 LeaveCriticalSection(&_poll_fd[i].mutex);
485 return wfd;
486 }
487 }
488 return INVALID_WINFD;
489 }
490
491 struct winfd handle_to_winfd(HANDLE handle)
492 {
493 int i;
494 struct winfd wfd;
495
496 CHECK_INIT_POLLING;
497
498 if ((handle == 0) || (handle == INVALID_HANDLE_VALUE))
499 return INVALID_WINFD;
500
501 for (i=0; i<MAX_FDS; i++) {
502 if (poll_fd[i].handle == handle) {
503 EnterCriticalSection(&_poll_fd[i].mutex);
504 // fd might have been deleted before we got to critical
505 if (poll_fd[i].handle != handle) {
506 LeaveCriticalSection(&_poll_fd[i].mutex);
507 continue;
508 }
509 memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
510 LeaveCriticalSection(&_poll_fd[i].mutex);
511 return wfd;
512 }
513 }
514 return INVALID_WINFD;
515 }
516
517 struct winfd overlapped_to_winfd(OVERLAPPED* overlapped)
518 {
519 int i;
520 struct winfd wfd;
521
522 CHECK_INIT_POLLING;
523
524 if (overlapped == NULL)
525 return INVALID_WINFD;
526
527 for (i=0; i<MAX_FDS; i++) {
528 if (poll_fd[i].overlapped == overlapped) {
529 EnterCriticalSection(&_poll_fd[i].mutex);
530 // fd might have been deleted before we got to critical
531 if (poll_fd[i].overlapped != overlapped) {
532 LeaveCriticalSection(&_poll_fd[i].mutex);
533 continue;
534 }
535 memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
536 LeaveCriticalSection(&_poll_fd[i].mutex);
537 return wfd;
538 }
539 }
540 return INVALID_WINFD;
541 }
542
543 /*
544 * POSIX poll equivalent, using Windows OVERLAPPED
545 * Currently, this function only accepts one of POLLIN or POLLOUT per fd
546 * (but you can create multiple fds from the same handle for read and write)
547 */
548 int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
549 {
550 unsigned i;
551 int _index, object_index, triggered;
552 HANDLE *handles_to_wait_on;
553 int *handle_to_index;
554 DWORD nb_handles_to_wait_on = 0;
555 DWORD ret;
556
557 #if defined(DYNAMIC_FDS)
558 DWORD nb_extra_handles = 0;
559 unsigned j;
560
561 // To address the possibility of missing new fds between the time the ne w
562 // pollable fd set is assembled, and the ResetEvent() call below, an
563 // additional new_fd[] HANDLE table is used for any new fd that was crea ted
564 // since the last call to poll (see below)
565 ResetEvent(fd_update);
566
567 // At this stage, any new fd creation will be detected through the fd_up date
568 // event notification, and any previous creation that we may have missed
569 // will be picked up through the existing new_fd[] table.
570 #endif
571
572 CHECK_INIT_POLLING;
573
574 triggered = 0;
575 handles_to_wait_on = malloc((nfds+1)*sizeof(HANDLE)); // +1 for fd_upd ate
576 handle_to_index = malloc(nfds*sizeof(int));
577 if ((handles_to_wait_on == NULL) || (handle_to_index == NULL)) {
578 errno = ENOMEM;
579 triggered = -1;
580 goto poll_exit;
581 }
582
583 for (i = 0; i < nfds; ++i) {
584 fds[i].revents = 0;
585
586 // Only one of POLLIN or POLLOUT can be selected with this versi on of poll (not both)
587 if ((fds[i].events & ~POLLIN) && (!(fds[i].events & POLLOUT))) {
588 fds[i].revents |= POLLERR;
589 errno = EACCES;
590 usbi_warn(NULL, "unsupported set of events");
591 triggered = -1;
592 goto poll_exit;
593 }
594
595 _index = _fd_to_index_and_lock(fds[i].fd);
596 poll_dbg("fd[%d]=%d: (overlapped=%p) got events %04X", i, poll_f d[_index].fd, poll_fd[_index].overlapped, fds[i].events);
597
598 if ( (_index < 0) || (poll_fd[_index].handle == INVALID_HANDLE_V ALUE)
599 || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlappe d == NULL)) {
600 fds[i].revents |= POLLNVAL | POLLERR;
601 errno = EBADF;
602 if (_index >= 0) {
603 LeaveCriticalSection(&_poll_fd[_index].mutex);
604 }
605 usbi_warn(NULL, "invalid fd");
606 triggered = -1;
607 goto poll_exit;
608 }
609
610 // IN or OUT must match our fd direction
611 if ((fds[i].events & POLLIN) && (poll_fd[_index].rw != RW_READ)) {
612 fds[i].revents |= POLLNVAL | POLLERR;
613 errno = EBADF;
614 usbi_warn(NULL, "attempted POLLIN on fd without READ acc ess");
615 LeaveCriticalSection(&_poll_fd[_index].mutex);
616 triggered = -1;
617 goto poll_exit;
618 }
619
620 if ((fds[i].events & POLLOUT) && (poll_fd[_index].rw != RW_WRITE )) {
621 fds[i].revents |= POLLNVAL | POLLERR;
622 errno = EBADF;
623 usbi_warn(NULL, "attempted POLLOUT on fd without WRITE a ccess");
624 LeaveCriticalSection(&_poll_fd[_index].mutex);
625 triggered = -1;
626 goto poll_exit;
627 }
628
629 // The following macro only works if overlapped I/O was reported pending
630 if ( (HasOverlappedIoCompleted(poll_fd[_index].overlapped))
631 || (HasOverlappedIoCompletedSync(poll_fd[_index].overlapped)) ) {
632 poll_dbg(" completed");
633 // checks above should ensure this works:
634 fds[i].revents = fds[i].events;
635 triggered++;
636 } else {
637 handles_to_wait_on[nb_handles_to_wait_on] = poll_fd[_ind ex].overlapped->hEvent;
638 handle_to_index[nb_handles_to_wait_on] = i;
639 #if defined(DYNAMIC_FDS)
640 // If this fd from the poll set is also part of the new_ fd event handle table, remove it
641 usbi_mutex_lock(&new_fd_mutex);
642 for (j=0; j<nb_new_fds; j++) {
643 if (handles_to_wait_on[nb_handles_to_wait_on] == new_fd[j]) {
644 new_fd[j] = INVALID_HANDLE_VALUE;
645 break;
646 }
647 }
648 usbi_mutex_unlock(&new_fd_mutex);
649 #endif
650 nb_handles_to_wait_on++;
651 }
652 LeaveCriticalSection(&_poll_fd[_index].mutex);
653 }
654 #if defined(DYNAMIC_FDS)
655 // At this stage, new_fd[] should only contain events from fds that
656 // have been added since the last call to poll, but are not (yet) part
657 // of the pollable fd set. Typically, these would be from fds that have
658 // been created between the construction of the fd set and the calling
659 // of poll.
660 // Event if we won't be able to return usable poll data on these events,
661 // make sure we monitor them to return an EINTR code
662 usbi_mutex_lock(&new_fd_mutex); // We could probably do without
663 for (i=0; i<nb_new_fds; i++) {
664 if (new_fd[i] != INVALID_HANDLE_VALUE) {
665 handles_to_wait_on[nb_handles_to_wait_on++] = new_fd[i];
666 nb_extra_handles++;
667 }
668 }
669 usbi_mutex_unlock(&new_fd_mutex);
670 poll_dbg("dynamic_fds: added %d extra handles", nb_extra_handles);
671 #endif
672
673 // If nothing was triggered, wait on all fds that require it
674 if ((timeout != 0) && (triggered == 0) && (nb_handles_to_wait_on != 0)) {
675 #if defined(DYNAMIC_FDS)
676 // Register for fd update notifications
677 handles_to_wait_on[nb_handles_to_wait_on++] = fd_update;
678 nb_extra_handles++;
679 #endif
680 if (timeout < 0) {
681 poll_dbg("starting infinite wait for %d handles...", (in t)nb_handles_to_wait_on);
682 } else {
683 poll_dbg("starting %d ms wait for %d handles...", timeou t, (int)nb_handles_to_wait_on);
684 }
685 ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_w ait_on,
686 FALSE, (timeout<0)?INFINITE:(DWORD)timeout);
687 object_index = ret-WAIT_OBJECT_0;
688 if ((object_index >= 0) && ((DWORD)object_index < nb_handles_to_ wait_on)) {
689 #if defined(DYNAMIC_FDS)
690 if ((DWORD)object_index >= (nb_handles_to_wait_on-nb_ext ra_handles)) {
691 // Detected fd update => flag a poll interruptio n
692 if ((DWORD)object_index == (nb_handles_to_wait_o n-1))
693 poll_dbg(" dynamic_fds: fd_update event ");
694 else
695 poll_dbg(" dynamic_fds: new fd I/O even t");
696 errno = EINTR;
697 triggered = -1;
698 goto poll_exit;
699 }
700 #endif
701 poll_dbg(" completed after wait");
702 i = handle_to_index[object_index];
703 _index = _fd_to_index_and_lock(fds[i].fd);
704 fds[i].revents = fds[i].events;
705 triggered++;
706 if (_index >= 0) {
707 LeaveCriticalSection(&_poll_fd[_index].mutex);
708 }
709 } else if (ret == WAIT_TIMEOUT) {
710 poll_dbg(" timed out");
711 triggered = 0; // 0 = timeout
712 } else {
713 errno = EIO;
714 triggered = -1; // error
715 }
716 }
717
718 poll_exit:
719 if (handles_to_wait_on != NULL) {
720 free(handles_to_wait_on);
721 }
722 if (handle_to_index != NULL) {
723 free(handle_to_index);
724 }
725 #if defined(DYNAMIC_FDS)
726 usbi_mutex_lock(&new_fd_mutex);
727 nb_new_fds = 0;
728 usbi_mutex_unlock(&new_fd_mutex);
729 #endif
730 return triggered;
731 }
732
733 /*
734 * close a fake pipe fd
735 */
736 int usbi_close(int fd)
737 {
738 int _index;
739 int r = -1;
740
741 CHECK_INIT_POLLING;
742
743 _index = _fd_to_index_and_lock(fd);
744
745 if (_index < 0) {
746 errno = EBADF;
747 } else {
748 if (poll_fd[_index].overlapped != NULL) {
749 // Must be a different event for each end of the pipe
750 CloseHandle(poll_fd[_index].overlapped->hEvent);
751 free(poll_fd[_index].overlapped);
752 }
753 r = _close(poll_fd[_index].fd);
754 if (r != 0) {
755 errno = EIO;
756 }
757 poll_fd[_index] = INVALID_WINFD;
758 LeaveCriticalSection(&_poll_fd[_index].mutex);
759 }
760 return r;
761 }
762
763 /*
764 * synchronous write for fake "pipe" signaling
765 */
766 ssize_t usbi_write(int fd, const void *buf, size_t count)
767 {
768 int _index;
769
770 CHECK_INIT_POLLING;
771
772 if (count != sizeof(unsigned char)) {
773 usbi_err(NULL, "this function should only used for signaling");
774 return -1;
775 }
776
777 _index = _fd_to_index_and_lock(fd);
778
779 if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) {
780 errno = EBADF;
781 if (_index >= 0) {
782 LeaveCriticalSection(&_poll_fd[_index].mutex);
783 }
784 return -1;
785 }
786
787 poll_dbg("set pipe event (fd = %d, thread = %08X)", _index, GetCurrentTh readId());
788 SetEvent(poll_fd[_index].overlapped->hEvent);
789 poll_fd[_index].overlapped->Internal = STATUS_WAIT_0;
790 // If two threads write on the pipe at the same time, we need to
791 // process two separate reads => use the overlapped as a counter
792 poll_fd[_index].overlapped->InternalHigh++;
793
794 LeaveCriticalSection(&_poll_fd[_index].mutex);
795 return sizeof(unsigned char);
796 }
797
798 /*
799 * synchronous read for fake "pipe" signaling
800 */
801 ssize_t usbi_read(int fd, void *buf, size_t count)
802 {
803 int _index;
804 ssize_t r = -1;
805
806 CHECK_INIT_POLLING;
807
808 if (count != sizeof(unsigned char)) {
809 usbi_err(NULL, "this function should only used for signaling");
810 return -1;
811 }
812
813 _index = _fd_to_index_and_lock(fd);
814
815 if (_index < 0) {
816 errno = EBADF;
817 return -1;
818 }
819
820 if (WaitForSingleObject(poll_fd[_index].overlapped->hEvent, INFINITE) != WAIT_OBJECT_0) {
821 usbi_warn(NULL, "waiting for event failed: %d", (int)GetLastErro r());
822 errno = EIO;
823 goto out;
824 }
825
826 poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, GetCurrentTh readId());
827 poll_fd[_index].overlapped->InternalHigh--;
828 // Don't reset unless we don't have any more events to process
829 if (poll_fd[_index].overlapped->InternalHigh <= 0) {
830 ResetEvent(poll_fd[_index].overlapped->hEvent);
831 poll_fd[_index].overlapped->Internal = STATUS_PENDING;
832 }
833
834 r = sizeof(unsigned char);
835
836 out:
837 LeaveCriticalSection(&_poll_fd[_index].mutex);
838 return r;
839 }
OLDNEW
« no previous file with comments | « third_party/libusb/libusb/os/poll_windows.h ('k') | third_party/libusb/libusb/os/threads_posix.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698