Module: wine Branch: master Commit: 3e79b8d6ebdb3372749aed67e5ee19eb5fd40586 URL: https://gitlab.winehq.org/wine/wine/-/commit/3e79b8d6ebdb3372749aed67e5ee19e...
Author: Rémi Bernon rbernon@codeweavers.com Date: Sat Jan 20 22:01:11 2024 +0100
dinput/tests: Enforce ordering of concurrent read IRPs.
---
dlls/dinput/tests/driver_bus.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-)
diff --git a/dlls/dinput/tests/driver_bus.c b/dlls/dinput/tests/driver_bus.c index c0d181c58a5..e0943c35294 100644 --- a/dlls/dinput/tests/driver_bus.c +++ b/dlls/dinput/tests/driver_bus.c @@ -348,13 +348,13 @@ static void irp_queue_push( struct irp_queue *queue, IRP *irp ) KeReleaseSpinLock( &queue->lock, irql ); }
-static void irp_queue_clear( struct irp_queue *queue ) +static void irp_queue_complete( struct irp_queue *queue, BOOL delete ) { IRP *irp;
while ((irp = irp_queue_pop( queue ))) { - irp->IoStatus.Status = STATUS_DELETE_PENDING; + if (delete) irp->IoStatus.Status = STATUS_DELETE_PENDING; IoCompleteRequest( irp, IO_NO_INCREMENT ); } } @@ -373,6 +373,7 @@ struct input_queue struct hid_expect *end; struct hid_expect *buffer; struct irp_queue pending; + struct irp_queue completed; };
static void input_queue_init( struct input_queue *queue, BOOL is_polled ) @@ -384,6 +385,7 @@ static void input_queue_init( struct input_queue *queue, BOOL is_polled ) queue->pos = queue->buffer; queue->end = queue->buffer; irp_queue_init( &queue->pending ); + irp_queue_init( &queue->completed ); }
static void input_queue_cleanup( struct input_queue *queue ) @@ -416,7 +418,11 @@ static NTSTATUS input_queue_read( struct input_queue *queue, IRP *irp ) KIRQL irql;
KeAcquireSpinLock( &queue->lock, &irql ); - if (input_queue_read_locked( queue, irp )) status = STATUS_SUCCESS; + if (input_queue_read_locked( queue, irp )) + { + irp_queue_push( &queue->completed, irp ); + status = STATUS_SUCCESS; + } else { IoMarkIrpPending( irp ); @@ -430,13 +436,10 @@ static NTSTATUS input_queue_read( struct input_queue *queue, IRP *irp )
static void input_queue_reset( struct input_queue *queue, void *in_buf, ULONG in_size ) { - struct irp_queue completed; ULONG remaining; KIRQL irql; IRP *irp;
- irp_queue_init( &completed ); - KeAcquireSpinLock( &queue->lock, &irql ); remaining = queue->end - queue->pos; queue->pos = queue->buffer; @@ -447,13 +450,13 @@ static void input_queue_reset( struct input_queue *queue, void *in_buf, ULONG in while (!queue->is_polled && queue->pos < queue->end && (irp = irp_queue_pop( &queue->pending ))) { input_queue_read_locked( queue, irp ); - irp_queue_push( &completed, irp ); + irp_queue_push( &queue->completed, irp ); } KeReleaseSpinLock( &queue->lock, irql );
if (!queue->is_polled) ok( !remaining, "unread input\n" );
- while ((irp = irp_queue_pop( &completed ))) IoCompleteRequest( irp, IO_NO_INCREMENT ); + irp_queue_complete( &queue->completed, FALSE ); }
struct device @@ -721,7 +724,8 @@ static NTSTATUS pdo_pnp( DEVICE_OBJECT *device, IRP *irp ) state = (code == IRP_MN_START_DEVICE || code == IRP_MN_CANCEL_REMOVE_DEVICE) ? 0 : PNP_DEVICE_REMOVED; KeAcquireSpinLock( &impl->base.lock, &irql ); impl->base.state = state; - irp_queue_clear( &impl->input_queue.pending ); + irp_queue_complete( &impl->input_queue.pending, TRUE ); + irp_queue_complete( &impl->input_queue.completed, TRUE ); KeReleaseSpinLock( &impl->base.lock, irql ); if (code != IRP_MN_REMOVE_DEVICE) status = STATUS_SUCCESS; else @@ -1087,7 +1091,10 @@ static NTSTATUS pdo_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) ok( !in_size, "got input size %lu\n", in_size ); ok( out_size == expected_size, "got output size %lu\n", out_size ); status = input_queue_read( &impl->input_queue, irp ); - break; + irp_queue_complete( &impl->input_queue.completed, FALSE ); + + winetest_pop_context(); + return status; }
case IOCTL_HID_WRITE_REPORT: @@ -1277,7 +1284,8 @@ static NTSTATUS pdo_handle_ioctl( struct phys_device *impl, IRP *irp, ULONG code case IOCTL_WINETEST_REMOVE_DEVICE: KeAcquireSpinLock( &impl->base.lock, &irql ); impl->base.state = PNP_DEVICE_REMOVED; - irp_queue_clear( &impl->input_queue.pending ); + irp_queue_complete( &impl->input_queue.pending, TRUE ); + irp_queue_complete( &impl->input_queue.completed, TRUE ); KeReleaseSpinLock( &impl->base.lock, irql ); impl->pending_remove = irp; IoMarkIrpPending( irp );