Make the initialization thread-safe
Perform the initialization inside a critical section. Unfortunately Windows critical sections, which are the simplest synchronization mechanism available on Windows, do not support static initialization. A call to InitializeCriticalSection is required. Therefore a simple spinlock, with an implementation based on atomic operations, is used as a workaround.
This commit is contained in:
parent
7b920f5c42
commit
f708eadcfd
@ -154,6 +154,7 @@ AC_CHECK_HEADERS([linux/serial.h])
|
|||||||
AC_CHECK_HEADERS([IOKit/serial/ioss.h])
|
AC_CHECK_HEADERS([IOKit/serial/ioss.h])
|
||||||
AC_CHECK_HEADERS([getopt.h])
|
AC_CHECK_HEADERS([getopt.h])
|
||||||
AC_CHECK_HEADERS([sys/param.h])
|
AC_CHECK_HEADERS([sys/param.h])
|
||||||
|
AC_CHECK_HEADERS([pthread.h])
|
||||||
|
|
||||||
# Checks for global variable declarations.
|
# Checks for global variable declarations.
|
||||||
AC_CHECK_DECLS([optreset])
|
AC_CHECK_DECLS([optreset])
|
||||||
|
|||||||
44
src/usbhid.c
44
src/usbhid.c
@ -24,6 +24,13 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_PTHREAD_H
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define NOGDI
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_HIDAPI)
|
#if defined(HAVE_HIDAPI)
|
||||||
#define USE_HIDAPI
|
#define USE_HIDAPI
|
||||||
@ -47,6 +54,14 @@
|
|||||||
#include "context-private.h"
|
#include "context-private.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
typedef LONG dc_mutex_t;
|
||||||
|
#define DC_MUTEX_INIT 0
|
||||||
|
#else
|
||||||
|
typedef pthread_mutex_t dc_mutex_t;
|
||||||
|
#define DC_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
|
||||||
|
#endif
|
||||||
|
|
||||||
struct dc_usbhid_t {
|
struct dc_usbhid_t {
|
||||||
/* Library context. */
|
/* Library context. */
|
||||||
dc_context_t *context;
|
dc_context_t *context;
|
||||||
@ -87,16 +102,41 @@ syserror(int errcode)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USBHID
|
#ifdef USBHID
|
||||||
|
static dc_mutex_t g_usbhid_mutex = DC_MUTEX_INIT;
|
||||||
static size_t g_usbhid_refcount = 0;
|
static size_t g_usbhid_refcount = 0;
|
||||||
#ifdef USE_LIBUSB
|
#ifdef USE_LIBUSB
|
||||||
static libusb_context *g_usbhid_ctx = NULL;
|
static libusb_context *g_usbhid_ctx = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
dc_mutex_lock (dc_mutex_t *mutex)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
while (InterlockedCompareExchange (mutex, 1, 0) == 1) {
|
||||||
|
SleepEx (0, TRUE);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
pthread_mutex_lock (mutex);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dc_mutex_unlock (dc_mutex_t *mutex)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
InterlockedExchange (mutex, 0);
|
||||||
|
#else
|
||||||
|
pthread_mutex_unlock (mutex);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
dc_usbhid_init (dc_context_t *context)
|
dc_usbhid_init (dc_context_t *context)
|
||||||
{
|
{
|
||||||
dc_status_t status = DC_STATUS_SUCCESS;
|
dc_status_t status = DC_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
dc_mutex_lock (&g_usbhid_mutex);
|
||||||
|
|
||||||
if (g_usbhid_refcount == 0) {
|
if (g_usbhid_refcount == 0) {
|
||||||
#if defined(USE_LIBUSB)
|
#if defined(USE_LIBUSB)
|
||||||
int rc = libusb_init (&g_usbhid_ctx);
|
int rc = libusb_init (&g_usbhid_ctx);
|
||||||
@ -119,12 +159,14 @@ dc_usbhid_init (dc_context_t *context)
|
|||||||
g_usbhid_refcount++;
|
g_usbhid_refcount++;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
dc_mutex_unlock (&g_usbhid_mutex);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
dc_usbhid_exit (void)
|
dc_usbhid_exit (void)
|
||||||
{
|
{
|
||||||
|
dc_mutex_lock (&g_usbhid_mutex);
|
||||||
|
|
||||||
if (--g_usbhid_refcount == 0) {
|
if (--g_usbhid_refcount == 0) {
|
||||||
#if defined(USE_LIBUSB)
|
#if defined(USE_LIBUSB)
|
||||||
@ -135,6 +177,8 @@ dc_usbhid_exit (void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dc_mutex_unlock (&g_usbhid_mutex);
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user