Windows: Further improve thread abstraction

Adopt typedefs and inline functions to get the benefits of type checking.

Convert all trivial functions to inline and remove return values where
they aren't checked.

Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
This commit is contained in:
Chris Dickens
2018-01-04 13:42:52 -08:00
parent 3f69af8676
commit f06c4f5b37
3 changed files with 83 additions and 132 deletions

View File

@@ -29,87 +29,16 @@ struct usbi_cond_perthread {
HANDLE event;
};
int usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
void usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
{
while (InterlockedExchange(mutex, 1) == 1)
while (InterlockedExchange(mutex, 1L) == 1L)
SleepEx(0, TRUE);
return 0;
}
int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex)
{
InterlockedExchange(mutex, 0);
return 0;
}
int usbi_mutex_init(usbi_mutex_t *mutex)
{
InitializeCriticalSection(mutex);
return 0;
}
int usbi_mutex_lock(usbi_mutex_t *mutex)
{
EnterCriticalSection(mutex);
return 0;
}
int usbi_mutex_unlock(usbi_mutex_t *mutex)
{
LeaveCriticalSection(mutex);
return 0;
}
int usbi_mutex_trylock(usbi_mutex_t *mutex)
{
if (TryEnterCriticalSection(mutex))
return 0;
else
return EBUSY;
}
int usbi_mutex_destroy(usbi_mutex_t *mutex)
{
DeleteCriticalSection(mutex);
return 0;
}
int usbi_cond_init(usbi_cond_t *cond)
void usbi_cond_init(usbi_cond_t *cond)
{
list_init(&cond->waiters);
list_init(&cond->not_waiting);
return 0;
}
int 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 EBUSY; // (!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);
}
return 0;
}
int 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;
int r = 0;
list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) {
if (!SetEvent(pos->event))
r = EINVAL;
}
// The wait function will remove its respective item from the list.
return r;
}
static int usbi_cond_intwait(usbi_cond_t *cond,
@@ -170,37 +99,28 @@ int usbi_cond_timedwait(usbi_cond_t *cond,
return usbi_cond_intwait(cond, mutex, millis);
}
int usbi_tls_key_create(usbi_tls_key_t *key)
void usbi_cond_broadcast(usbi_cond_t *cond)
{
*key = TlsAlloc();
if (*key == TLS_OUT_OF_INDEXES)
return ENOMEM;
else
return 0;
// 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_tls_key_get(usbi_tls_key_t key)
void usbi_cond_destroy(usbi_cond_t *cond)
{
return TlsGetValue(key);
}
// This assumes no one is using this anymore. The check MAY NOT BE safe.
struct usbi_cond_perthread *pos, *next;
int usbi_tls_key_set(usbi_tls_key_t key, void *value)
{
if (TlsSetValue(key, value))
return 0;
else
return EINVAL;
}
int usbi_tls_key_delete(usbi_tls_key_t key)
{
if (TlsFree(key))
return 0;
else
return EINVAL;
}
int usbi_get_tid(void)
{
return (int)GetCurrentThreadId();
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);
}
}

View File

@@ -21,17 +21,36 @@
#ifndef LIBUSB_THREADS_WINDOWS_H
#define LIBUSB_THREADS_WINDOWS_H
#define usbi_mutex_static_t volatile LONG
#define USBI_MUTEX_INITIALIZER 0
#define USBI_MUTEX_INITIALIZER 0L
typedef volatile LONG usbi_mutex_static_t;
void usbi_mutex_static_lock(usbi_mutex_static_t *mutex);
static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex)
{
InterlockedExchange(mutex, 0L);
}
#define usbi_mutex_t CRITICAL_SECTION
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;
typedef CRITICAL_SECTION usbi_mutex_t;
static inline int usbi_mutex_init(usbi_mutex_t *mutex)
{
InitializeCriticalSection(mutex);
return 0;
}
static inline void usbi_mutex_lock(usbi_mutex_t *mutex)
{
EnterCriticalSection(mutex);
}
static inline void usbi_mutex_unlock(usbi_mutex_t *mutex)
{
LeaveCriticalSection(mutex);
}
static inline int usbi_mutex_trylock(usbi_mutex_t *mutex)
{
return !TryEnterCriticalSection(mutex);
}
static inline void usbi_mutex_destroy(usbi_mutex_t *mutex)
{
DeleteCriticalSection(mutex);
}
// We *were* getting timespec from pthread.h:
#if (!defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED))
@@ -45,32 +64,44 @@ struct timespec {
// We *were* getting ETIMEDOUT from pthread.h:
#ifndef ETIMEDOUT
# define ETIMEDOUT 10060 /* This is the value in winsock.h. */
#define ETIMEDOUT 10060 /* This is the value in winsock.h. */
#endif
#define usbi_tls_key_t DWORD
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;
int usbi_mutex_static_lock(usbi_mutex_static_t *mutex);
int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex);
int usbi_mutex_init(usbi_mutex_t *mutex);
int usbi_mutex_lock(usbi_mutex_t *mutex);
int usbi_mutex_unlock(usbi_mutex_t *mutex);
int usbi_mutex_trylock(usbi_mutex_t *mutex);
int usbi_mutex_destroy(usbi_mutex_t *mutex);
int usbi_cond_init(usbi_cond_t *cond);
void usbi_cond_init(usbi_cond_t *cond);
int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex);
int usbi_cond_timedwait(usbi_cond_t *cond,
usbi_mutex_t *mutex, const struct timeval *tv);
int usbi_cond_broadcast(usbi_cond_t *cond);
int usbi_cond_destroy(usbi_cond_t *cond);
void usbi_cond_broadcast(usbi_cond_t *cond);
void usbi_cond_destroy(usbi_cond_t *cond);
int usbi_tls_key_create(usbi_tls_key_t *key);
void *usbi_tls_key_get(usbi_tls_key_t key);
int usbi_tls_key_set(usbi_tls_key_t key, void *value);
int usbi_tls_key_delete(usbi_tls_key_t key);
typedef DWORD usbi_tls_key_t;
static inline void usbi_tls_key_create(usbi_tls_key_t *key)
{
*key = TlsAlloc();
}
static inline void *usbi_tls_key_get(usbi_tls_key_t key)
{
return TlsGetValue(key);
}
static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr)
{
(void)TlsSetValue(key, ptr);
}
static inline void usbi_tls_key_delete(usbi_tls_key_t key)
{
(void)TlsFree(key);
}
int usbi_get_tid(void);
static inline int usbi_get_tid(void)
{
return (int)GetCurrentThreadId();
}
#endif /* LIBUSB_THREADS_WINDOWS_H */

View File

@@ -1 +1 @@
#define LIBUSB_NANO 11250
#define LIBUSB_NANO 11251