diff options
author | Pete Batard <pbatard@gmail.com> | 2010-08-15 21:44:13 +0100 |
---|---|---|
committer | Pete Batard <pbatard@gmail.com> | 2010-08-15 21:44:13 +0100 |
commit | 3cbb8af8742f1384f25df84b3d4047983cbce709 (patch) | |
tree | 432ceef3ad35829fb62c8bc95e1baf863057c2ce | |
parent | 689d78a0631b3ce2e341a947df0151f58e5ff21e (diff) | |
download | libusb-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.c | 14 | ||||
-rw-r--r-- | libusb/os/threads_windows.c | 10 | ||||
-rw-r--r-- | libusb/os/windows_usb.c | 19 |
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) { |