Module: wine Branch: master Commit: 85082e8bd3c9bcb0b45fc56b55cc7c88c653d028 URL: https://source.winehq.org/git/wine.git/?a=commit;h=85082e8bd3c9bcb0b45fc56b5...
Author: Jacek Caban jacek@codeweavers.com Date: Wed May 8 23:09:03 2019 +0200
hidclass.sys: Make read IRP queue thread safe.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Aric Stewart aric@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/hidclass.sys/Makefile.in | 2 +- dlls/hidclass.sys/device.c | 34 ++++++++++++++++++++++++---------- dlls/hidclass.sys/hid.h | 1 + dlls/hidclass.sys/pnp.c | 1 + 4 files changed, 27 insertions(+), 11 deletions(-)
diff --git a/dlls/hidclass.sys/Makefile.in b/dlls/hidclass.sys/Makefile.in index e942217..209c2df 100644 --- a/dlls/hidclass.sys/Makefile.in +++ b/dlls/hidclass.sys/Makefile.in @@ -1,6 +1,6 @@ MODULE = hidclass.sys IMPORTLIB = hidclass -IMPORTS = ntoskrnl +IMPORTS = hal ntoskrnl DELAYIMPORTS = setupapi hid
C_SRCS = \ diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 81d5c3c..fcdb1b8 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -126,10 +126,25 @@ error: return STATUS_UNSUCCESSFUL; }
+static IRP *pop_irp_from_queue(BASE_DEVICE_EXTENSION *ext) +{ + LIST_ENTRY *entry; + KIRQL old_irql; + IRP *irp = NULL; + + KeAcquireSpinLock(&ext->irp_queue_lock, &old_irql); + + entry = RemoveHeadList(&ext->irp_queue); + if (entry != &ext->irp_queue) + irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.s.ListEntry); + + KeReleaseSpinLock(&ext->irp_queue_lock, old_irql); + return irp; +} + void HID_DeleteDevice(HID_MINIDRIVER_REGISTRATION *driver, DEVICE_OBJECT *device) { BASE_DEVICE_EXTENSION *ext; - LIST_ENTRY *entry; IRP *irp;
ext = device->DeviceExtension; @@ -145,13 +160,10 @@ void HID_DeleteDevice(HID_MINIDRIVER_REGISTRATION *driver, DEVICE_OBJECT *device if (ext->ring_buffer) RingBuffer_Destroy(ext->ring_buffer);
- entry = RemoveHeadList(&ext->irp_queue); - while(entry != &ext->irp_queue) + while((irp = pop_irp_from_queue(ext))) { - irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.s.ListEntry); irp->IoStatus.u.Status = STATUS_DEVICE_REMOVED; IoCompleteRequest(irp, IO_NO_INCREMENT); - entry = RemoveHeadList(&ext->irp_queue); }
TRACE("Delete device(%p) %s\n", device, debugstr_w(ext->device_name)); @@ -189,7 +201,6 @@ static NTSTATUS copy_packet_into_buffer(HID_XFER_PACKET *packet, BYTE* buffer, U
static void HID_Device_processQueue(DEVICE_OBJECT *device) { - LIST_ENTRY *entry; IRP *irp; BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; UINT buffer_size = RingBuffer_GetBufferSize(ext->ring_buffer); @@ -197,11 +208,9 @@ static void HID_Device_processQueue(DEVICE_OBJECT *device)
packet = HeapAlloc(GetProcessHeap(), 0, buffer_size);
- entry = RemoveHeadList(&ext->irp_queue); - while(entry != &ext->irp_queue) + while((irp = pop_irp_from_queue(ext))) { int ptr; - irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.s.ListEntry); ptr = PtrToUlong( irp->Tail.Overlay.OriginalFileObject->FsContext );
RingBuffer_Read(ext->ring_buffer, ptr, packet, &buffer_size); @@ -222,7 +231,6 @@ static void HID_Device_processQueue(DEVICE_OBJECT *device) irp->IoStatus.u.Status = STATUS_UNSUCCESSFUL; } IoCompleteRequest( irp, IO_NO_INCREMENT ); - entry = RemoveHeadList(&ext->irp_queue); } HeapFree(GetProcessHeap(), 0, packet); } @@ -656,9 +664,15 @@ NTSTATUS WINAPI HID_Device_read(DEVICE_OBJECT *device, IRP *irp) BASE_DEVICE_EXTENSION *extension = device->DeviceExtension; if (extension->poll_interval) { + KIRQL old_irql; TRACE_(hid_report)("Queue irp\n"); + + KeAcquireSpinLock(&ext->irp_queue_lock, &old_irql); + InsertTailList(&ext->irp_queue, &irp->Tail.Overlay.s.ListEntry); rc = STATUS_PENDING; + + KeReleaseSpinLock(&ext->irp_queue_lock, old_irql); } else { diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h index 769b715..ff2e7ef 100644 --- a/dlls/hidclass.sys/hid.h +++ b/dlls/hidclass.sys/hid.h @@ -54,6 +54,7 @@ typedef struct _BASE_DEVICE_EXTENSION { HANDLE halt_event; HANDLE thread;
+ KSPIN_LOCK irp_queue_lock; LIST_ENTRY irp_queue;
/* Minidriver Specific stuff will end up here */ diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index 08aae15..a283d63 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -114,6 +114,7 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
ext = device->DeviceExtension; InitializeListHead(&ext->irp_queue); + KeInitializeSpinLock(&ext->irp_queue_lock);
TRACE("Created device %p\n",device); status = minidriver->AddDevice(minidriver->minidriver.DriverObject, device);