diff options
Diffstat (limited to 'libusb/os')
-rw-r--r-- | libusb/os/threads_windows.c | 96 | ||||
-rw-r--r-- | libusb/os/threads_windows.h | 30 | ||||
-rw-r--r-- | libusb/os/windows_common.c | 16 | ||||
-rw-r--r-- | libusb/os/windows_common.h | 3 | ||||
-rw-r--r-- | libusb/os/windows_usbdk.c | 18 | ||||
-rw-r--r-- | libusb/os/windows_winusb.c | 17 |
6 files changed, 40 insertions, 140 deletions
diff --git a/libusb/os/threads_windows.c b/libusb/os/threads_windows.c index 030f89e..27b1fb5 100644 --- a/libusb/os/threads_windows.c +++ b/libusb/os/threads_windows.c @@ -2,6 +2,7 @@ * libusb synchronization on Microsoft Windows * * Copyright © 2010 Michael Plante <michael.plante@gmail.com> + * Copyright © 2020 Chris Dickens <christopher.a.dickens@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,97 +25,20 @@ #include "libusbi.h" -struct usbi_cond_perthread { - struct list_head list; - HANDLE event; -}; - -void usbi_cond_init(usbi_cond_t *cond) -{ - list_init(&cond->waiters); - list_init(&cond->not_waiting); -} - -static int usbi_cond_intwait(usbi_cond_t *cond, - usbi_mutex_t *mutex, DWORD timeout_ms) -{ - struct usbi_cond_perthread *pos; - DWORD r; - - // Same assumption as usbi_cond_broadcast() holds - if (list_empty(&cond->not_waiting)) { - pos = malloc(sizeof(*pos)); - if (pos == NULL) - return ENOMEM; // This errno is not POSIX-allowed. - pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset. - if (pos->event == NULL) { - free(pos); - return ENOMEM; - } - } else { - pos = list_first_entry(&cond->not_waiting, struct usbi_cond_perthread, list); - list_del(&pos->list); // remove from not_waiting list. - // Ensure the event is clear before waiting - WaitForSingleObject(pos->event, 0); - } - - list_add(&pos->list, &cond->waiters); - - LeaveCriticalSection(mutex); - r = WaitForSingleObject(pos->event, timeout_ms); - EnterCriticalSection(mutex); - - list_del(&pos->list); - list_add(&pos->list, &cond->not_waiting); - - if (r == WAIT_OBJECT_0) - return 0; - else if (r == WAIT_TIMEOUT) - return ETIMEDOUT; - else - return EINVAL; -} - -// N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot! -int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) -{ - return usbi_cond_intwait(cond, mutex, INFINITE); -} - int usbi_cond_timedwait(usbi_cond_t *cond, usbi_mutex_t *mutex, const struct timeval *tv) { DWORD millis; - millis = (DWORD)(tv->tv_sec * 1000) + (tv->tv_usec / 1000); + millis = (DWORD)(tv->tv_sec * 1000L) + (tv->tv_usec / 1000L); /* round up to next millisecond */ - if (tv->tv_usec % 1000) + if (tv->tv_usec % 1000L) millis++; - return usbi_cond_intwait(cond, mutex, millis); -} - -void usbi_cond_broadcast(usbi_cond_t *cond) -{ - // Assumes mutex is locked; this is not in keeping with POSIX spec, but - // libusb does this anyway, so we simplify by not adding more sync - // primitives to the CV definition! - struct usbi_cond_perthread *pos; - - list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) - SetEvent(pos->event); - // The wait function will remove its respective item from the list. -} -void usbi_cond_destroy(usbi_cond_t *cond) -{ - // This assumes no one is using this anymore. The check MAY NOT BE safe. - struct usbi_cond_perthread *pos, *next; - - if (!list_empty(&cond->waiters)) - return; // (!see above!) - list_for_each_entry_safe(pos, next, &cond->not_waiting, list, struct usbi_cond_perthread) { - CloseHandle(pos->event); - list_del(&pos->list); - free(pos); - } -} + if (SleepConditionVariableCS(cond, mutex, millis)) + return 0; + else if (GetLastError() == ERROR_TIMEOUT) + return ETIMEDOUT; + else + return EINVAL; +}
\ No newline at end of file diff --git a/libusb/os/threads_windows.h b/libusb/os/threads_windows.h index e971163..3a98df5 100644 --- a/libusb/os/threads_windows.h +++ b/libusb/os/threads_windows.h @@ -57,7 +57,7 @@ static inline void usbi_mutex_destroy(usbi_mutex_t *mutex) } // We *were* getting timespec from pthread.h: -#if (!defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED)) +#if !defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED) #define HAVE_STRUCT_TIMESPEC 1 #define _TIMESPEC_DEFINED 1 struct timespec { @@ -71,19 +71,25 @@ struct timespec { #define ETIMEDOUT 10060 /* This is the value in winsock.h. */ #endif -typedef struct usbi_cond { - // Every time a thread touches the CV, it winds up in one of these lists. - // It stays there until the CV is destroyed, even if the thread terminates. - struct list_head waiters; - struct list_head not_waiting; -} usbi_cond_t; - -void usbi_cond_init(usbi_cond_t *cond); -int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex); +typedef CONDITION_VARIABLE usbi_cond_t; +static inline void usbi_cond_init(usbi_cond_t *cond) +{ + InitializeConditionVariable(cond); +} +static inline void usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) +{ + (void)SleepConditionVariableCS(cond, mutex, INFINITE); +} int usbi_cond_timedwait(usbi_cond_t *cond, usbi_mutex_t *mutex, const struct timeval *tv); -void usbi_cond_broadcast(usbi_cond_t *cond); -void usbi_cond_destroy(usbi_cond_t *cond); +static inline void usbi_cond_broadcast(usbi_cond_t *cond) +{ + WakeAllConditionVariable(cond); +} +static inline void usbi_cond_destroy(usbi_cond_t *cond) +{ + UNUSED(cond); +} typedef DWORD usbi_tls_key_t; static inline void usbi_tls_key_create(usbi_tls_key_t *key) diff --git a/libusb/os/windows_common.c b/libusb/os/windows_common.c index 577899a..e69d0b0 100644 --- a/libusb/os/windows_common.c +++ b/libusb/os/windows_common.c @@ -34,7 +34,6 @@ #define EPOCH_TIME UINT64_C(116444736000000000) // 1970.01.01 00:00:000 in MS Filetime // Public -BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED); enum windows_version windows_version = WINDOWS_UNDEFINED; // Global variables for init/exit @@ -59,11 +58,6 @@ struct timer_request { static HANDLE timer_thread = NULL; static DWORD timer_thread_id = 0; -/* Kernel32 dependencies */ -DLL_DECLARE_HANDLE(Kernel32); -/* This call is only available from XP SP2 */ -DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, IsWow64Process, (HANDLE, PBOOL)); - /* User32 dependencies */ DLL_DECLARE_HANDLE(User32); DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, GetMessageA, (LPMSG, HWND, UINT, UINT)); @@ -287,12 +281,6 @@ void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size) static BOOL windows_init_dlls(void) { - DLL_GET_HANDLE(Kernel32); - DLL_LOAD_FUNC_PREFIXED(Kernel32, p, IsWow64Process, FALSE); - pCancelIoEx = (BOOL (WINAPI *)(HANDLE, LPOVERLAPPED)) - GetProcAddress(DLL_HANDLE_NAME(Kernel32), "CancelIoEx"); - usbi_dbg("Will use CancelIo%s for I/O cancellation", pCancelIoEx ? "Ex" : ""); - DLL_GET_HANDLE(User32); DLL_LOAD_FUNC_PREFIXED(User32, p, GetMessageA, TRUE); DLL_LOAD_FUNC_PREFIXED(User32, p, PeekMessageA, TRUE); @@ -303,7 +291,6 @@ static BOOL windows_init_dlls(void) static void windows_exit_dlls(void) { - DLL_FREE_HANDLE(Kernel32); DLL_FREE_HANDLE(User32); } @@ -394,8 +381,7 @@ static BOOL is_x64(void) // Detect if we're running a 32 or 64 bit system if (sizeof(uintptr_t) < 8) { - if (pIsWow64Process != NULL) - pIsWow64Process(GetCurrentProcess(), &ret); + IsWow64Process(GetCurrentProcess(), &ret); } else { ret = TRUE; } diff --git a/libusb/os/windows_common.h b/libusb/os/windows_common.h index 7533573..069b147 100644 --- a/libusb/os/windows_common.h +++ b/libusb/os/windows_common.h @@ -134,9 +134,6 @@ enum windows_version { extern enum windows_version windows_version; -/* This call is only available from Vista */ -extern BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED); - #include <pshpack1.h> typedef struct USB_DEVICE_DESCRIPTOR { diff --git a/libusb/os/windows_usbdk.c b/libusb/os/windows_usbdk.c index aa48ce2..bbec3d8 100644 --- a/libusb/os/windows_usbdk.c +++ b/libusb/os/windows_usbdk.c @@ -728,20 +728,12 @@ static int usbdk_abort_transfers(struct usbi_transfer *itransfer) struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer); struct winfd *pollable_fd = &transfer_priv->pollable_fd; - if (pCancelIoEx != NULL) { - // Use CancelIoEx if available to cancel just a single transfer - if (!pCancelIoEx(priv->system_handle, pollable_fd->overlapped)) { - usbi_err(ctx, "CancelIoEx failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - } else { - if (!usbdk_helper.AbortPipe(priv->redirector_handle, transfer->endpoint)) { - usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0)); - return LIBUSB_ERROR_NO_DEVICE; - } - } + // Use CancelIoEx to cancel just a single transfer + if (CancelIoEx(priv->system_handle, pollable_fd->overlapped)) + return LIBUSB_SUCCESS; - return LIBUSB_SUCCESS; + usbi_warn(ctx, "CancelIoEx failed: %s", windows_error_str(0)); + return LIBUSB_ERROR_NOT_FOUND; } static int usbdk_cancel_transfer(struct usbi_transfer *itransfer) diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index ddd6e86..9fd188f 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -2100,8 +2100,8 @@ static int winusbx_init(struct libusb_context *ctx) if (WinUSBX[i].Initialize != NULL) { WinUSBX[i].initialized = true; - // Assume driver supports CancelIoEx() if it is available - WinUSBX[i].CancelIoEx_supported = (pCancelIoEx != NULL); + // Assume driver supports CancelIoEx() + WinUSBX[i].CancelIoEx_supported = true; usbi_dbg("initalized sub API %s", winusbx_driver_names[i]); } else { usbi_warn(ctx, "Failed to initalize sub API %s", winusbx_driver_names[i]); @@ -2926,7 +2926,7 @@ static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer) if (WinUSBX[sub_api].CancelIoEx_supported) { // Try to use CancelIoEx if available to cancel just a single transfer handle = handle_priv->interface_handle[current_interface].dev_handle; - if (pCancelIoEx(handle, transfer_priv->pollable_fd.overlapped)) + if (CancelIoEx(handle, transfer_priv->pollable_fd.overlapped)) return LIBUSB_SUCCESS; else if (GetLastError() == ERROR_NOT_FOUND) return LIBUSB_ERROR_NOT_FOUND; @@ -3978,16 +3978,11 @@ static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer) hid_handle = handle_priv->interface_handle[current_interface].api_handle; - if (pCancelIoEx != NULL) { - // Use CancelIoEx if available to cancel just a single transfer - if (pCancelIoEx(hid_handle, transfer_priv->pollable_fd.overlapped)) + // Use CancelIoEx to cancel just a single transfer + if (CancelIoEx(hid_handle, transfer_priv->pollable_fd.overlapped)) return LIBUSB_SUCCESS; - } else { - if (CancelIo(hid_handle)) - return LIBUSB_SUCCESS; - } - usbi_warn(ctx, "cancel failed: %s", windows_error_str(0)); + usbi_warn(ctx, "CancelIoEx failed: %s", windows_error_str(0)); return LIBUSB_ERROR_NOT_FOUND; } |