mirror of
git://source.winehq.org/git/wine.git
synced 2024-07-22 20:44:10 +00:00
ntoskrnl: Enumerate child devices on a separate thread.
This commit is contained in:
parent
92456eb747
commit
9fbdf2b434
|
@ -22,6 +22,7 @@
|
||||||
#define __WINE_NTOSKRNL_PRIVATE_H
|
#define __WINE_NTOSKRNL_PRIVATE_H
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include "ntstatus.h"
|
#include "ntstatus.h"
|
||||||
#define WIN32_NO_STATUS
|
#define WIN32_NO_STATUS
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
|
|
|
@ -38,6 +38,12 @@ DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
|
WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
|
||||||
|
|
||||||
|
DECLARE_CRITICAL_SECTION(invalidated_devices_cs);
|
||||||
|
static CONDITION_VARIABLE invalidated_devices_cv = CONDITION_VARIABLE_INIT;
|
||||||
|
|
||||||
|
static DEVICE_OBJECT **invalidated_devices;
|
||||||
|
static size_t invalidated_devices_count;
|
||||||
|
|
||||||
static inline const char *debugstr_propkey( const DEVPROPKEY *id )
|
static inline const char *debugstr_propkey( const DEVPROPKEY *id )
|
||||||
{
|
{
|
||||||
if (!id) return "(null)";
|
if (!id) return "(null)";
|
||||||
|
@ -468,8 +474,14 @@ void WINAPI IoInvalidateDeviceRelations( DEVICE_OBJECT *device_object, DEVICE_RE
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case BusRelations:
|
case BusRelations:
|
||||||
handle_bus_relations( device_object );
|
EnterCriticalSection( &invalidated_devices_cs );
|
||||||
|
invalidated_devices = realloc( invalidated_devices,
|
||||||
|
(invalidated_devices_count + 1) * sizeof(*invalidated_devices) );
|
||||||
|
invalidated_devices[invalidated_devices_count++] = device_object;
|
||||||
|
LeaveCriticalSection( &invalidated_devices_cs );
|
||||||
|
WakeConditionVariable( &invalidated_devices_cv );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
FIXME("Unhandled relation %#x.\n", type);
|
FIXME("Unhandled relation %#x.\n", type);
|
||||||
break;
|
break;
|
||||||
|
@ -1086,6 +1098,30 @@ static NTSTATUS WINAPI pnp_manager_driver_entry( DRIVER_OBJECT *driver, UNICODE_
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DWORD CALLBACK device_enum_thread_proc(void *arg)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
DEVICE_OBJECT *device;
|
||||||
|
|
||||||
|
EnterCriticalSection( &invalidated_devices_cs );
|
||||||
|
|
||||||
|
while (!invalidated_devices_count)
|
||||||
|
SleepConditionVariableCS( &invalidated_devices_cv, &invalidated_devices_cs, INFINITE );
|
||||||
|
|
||||||
|
device = invalidated_devices[--invalidated_devices_count];
|
||||||
|
|
||||||
|
/* Don't hold the CS while enumerating the device. Tests show that
|
||||||
|
* calling IoInvalidateDeviceRelations() from another thread shouldn't
|
||||||
|
* block, even if this thread is blocked in an IRP handler. */
|
||||||
|
LeaveCriticalSection( &invalidated_devices_cs );
|
||||||
|
|
||||||
|
handle_bus_relations( device );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void pnp_manager_start(void)
|
void pnp_manager_start(void)
|
||||||
{
|
{
|
||||||
static const WCHAR driver_nameW[] = {'\\','D','r','i','v','e','r','\\','P','n','p','M','a','n','a','g','e','r',0};
|
static const WCHAR driver_nameW[] = {'\\','D','r','i','v','e','r','\\','P','n','p','M','a','n','a','g','e','r',0};
|
||||||
|
@ -1109,6 +1145,8 @@ void pnp_manager_start(void)
|
||||||
RpcStringFreeW( &binding_str );
|
RpcStringFreeW( &binding_str );
|
||||||
if (err)
|
if (err)
|
||||||
ERR("RpcBindingFromStringBinding() failed, error %#lx\n", err);
|
ERR("RpcBindingFromStringBinding() failed, error %#lx\n", err);
|
||||||
|
|
||||||
|
CreateThread( NULL, 0, device_enum_thread_proc, NULL, 0, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
void pnp_manager_stop_driver( struct wine_driver *driver )
|
void pnp_manager_stop_driver( struct wine_driver *driver )
|
||||||
|
|
|
@ -272,11 +272,11 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp)
|
||||||
device->power_state = PowerDeviceD0;
|
device->power_state = PowerDeviceD0;
|
||||||
|
|
||||||
status = ZwWaitForSingleObject(device->plug_event, TRUE, &wait_time);
|
status = ZwWaitForSingleObject(device->plug_event, TRUE, &wait_time);
|
||||||
todo_wine ok(!status, "Failed to wait for child plug event, status %#lx.\n", status);
|
ok(!status, "Failed to wait for child plug event, status %#lx.\n", status);
|
||||||
status = ZwSetEvent(device->plug_event2, NULL);
|
status = ZwSetEvent(device->plug_event2, NULL);
|
||||||
ok(!status, "Failed to set event, status %#lx.\n", status);
|
ok(!status, "Failed to set event, status %#lx.\n", status);
|
||||||
status = ZwWaitForSingleObject(device->plug_event, TRUE, &wait_time);
|
status = ZwWaitForSingleObject(device->plug_event, TRUE, &wait_time);
|
||||||
todo_wine ok(!status, "Failed to wait for child plug event, status %#lx.\n", status);
|
ok(!status, "Failed to wait for child plug event, status %#lx.\n", status);
|
||||||
|
|
||||||
ret = STATUS_SUCCESS;
|
ret = STATUS_SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
@ -692,15 +692,15 @@ static NTSTATUS fdo_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG code)
|
||||||
* for the other. */
|
* for the other. */
|
||||||
|
|
||||||
status = ZwSetEvent(plug_event, NULL);
|
status = ZwSetEvent(plug_event, NULL);
|
||||||
todo_wine ok(!status, "Failed to set event, status %#lx.\n", status);
|
ok(!status, "Failed to set event, status %#lx.\n", status);
|
||||||
status = ZwWaitForSingleObject(plug_event2, TRUE, &wait_time);
|
status = ZwWaitForSingleObject(plug_event2, TRUE, &wait_time);
|
||||||
todo_wine ok(!status, "Failed to wait for child plug event, status %#lx.\n", status);
|
ok(!status, "Failed to wait for child plug event, status %#lx.\n", status);
|
||||||
ok(surprise_removal_count == 1, "Got %u surprise removal events.\n", surprise_removal_count);
|
ok(surprise_removal_count == 1, "Got %u surprise removal events.\n", surprise_removal_count);
|
||||||
/* We shouldn't get IRP_MN_REMOVE_DEVICE until all user-space
|
/* We shouldn't get IRP_MN_REMOVE_DEVICE until all user-space
|
||||||
* handles to the device are closed (and the user-space thread is
|
* handles to the device are closed (and the user-space thread is
|
||||||
* currently blocked in this ioctl and won't close its handle
|
* currently blocked in this ioctl and won't close its handle
|
||||||
* yet.) */
|
* yet.) */
|
||||||
todo_wine ok(!remove_device_count, "Got %u remove events.\n", remove_device_count);
|
ok(!remove_device_count, "Got %u remove events.\n", remove_device_count);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue