summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPete Batard <pbatard@gmail.com>2010-08-15 21:44:13 +0100
committerPete Batard <pbatard@gmail.com>2010-08-15 21:44:13 +0100
commit3cbb8af8742f1384f25df84b3d4047983cbce709 (patch)
tree432ceef3ad35829fb62c8bc95e1baf863057c2ce
parent689d78a0631b3ce2e341a947df0151f58e5ff21e (diff)
downloadlibusb-3cbb8af8742f1384f25df84b3d4047983cbce709.tar.gz
added Workaround for MinGW-w64 multilib bug
* current MinGW-w64 32 bit headers (winbase.h) are missing the WINAPI qualifier on Interlocked### calls * this results in missing decorations on symbols and failed linking as a result * this workaround hooks into kernel32.dll for these function calls to alleviate the issue
-rw-r--r--libusb/os/poll_windows.c14
-rw-r--r--libusb/os/threads_windows.c10
-rw-r--r--libusb/os/windows_usb.c19
3 files changed, 38 insertions, 5 deletions
diff --git a/libusb/os/poll_windows.c b/libusb/os/poll_windows.c
index 9ae9895..6941164 100644
--- a/libusb/os/poll_windows.c
+++ b/libusb/os/poll_windows.c
@@ -95,6 +95,14 @@ static inline int _open_osfhandle(intptr_t osfhandle, int flags)
#define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0)
+// Workaround for MinGW-w64 multilib bug
+static LONG (WINAPI *pInterlockedExchange)(LONG volatile *, LONG) = NULL;
+#define INIT_INTERLOCKEDEXCHANGE if (pInterlockedExchange == NULL) { \
+ pInterlockedExchange = (LONG (WINAPI *)(LONG volatile *, LONG)) \
+ GetProcAddress(GetModuleHandle("KERNEL32"), "InterlockedExchange"); \
+ if (pInterlockedExchange == NULL) return; \
+ }
+
// public fd data
const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, RW_NONE};
struct winfd poll_fd[MAX_FDS];
@@ -147,7 +155,8 @@ void init_polling(void)
{
int i;
- while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
+ INIT_INTERLOCKEDEXCHANGE;
+ while (pInterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
SleepEx(0, TRUE);
}
if (!is_polling_set) {
@@ -242,7 +251,8 @@ void exit_polling(void)
{
int i;
- while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
+ INIT_INTERLOCKEDEXCHANGE;
+ while (pInterlockedExchange((LONG *)&compat_spinlock, 1) == 1) {
SleepEx(0, TRUE);
}
if (is_polling_set) {
diff --git a/libusb/os/threads_windows.c b/libusb/os/threads_windows.c
index 8a29920..9d64fb0 100644
--- a/libusb/os/threads_windows.c
+++ b/libusb/os/threads_windows.c
@@ -25,6 +25,13 @@
#include "libusbi.h"
+// Workaround for MinGW-w64 multilib bug
+static LONG (WINAPI *pInterlockedExchange)(LONG volatile *, LONG) = NULL;
+#define INIT_INTERLOCKEDEXCHANGE if (pInterlockedExchange == NULL) { \
+ pInterlockedExchange = (LONG (WINAPI *)(LONG volatile *, LONG)) \
+ GetProcAddress(GetModuleHandle("KERNEL32"), "InterlockedExchange"); \
+ if (pInterlockedExchange == NULL) return ((errno=ENOENT)); \
+ }
int usbi_mutex_init(usbi_mutex_t *mutex,
const usbi_mutexattr_t *attr) {
@@ -68,7 +75,8 @@ int usbi_mutex_unlock(usbi_mutex_t *mutex) {
int usbi_mutex_static_lock(usbi_mutex_static_t *mutex) {
if(!mutex) return ((errno=EINVAL));
- while (InterlockedExchange((LONG *)mutex, 1) == 1) {
+ INIT_INTERLOCKEDEXCHANGE;
+ while (pInterlockedExchange((LONG *)mutex, 1) == 1) {
SleepEx(0, TRUE);
}
return 0;
diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c
index f41f064..bb37572 100644
--- a/libusb/os/windows_usb.c
+++ b/libusb/os/windows_usb.c
@@ -111,6 +111,19 @@ static int composite_abort_control(struct usbi_transfer *itransfer);
static int composite_reset_device(struct libusb_device_handle *dev_handle);
static int composite_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size);
+// Workaround for MinGW-w64 multilib bug
+static LONG (WINAPI *pInterlockedExchange)(LONG volatile *, LONG) = NULL;
+#define INIT_INTERLOCKEDEXCHANGE if (pInterlockedExchange == NULL) { \
+ pInterlockedExchange = (LONG (WINAPI *)(LONG volatile *, LONG)) \
+ GetProcAddress(GetModuleHandle("KERNEL32"), "InterlockedExchange"); \
+ if (pInterlockedExchange == NULL) return 1; \
+ }
+static LONG (WINAPI *pInterlockedIncrement)(LONG volatile *) = NULL;
+#define INIT_INTERLOCKEDINCREMENT if (pInterlockedIncrement == NULL) { \
+ pInterlockedIncrement = (LONG (WINAPI *)(LONG volatile *)) \
+ GetProcAddress(GetModuleHandle("KERNEL32"), "InterlockedIncrement");\
+ if (pInterlockedIncrement == NULL) return LIBUSB_ERROR_NOT_FOUND; \
+ }
// Global variables
struct windows_hcd_priv* hcd_root = NULL;
@@ -2121,7 +2134,8 @@ unsigned __stdcall windows_clock_gettime_threaded(void* param)
}
ReleaseMutex(timer_mutex);
- nb_responses = InterlockedExchange((LONG*)&request_count[0], 0);
+ INIT_INTERLOCKEDEXCHANGE;
+ nb_responses = pInterlockedExchange((LONG*)&request_count[0], 0);
if ( (nb_responses)
&& (ReleaseSemaphore(timer_response, nb_responses, NULL) == 0) ) {
usbi_dbg("unable to release timer semaphore %d: %s", windows_error_str(0));
@@ -2144,8 +2158,9 @@ static int windows_clock_gettime(int clk_id, struct timespec *tp)
switch(clk_id) {
case USBI_CLOCK_MONOTONIC:
if (hires_frequency != 0) {
+ INIT_INTERLOCKEDINCREMENT;
while (1) {
- InterlockedIncrement((LONG*)&request_count[0]);
+ pInterlockedIncrement((LONG*)&request_count[0]);
SetEvent(timer_request[0]);
r = WaitForSingleObject(timer_response, TIMER_REQUEST_RETRY_MS);
switch(r) {