Commit 44348970 authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

wineusb.sys: Spawn a separate thread to consume Unix library events.

parent 4676273b
......@@ -20,6 +20,7 @@
#include <assert.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdlib.h>
#include <pthread.h>
#include <libusb.h>
......@@ -107,6 +108,71 @@ static DEVICE_OBJECT *bus_fdo, *bus_pdo;
static libusb_hotplug_callback_handle hotplug_cb_handle;
static pthread_cond_t event_cond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t event_mutex = PTHREAD_MUTEX_INITIALIZER;
enum usb_event_type
{
USB_EVENT_SHUTDOWN,
};
struct usb_event
{
enum usb_event_type type;
};
static struct usb_event *usb_events;
static size_t usb_event_count, usb_events_capacity;
static bool array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
{
unsigned int new_capacity, max_capacity;
void *new_elements;
if (count <= *capacity)
return true;
max_capacity = ~(size_t)0 / size;
if (count > max_capacity)
return false;
new_capacity = max(4, *capacity);
while (new_capacity < count && new_capacity <= max_capacity / 2)
new_capacity *= 2;
if (new_capacity < count)
new_capacity = max_capacity;
if (!(new_elements = realloc(*elements, new_capacity * size)))
return false;
*elements = new_elements;
*capacity = new_capacity;
return true;
}
static void queue_event(const struct usb_event *event)
{
pthread_mutex_lock(&event_mutex);
if (array_reserve((void **)&usb_events, &usb_events_capacity, usb_event_count + 1, sizeof(*usb_events)))
usb_events[usb_event_count++] = *event;
else
ERR("Failed to queue event.\n");
pthread_mutex_unlock(&event_mutex);
pthread_cond_signal(&event_cond);
}
static void get_event(struct usb_event *event)
{
pthread_mutex_lock(&event_mutex);
while (!usb_event_count)
pthread_cond_wait(&event_cond, &event_mutex);
*event = usb_events[0];
if (--usb_event_count)
memmove(usb_events, usb_events + 1, usb_event_count * sizeof(*usb_events));
pthread_mutex_unlock(&event_mutex);
}
static void destroy_unix_device(struct unix_device *unix_device)
{
pthread_mutex_lock(&unix_device_mutex);
......@@ -293,7 +359,7 @@ static void remove_usb_device(libusb_device *libusb_device)
}
static BOOL thread_shutdown;
static HANDLE event_thread;
static HANDLE libusb_event_thread, event_thread;
static int LIBUSB_CALL hotplug_cb(libusb_context *context, libusb_device *device,
libusb_hotplug_event event, void *user_data)
......@@ -306,11 +372,12 @@ static int LIBUSB_CALL hotplug_cb(libusb_context *context, libusb_device *device
return 0;
}
static DWORD CALLBACK event_thread_proc(void *arg)
static DWORD CALLBACK libusb_event_thread_proc(void *arg)
{
static const struct usb_event shutdown_event = {.type = USB_EVENT_SHUTDOWN};
int ret;
TRACE("Starting event thread.\n");
TRACE("Starting libusb event thread.\n");
while (!thread_shutdown)
{
......@@ -318,10 +385,31 @@ static DWORD CALLBACK event_thread_proc(void *arg)
ERR("Error handling events: %s\n", libusb_strerror(ret));
}
TRACE("Shutting down event thread.\n");
queue_event(&shutdown_event);
TRACE("Shutting down libusb event thread.\n");
return 0;
}
static DWORD CALLBACK event_thread_proc(void *arg)
{
struct usb_event event;
TRACE("Starting client event thread.\n");
for (;;)
{
get_event(&event);
switch (event.type)
{
case USB_EVENT_SHUTDOWN:
TRACE("Shutting down client event thread.\n");
return 0;
}
}
}
static NTSTATUS fdo_pnp(IRP *irp)
{
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
......@@ -391,6 +479,8 @@ static NTSTATUS fdo_pnp(IRP *irp)
libusb_hotplug_deregister_callback(NULL, hotplug_cb_handle);
thread_shutdown = TRUE;
libusb_interrupt_event_handler(NULL);
WaitForSingleObject(libusb_event_thread, INFINITE);
CloseHandle(libusb_event_thread);
WaitForSingleObject(event_thread, INFINITE);
CloseHandle(event_thread);
......@@ -1007,6 +1097,7 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *path)
return STATUS_UNSUCCESSFUL;
}
libusb_event_thread = CreateThread(NULL, 0, libusb_event_thread_proc, NULL, 0, NULL);
event_thread = CreateThread(NULL, 0, event_thread_proc, NULL, 0, NULL);
driver->DriverExtension->AddDevice = driver_add_device;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment