From 76eef888a1925838d59330ddc34956674b89bd7b Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Sat, 30 Jan 2010 21:45:15 +0000 Subject: r127: merged concurrency branch with master (native improved concurrency handling for Windows files) [c119->c137]: c119: concurrency handling: - use semaphore in init/exit (Orin Eman) - use separate thread for timer and remove the need for affinity restoration - minor code readability improvements (moved GUIDs to .h) c120: removed unneeded disabling of APIs in winusb_exit & hid_exit c121: changed CreateThread to _beginthreadex, so CRT works properly when mem is low (Michael Plante) c122: made name of named-semaphore unique across the system per-process (Michael Plante) c123: allow timer thread to quit gracefully, and cleanup many of the handles (Michael Plante) c124: fixed concurrent_usage if init fails (Michael Plante) c125: drop PulseEvent in timer thread and use semaphore for response (Orin Eman). c126: removed pthread dependency in windows_compat.c c127: fixed missing reset of timer_request when event has already been handled c128: additional fixes for timer thread: - closed timer_mutex handles, and fixed volatile warning regarding interlocked ops (Michael Plante) - missing ResetEvent and possible missing request handling fix (Orin Eman) - additional fixes c129: use of spinlocks and critical sections in windows_compat.c for mutexes (Orin Eman, Michael Plante) c130: fixed missing spinlock in exit_polling c131: made spinlock static, changed to LONG, and casted off volatile in InterlockedExchange calls (Michael Plante) c132: additional security checks when entering critical sections in windows_compat.c c133: brought latest master commits to the concurrency branch [r119 -> r122] c134: fixed unfortunate inverted comparison introduced in c132 c135: fixed timer thread warnings with MinGW c136: brought latest master commits to the concurrency branch [r123 -> r126] c137: removed pthread.h and sched.h includes from windows_usb.c --- libusb/os/windows_compat.c | 141 ++++++++++++++++++++++++++++----------------- 1 file changed, 88 insertions(+), 53 deletions(-) (limited to 'libusb/os/windows_compat.c') diff --git a/libusb/os/windows_compat.c b/libusb/os/windows_compat.c index 58b91d3..4ff0c4f 100644 --- a/libusb/os/windows_compat.c +++ b/libusb/os/windows_compat.c @@ -71,7 +71,6 @@ #include #include #include -#include #include #include "windows_compat.h" @@ -129,7 +128,7 @@ const struct winfd INVALID_WINFD = {-1, NULL, NULL, RW_NONE, FALSE}; struct winfd poll_fd[MAX_FDS]; // internal fd data struct { - pthread_mutex_t mutex; // thread mutex lock for fds + CRITICAL_SECTION mutex; // lock for fds BYTE marker; // 1st byte of a read_for_poll operation gets stored here } _poll_fd[MAX_FDS]; @@ -137,25 +136,25 @@ struct { // globals BOOLEAN is_polling_set = FALSE; LONG pipe_number = 0; +static volatile LONG compat_spinlock = 0; // Init void init_polling(void) { int i; - if (is_polling_set) { - // The sleep 1 sec is to give enough time for our initialization - // below to finish, should concurrent simultaneous inits be issued - // from multiple threads - we don't want the second init to return - // before the first has had time to complete its job. - Sleep(1000); - return; + + while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) { + SleepEx(0, TRUE); } - is_polling_set = TRUE; - for (i=0; i 0) && (poll_fd[i].handle != INVALID_HANDLE_VALUE) && (poll_fd[i].handle != 0) - && (GetFileType(poll_fd[i].handle) == FILE_TYPE_UNKNOWN) ) { - _close(poll_fd[i].fd); + while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) { + SleepEx(0, TRUE); + } + if (is_polling_set) { + is_polling_set = FALSE; + + for (i=0; i 0) && (poll_fd[i].handle != INVALID_HANDLE_VALUE) && (poll_fd[i].handle != 0) + && (GetFileType(poll_fd[i].handle) == FILE_TYPE_UNKNOWN) ) { + _close(poll_fd[i].fd); + } + free_overlapped(poll_fd[i].overlapped); + poll_fd[i] = INVALID_WINFD; + LeaveCriticalSection(&_poll_fd[i].mutex); + DeleteCriticalSection(&_poll_fd[i].mutex); } - free_overlapped(poll_fd[i].overlapped); - poll_fd[i] = INVALID_WINFD; - pthread_mutex_unlock(&_poll_fd[i].mutex); - pthread_mutex_destroy(&_poll_fd[i].mutex); } + compat_spinlock = 0; } /* @@ -325,7 +334,13 @@ int _libusb_pipe(int filedes[2]) for (i=0, j=0; i= 0) { + LeaveCriticalSection(&_poll_fd[i].mutex); + continue; + } + poll_fd[i].fd = filedes[j]; poll_fd[i].handle = handle[j]; poll_fd[i].overlapped = (j==0)?overlapped0:overlapped1; @@ -337,7 +352,7 @@ int _libusb_pipe(int filedes[2]) // so that we get read event notifications _init_read_marker(i); } - pthread_mutex_unlock(&_poll_fd[i].mutex); + LeaveCriticalSection(&_poll_fd[i].mutex); if (j>=2) { return 0; } @@ -409,12 +424,17 @@ struct winfd create_fd_for_poll(HANDLE handle, int access_mode) for (i=0; i= 0) { + LeaveCriticalSection(&_poll_fd[i].mutex); + continue; + } wfd.fd = fd; wfd.handle = handle; wfd.overlapped = overlapped; memcpy(&poll_fd[i], &wfd, sizeof(struct winfd)); - pthread_mutex_unlock(&_poll_fd[i].mutex); + LeaveCriticalSection(&_poll_fd[i].mutex); return wfd; } } @@ -452,7 +472,7 @@ void free_fd_for_poll(int fd) return; } _free_index(index); - pthread_mutex_unlock(&_poll_fd[index].mutex); + LeaveCriticalSection(&_poll_fd[index].mutex); } /* @@ -470,9 +490,14 @@ struct winfd fd_to_winfd(int fd) for (i=0; i= 0) { - pthread_mutex_unlock(&_poll_fd[index].mutex); + LeaveCriticalSection(&_poll_fd[index].mutex); } printb("poll: invalid fd\n"); return -1; @@ -570,7 +605,7 @@ int _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout) fds[i].revents |= POLLNVAL | POLLERR; errno = EBADF; printb("poll: attempted POLLIN on fd[%d] without READ access\n", i); - pthread_mutex_unlock(&_poll_fd[index].mutex); + LeaveCriticalSection(&_poll_fd[index].mutex); return -1; } @@ -578,7 +613,7 @@ int _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout) fds[i].revents |= POLLNVAL | POLLERR; errno = EBADF; printb("poll: attempted POLLOUT on fd[%d] without WRITE access\n", i); - pthread_mutex_unlock(&_poll_fd[index].mutex); + LeaveCriticalSection(&_poll_fd[index].mutex); return -1; } @@ -596,7 +631,7 @@ int _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout) handle_to_index[nb_handles_to_wait_on] = i; nb_handles_to_wait_on++; } - pthread_mutex_unlock(&_poll_fd[index].mutex); + LeaveCriticalSection(&_poll_fd[index].mutex); } if (triggered != 0) @@ -616,7 +651,7 @@ int _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout) fds[i].revents = fds[i].events; triggered++; if (index >= 0) { - pthread_mutex_unlock(&_poll_fd[index].mutex); + LeaveCriticalSection(&_poll_fd[index].mutex); } } else if (ret == WAIT_TIMEOUT) { printb(" timed out\n"); @@ -654,7 +689,7 @@ int _libusb_close(int fd) } else { errno = 0; } - pthread_mutex_unlock(&_poll_fd[index].mutex); + LeaveCriticalSection(&_poll_fd[index].mutex); } return errno?-1:0; } @@ -684,7 +719,7 @@ ssize_t _libusb_write(int fd, const void *buf, size_t count) || (poll_fd[index].rw != RW_WRITE) ) { errno = EBADF; if (index >= 0) { - pthread_mutex_unlock(&_poll_fd[index].mutex); + LeaveCriticalSection(&_poll_fd[index].mutex); } return -1; } @@ -731,10 +766,10 @@ ssize_t _libusb_write(int fd, const void *buf, size_t count) out: if (errno) { reset_overlapped(poll_fd[index].overlapped); - pthread_mutex_unlock(&_poll_fd[index].mutex); + LeaveCriticalSection(&_poll_fd[index].mutex); return -1; } else { - pthread_mutex_unlock(&_poll_fd[index].mutex); + LeaveCriticalSection(&_poll_fd[index].mutex); return (ssize_t)wr_count; } } @@ -830,7 +865,7 @@ ssize_t _libusb_read(int fd, void *buf, size_t count) out: // Setup pending read I/O for the marker _init_read_marker(index); - pthread_mutex_unlock(&_poll_fd[index].mutex); + LeaveCriticalSection(&_poll_fd[index].mutex); if (errno) return -1; else -- cgit v1.2.1