summaryrefslogtreecommitdiff
path: root/libusb/os/windows_compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'libusb/os/windows_compat.c')
-rw-r--r--libusb/os/windows_compat.c141
1 files changed, 88 insertions, 53 deletions
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 <stdio.h>
#include <stdlib.h>
#include <stdint.h>
-#include <pthread.h>
#include <io.h>
#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<MAX_FDS; i++) {
- poll_fd[i] = INVALID_WINFD;
- _poll_fd[i].marker = 0;
- pthread_mutex_init(&_poll_fd[i].mutex, NULL);
+ if (!is_polling_set) {
+ for (i=0; i<MAX_FDS; i++) {
+ poll_fd[i] = INVALID_WINFD;
+ _poll_fd[i].marker = 0;
+ InitializeCriticalSection(&_poll_fd[i].mutex);
+ }
+ is_polling_set = TRUE;
}
+ compat_spinlock = 0;
}
// Internal function to retrieve the table index (and lock the fd mutex)
@@ -168,7 +167,12 @@ int _fd_to_index_and_lock(int fd)
for (i=0; i<MAX_FDS; i++) {
if (poll_fd[i].fd == fd) {
- pthread_mutex_lock(&_poll_fd[i].mutex);
+ EnterCriticalSection(&_poll_fd[i].mutex);
+ // fd might have changed before we got to critical
+ if (poll_fd[i].fd != fd) {
+ LeaveCriticalSection(&_poll_fd[i].mutex);
+ continue;
+ }
return i;
}
}
@@ -218,26 +222,31 @@ void reset_overlapped(OVERLAPPED *overlapped)
void exit_polling(void)
{
int i;
- if (!is_polling_set)
- return;
- is_polling_set = FALSE;
- for (i=0; i<MAX_FDS; i++) {
- // Cancel any async I/O (handle can be invalid)
- CancelIo(poll_fd[i].handle);
- // If anything was pending on that I/O, it should be
- // terminating, and we should be able to access the fd
- // mutex lock before too long
- pthread_mutex_lock(&_poll_fd[i].mutex);
- if ( (poll_fd[i].fd > 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<MAX_FDS; i++) {
+ // Cancel any async I/O (handle can be invalid)
+ CancelIo(poll_fd[i].handle);
+ // If anything was pending on that I/O, it should be
+ // terminating, and we should be able to access the fd
+ // mutex lock before too long
+ EnterCriticalSection(&_poll_fd[i].mutex);
+ if ( (poll_fd[i].fd > 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<MAX_FDS; i++) {
if (poll_fd[i].fd < 0) {
- pthread_mutex_lock(&_poll_fd[i].mutex);
+ EnterCriticalSection(&_poll_fd[i].mutex);
+ // fd might have been allocated before we got to critical
+ if (poll_fd[i].fd >= 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<MAX_FDS; i++) {
if (poll_fd[i].fd < 0) {
- pthread_mutex_lock(&_poll_fd[i].mutex);
+ EnterCriticalSection(&_poll_fd[i].mutex);
+ // fd might have been removed before we got to critical
+ if (poll_fd[i].fd >= 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<MAX_FDS; i++) {
if (poll_fd[i].fd == fd) {
- pthread_mutex_lock(&_poll_fd[i].mutex);
+ EnterCriticalSection(&_poll_fd[i].mutex);
+ // fd might have been deleted before we got to critical
+ if (poll_fd[i].fd != fd) {
+ LeaveCriticalSection(&_poll_fd[i].mutex);
+ continue;
+ }
memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
- pthread_mutex_unlock(&_poll_fd[i].mutex);
+ LeaveCriticalSection(&_poll_fd[i].mutex);
return wfd;
}
}
@@ -491,9 +516,14 @@ struct winfd handle_to_winfd(HANDLE handle)
for (i=0; i<MAX_FDS; i++) {
if (poll_fd[i].handle == handle) {
- pthread_mutex_lock(&_poll_fd[i].mutex);
+ EnterCriticalSection(&_poll_fd[i].mutex);
+ // fd might have been deleted before we got to critical
+ if (poll_fd[i].handle != handle) {
+ LeaveCriticalSection(&_poll_fd[i].mutex);
+ continue;
+ }
memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
- pthread_mutex_unlock(&_poll_fd[i].mutex);
+ LeaveCriticalSection(&_poll_fd[i].mutex);
return wfd;
}
}
@@ -512,9 +542,14 @@ struct winfd overlapped_to_winfd(OVERLAPPED* overlapped)
for (i=0; i<MAX_FDS; i++) {
if (poll_fd[i].overlapped == overlapped) {
- pthread_mutex_lock(&_poll_fd[i].mutex);
+ EnterCriticalSection(&_poll_fd[i].mutex);
+ // fd might have been deleted before we got to critical
+ if (poll_fd[i].overlapped != overlapped) {
+ LeaveCriticalSection(&_poll_fd[i].mutex);
+ continue;
+ }
memcpy(&wfd, &poll_fd[i], sizeof(struct winfd));
- pthread_mutex_unlock(&_poll_fd[i].mutex);
+ LeaveCriticalSection(&_poll_fd[i].mutex);
return wfd;
}
}
@@ -559,7 +594,7 @@ int _libusb_poll(struct pollfd *fds, unsigned int nfds, int timeout)
fds[i].revents |= POLLNVAL | POLLERR;
errno = EBADF;
if (index >= 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