Misc: Trim and consolidate header file usage
[platform/upstream/libusb.git] / libusb / os / poll_windows.c
1 /*
2  * poll_windows: poll compatibility wrapper for Windows
3  * Copyright © 2017 Chris Dickens <christopher.a.dickens@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *
19  */
20
21 /*
22  * poll() and pipe() Windows compatibility layer for libusb 1.0
23  *
24  * The way this layer works is by using OVERLAPPED with async I/O transfers, as
25  * OVERLAPPED have an associated event which is flagged for I/O completion.
26  *
27  * For USB pollable async I/O, you would typically:
28  * - obtain a Windows HANDLE to a file or device that has been opened in
29  *   OVERLAPPED mode
30  * - call usbi_create_fd with this handle to obtain a custom fd.
31  * - leave the core functions call the poll routine and flag POLLIN/POLLOUT
32  *
33  * The pipe pollable synchronous I/O works using the overlapped event associated
34  * with a fake pipe. The read/write functions are only meant to be used in that
35  * context.
36  */
37 #include <config.h>
38
39 #include <assert.h>
40 #include <errno.h>
41 #include <intrin.h>
42 #include <malloc.h>
43 #include <stdlib.h>
44
45 #include "libusbi.h"
46 #include "windows_common.h"
47
48 // public fd data
49 const struct winfd INVALID_WINFD = { -1, NULL };
50
51 // private data
52 struct file_descriptor {
53         enum fd_type { FD_TYPE_PIPE, FD_TYPE_TRANSFER } type;
54         LONG refcount;
55         OVERLAPPED overlapped;
56 };
57
58 static usbi_mutex_static_t fd_table_lock = USBI_MUTEX_INITIALIZER;
59
60 #define BITS_PER_BYTE                   8
61 #define BITMAP_BITS_PER_WORD            (sizeof(unsigned long) * BITS_PER_BYTE)
62 #define FD_TABLE_INCR_SIZE              64
63
64 static struct file_descriptor **fd_table;
65 static unsigned long *fd_table_bitmap;
66 static unsigned int fd_table_size;
67 static unsigned int fd_count;
68
69 #define return_with_errno(err)          \
70         do {                            \
71                 errno = (err);          \
72                 return -1;              \
73         } while (0)
74
75 static struct file_descriptor *alloc_fd(enum fd_type type, LONG refcount)
76 {
77         struct file_descriptor *fd = calloc(1, sizeof(*fd));
78
79         if (fd == NULL)
80                 return NULL;
81         fd->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
82         if (fd->overlapped.hEvent == NULL) {
83                 free(fd);
84                 return NULL;
85         }
86         fd->type = type;
87         fd->refcount = refcount;
88         return fd;
89 }
90
91 static struct file_descriptor *get_fd(unsigned int _fd, bool ref)
92 {
93         struct file_descriptor *fd = NULL;
94
95         if (_fd < fd_table_size)
96                 fd = fd_table[_fd];
97         if (fd != NULL && ref)
98                 InterlockedIncrement(&fd->refcount);
99
100         return fd;
101 }
102
103 static void put_fd(struct file_descriptor *fd)
104 {
105         if (InterlockedDecrement(&fd->refcount) == 0L) {
106                 CloseHandle(fd->overlapped.hEvent);
107                 free(fd);
108         }
109 }
110
111 static int install_fd(struct file_descriptor *fd)
112 {
113         unsigned int n;
114
115         if (fd_count == fd_table_size) {
116                 struct file_descriptor **new_table;
117                 unsigned long* new_bitmap;
118
119                 // Need to expand the fd table and bitmap
120                 new_table = realloc(fd_table, (fd_table_size + FD_TABLE_INCR_SIZE) * sizeof(*new_table));
121                 if (new_table == NULL)
122                         return -ENOMEM;
123                 memset(new_table + fd_table_size, 0, FD_TABLE_INCR_SIZE * sizeof(*new_table));
124                 fd_table = new_table;
125
126                 new_bitmap = realloc(fd_table_bitmap, (fd_table_size + FD_TABLE_INCR_SIZE) / BITS_PER_BYTE);
127                 if (new_bitmap == NULL)
128                         return -ENOMEM;
129                 memset(new_bitmap + (fd_table_size / BITMAP_BITS_PER_WORD), 0, FD_TABLE_INCR_SIZE / BITS_PER_BYTE);
130                 fd_table_bitmap = new_bitmap;
131
132                 fd_table_size += FD_TABLE_INCR_SIZE;
133                 assert(fd_table_size < (unsigned int)INT_MAX);
134         }
135
136         for (n = 0; n < fd_table_size; n += BITMAP_BITS_PER_WORD) {
137                 unsigned int idx = n / BITMAP_BITS_PER_WORD;
138                 unsigned long mask, pos;
139
140                 mask = ~fd_table_bitmap[idx];
141                 if (mask == 0UL)
142                         continue;
143
144                 assert(_BitScanForward(&pos, mask));
145                 fd_table_bitmap[idx] |= 1UL << pos;
146                 n += pos;
147                 break;
148         }
149
150         assert(n < fd_table_size);
151         assert(fd_table[n] == NULL);
152         fd_table[n] = fd;
153         fd_count++;
154
155         return n;
156 }
157
158 static void remove_fd(unsigned int pos)
159 {
160         assert(fd_table[pos] != NULL);
161         fd_table[pos] = NULL;
162         fd_table_bitmap[pos / BITMAP_BITS_PER_WORD] &= ~(1UL << (pos % BITMAP_BITS_PER_WORD));
163         fd_count--;
164         if (fd_count == 0) {
165                 free(fd_table);
166                 free(fd_table_bitmap);
167                 fd_table = NULL;
168                 fd_table_bitmap = NULL;
169                 fd_table_size = 0;
170         }
171 }
172
173 /*
174  * Create both an fd and an OVERLAPPED, so that it can be used with our
175  * polling function
176  * The handle MUST support overlapped transfers (usually requires CreateFile
177  * with FILE_FLAG_OVERLAPPED)
178  * Return a pollable file descriptor struct, or INVALID_WINFD on error
179  *
180  * Note that the fd returned by this function is a per-transfer fd, rather
181  * than a per-session fd and cannot be used for anything else but our
182  * custom functions.
183  * if you plan to do R/W on the same handle, you MUST create 2 fds: one for
184  * read and one for write. Using a single R/W fd is unsupported and will
185  * produce unexpected results
186  */
187 struct winfd usbi_create_fd(void)
188 {
189         struct file_descriptor *fd;
190         struct winfd wfd;
191
192         fd = alloc_fd(FD_TYPE_TRANSFER, 1);
193         if (fd == NULL)
194                 return INVALID_WINFD;
195
196         usbi_mutex_static_lock(&fd_table_lock);
197         wfd.fd = install_fd(fd);
198         usbi_mutex_static_unlock(&fd_table_lock);
199
200         if (wfd.fd < 0) {
201                 put_fd(fd);
202                 return INVALID_WINFD;
203         }
204
205         wfd.overlapped = &fd->overlapped;
206
207         return wfd;
208 }
209
210 struct wait_thread_data {
211         HANDLE thread;
212         HANDLE handles[MAXIMUM_WAIT_OBJECTS];
213         DWORD num_handles;
214         DWORD error;
215 };
216
217 static DWORD WINAPI WaitThread(LPVOID lpParam)
218 {
219         struct wait_thread_data *thread_data = lpParam;
220         HANDLE notify_event = thread_data->handles[0];
221         DWORD status;
222
223         status = WaitForMultipleObjects(thread_data->num_handles, thread_data->handles, FALSE, INFINITE);
224         if ((status >= WAIT_OBJECT_0) && (status < (WAIT_OBJECT_0 + thread_data->num_handles))) {
225                 if (status > WAIT_OBJECT_0) {
226                         // This will wake up all the other waiting threads
227                         SetEvent(notify_event);
228                 }
229                 thread_data->error = 0;
230         } else {
231                 assert(status == WAIT_FAILED);
232                 thread_data->error = (status == WAIT_FAILED) ? GetLastError() : ERROR_CAN_NOT_COMPLETE;
233         }
234
235         return 0;
236 }
237
238 static DWORD poll_wait(const HANDLE *wait_handles, DWORD num_wait_handles, DWORD timeout)
239 {
240         struct wait_thread_data *thread_data;
241         HANDLE notify_event;
242         HANDLE* handles;
243         int n, num_threads;
244         DWORD error, status;
245
246         if (num_wait_handles <= MAXIMUM_WAIT_OBJECTS)
247                 return WaitForMultipleObjects(num_wait_handles, wait_handles, FALSE, timeout);
248
249         // To wait on more than MAXIMUM_WAIT_OBJECTS, each thread (including the
250         // current thread) will wait on an event and (MAXIMUM_WAIT_OBJECTS - 1)
251         // HANDLEs.  The event is shared amongst all threads so that any thread
252         // that returns from a WaitForMultipleObjects() call will set the event
253         // and wake up all the other threads.
254         notify_event = CreateEvent(NULL, FALSE, FALSE, NULL);
255         if (notify_event == NULL)
256                 return WAIT_FAILED;
257
258         num_threads = 1 + (num_wait_handles - MAXIMUM_WAIT_OBJECTS - 1) / (MAXIMUM_WAIT_OBJECTS - 1);
259         thread_data = malloc(num_threads * sizeof(*thread_data));
260         if (thread_data == NULL) {
261                 CloseHandle(notify_event);
262                 SetLastError(ERROR_OUTOFMEMORY);
263                 return WAIT_FAILED;
264         }
265
266         handles = _alloca(MAXIMUM_WAIT_OBJECTS * sizeof(HANDLE));
267         handles[0] = notify_event;
268         memcpy(handles + 1, wait_handles, (MAXIMUM_WAIT_OBJECTS - 1) * sizeof(HANDLE));
269         wait_handles += MAXIMUM_WAIT_OBJECTS - 1;
270         num_wait_handles -= MAXIMUM_WAIT_OBJECTS - 1;
271
272         for (n = 0; n < num_threads; n++) {
273                 DWORD copy_size = MIN(num_wait_handles, MAXIMUM_WAIT_OBJECTS - 1);
274
275                 thread_data[n].handles[0] = notify_event;
276                 memcpy(thread_data[n].handles + 1, wait_handles, copy_size * sizeof(HANDLE));
277                 thread_data[n].num_handles = copy_size + 1;
278
279                 // Create the thread that will wait on these HANDLEs
280                 thread_data[n].thread = CreateThread(NULL, 0, WaitThread, &thread_data[n], 0, NULL);
281                 if (thread_data[n].thread == NULL) {
282                         thread_data[n].error = GetLastError();
283                         SetEvent(notify_event);
284                         num_threads = n + 1;
285                         break;
286                 }
287
288                 wait_handles += copy_size;
289                 num_wait_handles -= copy_size;
290         }
291
292         status = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, handles, FALSE, timeout);
293         if ((status >= WAIT_OBJECT_0) && (status < (WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS))) {
294                 if (status > WAIT_OBJECT_0) {
295                         // Wake up all the waiting threads
296                         SetEvent(notify_event);
297                         status = WAIT_OBJECT_0;
298                 }
299                 error = 0;
300         } else if (status == WAIT_TIMEOUT) {
301                 // Wake up all the waiting threads
302                 SetEvent(notify_event);
303                 error = 0;
304         } else {
305                 assert(status == WAIT_FAILED);
306                 error = (status == WAIT_FAILED) ? GetLastError() : ERROR_CAN_NOT_COMPLETE;
307         }
308
309         for (n = 0; n < num_threads; n++) {
310                 if (thread_data[n].thread != NULL) {
311                         if (WaitForSingleObject(thread_data[n].thread, INFINITE) != WAIT_OBJECT_0)
312                                 usbi_err(NULL, "WaitForSingleObject() failed: %lu", GetLastError());
313                         CloseHandle(thread_data[n].thread);
314                 }
315                 if (thread_data[n].error) {
316                         usbi_err(NULL, "wait thread %d had error %lu\n", n, thread_data[n].error);
317                         error = thread_data[n].error;
318                         status = WAIT_FAILED;
319                 }
320         }
321
322         free(thread_data);
323
324         CloseHandle(notify_event);
325
326         if (status == WAIT_FAILED)
327                 SetLastError(error);
328
329         return status;
330 }
331
332 /*
333  * POSIX poll equivalent, using Windows OVERLAPPED
334  * Currently, this function only accepts one of POLLIN or POLLOUT per fd
335  * (but you can create multiple fds from the same handle for read and write)
336  */
337 int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout)
338 {
339         struct file_descriptor **fds_array;
340         HANDLE *handles_array;
341         struct file_descriptor *fd;
342         unsigned int n;
343         int nready;
344
345         if (nfds <= MAXIMUM_WAIT_OBJECTS) {
346                 fds_array = _alloca(nfds * sizeof(*fds_array));
347                 handles_array = _alloca(nfds * sizeof(*handles_array));
348         } else {
349                 fds_array = malloc(nfds * sizeof(*fds_array));
350                 if (fds_array == NULL)
351                         return_with_errno(ENOMEM);
352                 handles_array = malloc(nfds * sizeof(*handles_array));
353                 if (handles_array == NULL) {
354                         free(fds_array);
355                         return_with_errno(ENOMEM);
356                 }
357         }
358
359         usbi_mutex_static_lock(&fd_table_lock);
360         for (n = 0; n < nfds; n++) {
361                 struct pollfd *pfd = &fds[n];
362
363                 // Keep it simple - only allow either POLLIN *or* POLLOUT
364                 assert((pfd->events == POLLIN) || (pfd->events == POLLOUT));
365                 if ((pfd->events != POLLIN) && (pfd->events != POLLOUT)) {
366                         fds_array[n] = NULL;
367                         continue;
368                 }
369
370                 // All file descriptors must be valid
371                 fd = get_fd(pfd->fd, true);
372                 assert(fd != NULL);
373                 if (fd == NULL) {
374                         fds_array[n] = NULL;
375                         continue;
376                 }
377
378                 // We hold a reference to fd for the duration of usbi_poll()
379                 fds_array[n] = fd;
380                 handles_array[n] = fd->overlapped.hEvent;
381         }
382         usbi_mutex_static_unlock(&fd_table_lock);
383
384         nready = 0;
385         while (nready == 0) {
386                 DWORD ret;
387
388                 // Check all fds for events
389                 for (n = 0; n < nfds; n++) {
390                         fd = fds_array[n];
391                         if (fd == NULL) {
392                                 fds[n].revents = POLLNVAL;
393                                 nready++;
394                         } else if (HasOverlappedIoCompleted(&fd->overlapped) &&
395                                         (WaitForSingleObject(fd->overlapped.hEvent, 0) == WAIT_OBJECT_0)) {
396                                 fds[n].revents = fds[n].events;
397                                 nready++;
398                         } else {
399                                 fds[n].revents = 0;
400                         }
401                 }
402
403                 if ((nready != 0) || (timeout == 0))
404                         break;
405
406                 // Wait for any of the events to trigger
407                 ret = poll_wait(handles_array, nfds, (timeout < 0) ? INFINITE : (DWORD)timeout);
408                 if (ret == WAIT_TIMEOUT) {
409                         assert(timeout > 0);
410                         timeout = 0;
411                 } else if (ret == WAIT_FAILED) {
412                         usbi_err(NULL, "WaitForMultipleObjects failed: %lu", GetLastError());
413                         errno = EIO;
414                         nready = -1;
415                 }
416         }
417
418         for (n = 0; n < nfds; n++) {
419                 if (fds_array[n] != NULL)
420                         put_fd(fds_array[n]);
421         }
422
423         if (nfds > MAXIMUM_WAIT_OBJECTS) {
424                 free(handles_array);
425                 free(fds_array);
426         }
427
428         return nready;
429 }
430
431 /*
432  * close a fake file descriptor
433  */
434 int usbi_close(int _fd)
435 {
436         struct file_descriptor *fd;
437
438         usbi_mutex_static_lock(&fd_table_lock);
439         fd = get_fd(_fd, false);
440         if (fd != NULL)
441                 remove_fd(_fd);
442         usbi_mutex_static_unlock(&fd_table_lock);
443
444         if (fd == NULL)
445                 return_with_errno(EBADF);
446
447         put_fd(fd);
448
449         return 0;
450 }
451
452 /*
453 * Create a fake pipe.
454 * As libusb only uses pipes for signaling, all we need from a pipe is an
455 * event. To that extent, we create a single wfd and overlapped as a means
456 * to access that event.
457 */
458 int usbi_pipe(int filedes[2])
459 {
460         struct file_descriptor *fd;
461         int r_fd, w_fd;
462         int error = 0;
463
464         fd = alloc_fd(FD_TYPE_PIPE, 2);
465         if (fd == NULL)
466                 return_with_errno(ENOMEM);
467
468         fd->overlapped.Internal = STATUS_PENDING;
469
470         usbi_mutex_static_lock(&fd_table_lock);
471         r_fd = install_fd(fd);
472         if (r_fd >= 0) {
473                 w_fd = install_fd(fd);
474                 if (w_fd < 0) {
475                         remove_fd(r_fd);
476                         error = w_fd;
477                 }
478         } else {
479                 error = r_fd;
480                 w_fd = -1; // Keep compiler happy
481         }
482         usbi_mutex_static_unlock(&fd_table_lock);
483
484         if (error) {
485                 CloseHandle(fd->overlapped.hEvent);
486                 free(fd);
487                 return_with_errno(error);
488         }
489
490         filedes[0] = r_fd;
491         filedes[1] = w_fd;
492
493         return 0;
494 }
495
496 /*
497  * synchronous write for fake "pipe" signaling
498  */
499 ssize_t usbi_write(int _fd, const void *buf, size_t count)
500 {
501         struct file_descriptor *fd;
502
503         UNUSED(buf);
504
505         if (count != sizeof(unsigned char)) {
506                 usbi_err(NULL, "this function should only used for signaling");
507                 return_with_errno(EINVAL);
508         }
509
510         usbi_mutex_static_lock(&fd_table_lock);
511         fd = get_fd(_fd, false);
512         if (fd && fd->type == FD_TYPE_PIPE) {
513                 assert(fd->overlapped.Internal == STATUS_PENDING);
514                 fd->overlapped.Internal = STATUS_WAIT_0;
515                 SetEvent(fd->overlapped.hEvent);
516         } else {
517                 fd = NULL;
518         }
519         usbi_mutex_static_unlock(&fd_table_lock);
520
521         if (fd == NULL)
522                 return_with_errno(EBADF);
523
524         return sizeof(unsigned char);
525 }
526
527 /*
528  * synchronous read for fake "pipe" signaling
529  */
530 ssize_t usbi_read(int _fd, void *buf, size_t count)
531 {
532         struct file_descriptor *fd;
533
534         UNUSED(buf);
535
536         if (count != sizeof(unsigned char)) {
537                 usbi_err(NULL, "this function should only used for signaling");
538                 return_with_errno(EINVAL);
539         }
540
541         usbi_mutex_static_lock(&fd_table_lock);
542         fd = get_fd(_fd, false);
543         if (fd && fd->type == FD_TYPE_PIPE) {
544                 assert(fd->overlapped.Internal == STATUS_WAIT_0);
545                 fd->overlapped.Internal = STATUS_PENDING;
546                 ResetEvent(fd->overlapped.hEvent);
547         } else {
548                 fd = NULL;
549         }
550         usbi_mutex_static_unlock(&fd_table_lock);
551
552         if (fd == NULL)
553                 return_with_errno(EBADF);
554
555         return sizeof(unsigned char);
556 }