- Allocate work item for each filter / pin being opened

- Use ExInterlockedInsertTailList to insert a new audio device to prevent race conditions when more than one audio device is present
- Free work item in their target worker routine

svn path=/trunk/; revision=40646
This commit is contained in:
Johannes Anderwald 2009-04-22 10:57:28 +00:00
parent 7a75a5802f
commit 67f6e0572a
4 changed files with 118 additions and 69 deletions

View file

@ -236,6 +236,8 @@ CreatePinWorkerRoutine(
{
SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0);
ExFreePool(WorkerContext->DispatchContext);
IoFreeWorkItem(WorkerContext->WorkItem);
ExFreePool(WorkerContext);
return;
}
@ -252,6 +254,8 @@ CreatePinWorkerRoutine(
SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0);
ExFreePool(WorkerContext->DispatchContext);
ExFreePool(MixerPinConnect);
IoFreeWorkItem(WorkerContext->WorkItem);
ExFreePool(WorkerContext);
return;
}
@ -391,9 +395,10 @@ CreatePinWorkerRoutine(
*((PHANDLE)WorkerContext->Irp->UserBuffer) = VirtualPinHandle;
SetIrpIoStatus(WorkerContext->Irp, STATUS_SUCCESS, sizeof(HANDLE));
IoFreeWorkItem(WorkerContext->WorkItem);
ExFreePool(WorkerContext);
return;
cleanup:
if (RealFileObject)
ObDereferenceObject(RealFileObject);
@ -410,7 +415,8 @@ cleanup:
ExFreePool(WorkerContext->DispatchContext);
SetIrpIoStatus(WorkerContext->Irp, Status, 0);
IoFreeWorkItem(WorkerContext->WorkItem);
ExFreePool(WorkerContext);
}
NTSTATUS
@ -722,8 +728,7 @@ HandleSysAudioFilterPinCreation(
KSPIN_CINSTANCES PinInstances;
PPIN_WORKER_CONTEXT WorkerContext;
PDISPATCH_CONTEXT DispatchContext;
PIO_WORKITEM WorkItem;
IoStack = IoGetCurrentIrpStackLocation(Irp);
@ -806,10 +811,7 @@ HandleSysAudioFilterPinCreation(
}
}
ASSERT(DeviceExtension->WorkItem);
ASSERT(DeviceExtension->WorkerContext);
/* create worker context */
/* create dispatch pin context */
DispatchContext = ExAllocatePool(NonPagedPool, sizeof(DISPATCH_CONTEXT));
if (!DispatchContext)
{
@ -817,11 +819,24 @@ HandleSysAudioFilterPinCreation(
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
}
// FIXME
// mutal exclusion
/* allocate worker context */
WorkerContext = ExAllocatePool(NonPagedPool, sizeof(PIN_WORKER_CONTEXT));
if (!WorkerContext)
{
/* no memory */
ExFreePool(DispatchContext);
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
}
/* get worker context */
WorkerContext = (PPIN_WORKER_CONTEXT)DeviceExtension->WorkerContext;
/* allocate work item */
WorkItem = IoAllocateWorkItem(DeviceObject);
if (!WorkerContext)
{
/* no memory */
ExFreePool(DispatchContext);
ExFreePool(WorkerContext);
return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
}
/* prepare context */
RtlZeroMemory(WorkerContext, sizeof(PIN_WORKER_CONTEXT));
@ -841,13 +856,14 @@ HandleSysAudioFilterPinCreation(
WorkerContext->PinConnect = PinConnect;
WorkerContext->AudioClient = ClientInfo;
WorkerContext->DeviceExtension = DeviceExtension;
WorkerContext->WorkItem = WorkItem;
DPRINT("Queing Irp %p\n", Irp);
/* queue the work item */
IoMarkIrpPending(Irp);
Irp->IoStatus.Status = STATUS_PENDING;
Irp->IoStatus.Information = 0;
IoQueueWorkItem(DeviceExtension->WorkItem, CreatePinWorkerRoutine, DelayedWorkQueue, (PVOID)WorkerContext);
IoQueueWorkItem(WorkItem, CreatePinWorkerRoutine, DelayedWorkQueue, (PVOID)WorkerContext);
/* mark irp as pending */
return STATUS_PENDING;

View file

@ -28,7 +28,10 @@ FilterPinWorkerRoutine(
NTSTATUS Status;
ULONG BytesReturned;
PSYSAUDIODEVEXT DeviceExtension;
PKSAUDIO_DEVICE_ENTRY DeviceEntry = (PKSAUDIO_DEVICE_ENTRY)Context;
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
PFILTER_WORKER_CONTEXT Ctx = (PFILTER_WORKER_CONTEXT)Context;
DeviceEntry = Ctx->DeviceEntry;
DPRINT("Querying filter...\n");
@ -42,21 +45,13 @@ FilterPinWorkerRoutine(
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to query number of pins Status %x\n", Status);
ObDereferenceObject(DeviceEntry->FileObject);
ZwClose(DeviceEntry->Handle);
ExFreePool(DeviceEntry->DeviceName.Buffer);
ExFreePool(DeviceEntry);
return;
goto cleanup;
}
if (!Count)
{
DPRINT1("Filter has no pins!\n");
ObDereferenceObject(DeviceEntry->FileObject);
ZwClose(DeviceEntry->Handle);
ExFreePool(DeviceEntry->DeviceName.Buffer);
ExFreePool(DeviceEntry);
return;
goto cleanup;
}
/* allocate pin array */
@ -65,11 +60,7 @@ FilterPinWorkerRoutine(
{
/* no memory */
DPRINT1("Failed to allocate memory Block %x\n", Count * sizeof(PIN_INFO));
ObDereferenceObject(DeviceEntry->FileObject);
ZwClose(DeviceEntry->Handle);
ExFreePool(DeviceEntry->DeviceName.Buffer);
ExFreePool(DeviceEntry);
return;
goto cleanup;
}
/* clear array */
RtlZeroMemory(DeviceEntry->Pins, sizeof(PIN_INFO) * Count);
@ -114,12 +105,27 @@ FilterPinWorkerRoutine(
}
DPRINT("Num Pins %u Num WaveIn Pins %u Name WaveOut Pins %u\n", DeviceEntry->NumberOfPins, DeviceEntry->NumWaveInPin, DeviceEntry->NumWaveOutPin);
/* fetch device extension */
DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
/* insert new audio device */
ExInterlockedInsertTailList(&DeviceExtension->KsAudioDeviceList, &DeviceEntry->Entry, &DeviceExtension->Lock);
/* increment audio device count */
InterlockedIncrement((PLONG)&DeviceExtension->NumberOfKsAudioDevices);
InsertTailList(&DeviceExtension->KsAudioDeviceList, &DeviceEntry->Entry);
DeviceExtension->NumberOfKsAudioDevices++;
/* free work item */
IoFreeWorkItem(Ctx->WorkItem);
/* free work item context */
ExFreePool(Ctx);
return;
cleanup:
ObDereferenceObject(DeviceEntry->FileObject);
ZwClose(DeviceEntry->Handle);
ExFreePool(DeviceEntry->DeviceName.Buffer);
ExFreePool(DeviceEntry);
IoFreeWorkItem(Ctx->WorkItem);
ExFreePool(Ctx);
}
NTSTATUS
@ -177,7 +183,9 @@ DeviceInterfaceChangeCallback(
DEVICE_INTERFACE_CHANGE_NOTIFICATION * Event;
NTSTATUS Status = STATUS_SUCCESS;
PSYSAUDIODEVEXT DeviceExtension;
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
PKSAUDIO_DEVICE_ENTRY DeviceEntry = NULL;
PIO_WORKITEM WorkItem = NULL;
PFILTER_WORKER_CONTEXT Ctx = NULL;
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context;
DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
@ -191,48 +199,67 @@ DeviceInterfaceChangeCallback(
DeviceEntry = ExAllocatePool(NonPagedPool, sizeof(KSAUDIO_DEVICE_ENTRY));
if (!DeviceEntry)
{
/* no memory */
return STATUS_INSUFFICIENT_RESOURCES;
}
/* initialize audio device entry */
RtlZeroMemory(DeviceEntry, sizeof(KSAUDIO_DEVICE_ENTRY));
/* allocate filter ctx */
Ctx = ExAllocatePool(NonPagedPool, sizeof(FILTER_WORKER_CONTEXT));
if (!Ctx)
{
/* no memory */
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
/* allocate work item */
WorkItem = IoAllocateWorkItem(DeviceObject);
if (!WorkItem)
{
/* no memory */
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
/* set device name */
DeviceEntry->DeviceName.Length = 0;
DeviceEntry->DeviceName.MaximumLength = Event->SymbolicLinkName->Length + 5 * sizeof(WCHAR);
DeviceEntry->DeviceName.Buffer = ExAllocatePool(NonPagedPool, DeviceEntry->DeviceName.MaximumLength);
if (!DeviceEntry->DeviceName.Buffer)
{
ExFreePool(DeviceEntry);
return STATUS_INSUFFICIENT_RESOURCES;
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
if (!NT_SUCCESS(RtlAppendUnicodeToString(&DeviceEntry->DeviceName, L"\\??\\")))
{
ExFreePool(DeviceEntry->DeviceName.Buffer);
ExFreePool(DeviceEntry);
return STATUS_INSUFFICIENT_RESOURCES;
DPRINT1("RtlAppendUnicodeToString failed with %x\n", Status);
goto cleanup;
}
if (!NT_SUCCESS(RtlAppendUnicodeStringToString(&DeviceEntry->DeviceName, Event->SymbolicLinkName)))
{
ExFreePool(DeviceEntry->DeviceName.Buffer);
ExFreePool(DeviceEntry);
return STATUS_INSUFFICIENT_RESOURCES;
DPRINT1("RtlAppendUnicodeStringToString failed with %x\n", Status);
goto cleanup;
}
Status = OpenDevice(&DeviceEntry->DeviceName, &DeviceEntry->Handle, &DeviceEntry->FileObject);
if (!NT_SUCCESS(Status))
{
DPRINT("ZwCreateFile failed with %x\n", Status);
ExFreePool(DeviceEntry->DeviceName.Buffer);
ExFreePool(DeviceEntry);
return Status;
goto cleanup;
}
DPRINT("Successfully opened audio device %u handle %p file object %p device object %p\n", DeviceExtension->NumberOfKsAudioDevices, DeviceEntry->Handle, DeviceEntry->FileObject, DeviceEntry->FileObject->DeviceObject);
//FIXME
// mutal exclusion
IoQueueWorkItem(DeviceExtension->WorkItem, FilterPinWorkerRoutine, DelayedWorkQueue, (PVOID)DeviceEntry);
Ctx->DeviceEntry = DeviceEntry;
Ctx->WorkItem = WorkItem;
IoQueueWorkItem(WorkItem, FilterPinWorkerRoutine, DelayedWorkQueue, (PVOID)Ctx);
return Status;
}
else
@ -241,6 +268,23 @@ DeviceInterfaceChangeCallback(
UNIMPLEMENTED
return STATUS_SUCCESS;
}
cleanup:
if (Ctx)
ExFreePool(Ctx);
if (WorkItem)
IoFreeWorkItem(WorkItem);
if (DeviceEntry)
{
if (DeviceEntry->DeviceName.Buffer)
ExFreePool(DeviceEntry->DeviceName.Buffer);
ExFreePool(DeviceEntry);
}
return Status;
}
NTSTATUS

View file

@ -118,7 +118,7 @@ SysAudio_InstallDevice(
RtlZeroMemory(DeviceExtension, sizeof(SYSAUDIODEVEXT));
/* Initialize the mutex */
KeInitializeMutex(&DeviceExtension->Mutex, 0);
KeInitializeSpinLock(&DeviceExtension->Lock);
/* Initialize the ks audio device list */
InitializeListHead(&DeviceExtension->KsAudioDeviceList);
@ -131,22 +131,6 @@ SysAudio_InstallDevice(
goto cleanup;
}
/* allocate work item */
DeviceExtension->WorkItem = IoAllocateWorkItem(DeviceObject);
if (!DeviceExtension->WorkItem)
{
DPRINT1("Failed to allocate work item\n");
goto cleanup;
}
/* allocate work item context */
DeviceExtension->WorkerContext = ExAllocatePool(NonPagedPool, sizeof(PIN_WORKER_CONTEXT));
if (!DeviceExtension->WorkerContext)
{
DPRINT1("Failed to allocate work item context\n");
goto cleanup;
}
/* Register device notification hooks */
Status = SysAudioRegisterNotifications(DriverObject,
DeviceObject);

View file

@ -70,14 +70,11 @@ typedef struct
LIST_ENTRY KsAudioDeviceList; // audio device list
PVOID KsAudioNotificationEntry; // ks audio notification hook
PVOID EchoCancelNotificationEntry; // ks echo cancel notification hook
KMUTEX Mutex; // audio device list mutex
KSPIN_LOCK Lock; // audio device list mutex
PFILE_OBJECT KMixerFileObject; // mixer file object
HANDLE KMixerHandle; // mixer file handle
PIO_WORKITEM WorkItem; // work item for pin creation
PVOID WorkerContext; // work item context
}SYSAUDIODEVEXT, *PSYSAUDIODEVEXT;
// struct DISPATCH_CONTEXT
@ -113,8 +110,16 @@ typedef struct
PSYSAUDIO_CLIENT AudioClient;
PSYSAUDIODEVEXT DeviceExtension;
PKSDATAFORMAT_WAVEFORMATEX MixerFormat;
PIO_WORKITEM WorkItem;
}PIN_WORKER_CONTEXT, *PPIN_WORKER_CONTEXT;
typedef struct
{
PIO_WORKITEM WorkItem;
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
}FILTER_WORKER_CONTEXT, *PFILTER_WORKER_CONTEXT;
NTSTATUS
SysAudioAllocateDeviceHeader(
IN SYSAUDIODEVEXT *DeviceExtension);