Jacek Caban : hidclass.sys: Make read IRP queue thread safe.

Alexandre Julliard julliard at winehq.org
Thu May 9 13:32:43 CDT 2019


Module: wine
Branch: master
Commit: 85082e8bd3c9bcb0b45fc56b55cc7c88c653d028
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=85082e8bd3c9bcb0b45fc56b55cc7c88c653d028

Author: Jacek Caban <jacek at 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 at codeweavers.com>
Signed-off-by: Aric Stewart <aric at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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);




More information about the wine-cvs mailing list