Author: janderwald
Date: Wed Apr 22 14:57:28 2009
New Revision: 40646

URL: http://svn.reactos.org/svn/reactos?rev=40646&view=rev
Log:
- 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

Modified:
    trunk/reactos/drivers/wdm/audio/sysaudio/control.c
    trunk/reactos/drivers/wdm/audio/sysaudio/deviface.c
    trunk/reactos/drivers/wdm/audio/sysaudio/main.c
    trunk/reactos/drivers/wdm/audio/sysaudio/sysaudio.h

Modified: trunk/reactos/drivers/wdm/audio/sysaudio/control.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/sysaudio/control.c?rev=40646&r1=40645&r2=40646&view=diff
==============================================================================
--- trunk/reactos/drivers/wdm/audio/sysaudio/control.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/sysaudio/control.c [iso-8859-1] Wed Apr 22 
14:57:28 2009
@@ -236,6 +236,8 @@
         {
             SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0);
             ExFreePool(WorkerContext->DispatchContext);
+            IoFreeWorkItem(WorkerContext->WorkItem);
+            ExFreePool(WorkerContext);
             return;
         }
 
@@ -252,6 +254,8 @@
             SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0);
             ExFreePool(WorkerContext->DispatchContext);
             ExFreePool(MixerPinConnect);
+            IoFreeWorkItem(WorkerContext->WorkItem);
+            ExFreePool(WorkerContext);
             return;
         }
 
@@ -391,8 +395,9 @@
     *((PHANDLE)WorkerContext->Irp->UserBuffer) = VirtualPinHandle;
 
     SetIrpIoStatus(WorkerContext->Irp, STATUS_SUCCESS, sizeof(HANDLE));
+    IoFreeWorkItem(WorkerContext->WorkItem);
+    ExFreePool(WorkerContext);
     return;
-
 
 cleanup:
     if (RealFileObject)
@@ -410,7 +415,8 @@
 
     ExFreePool(WorkerContext->DispatchContext);
     SetIrpIoStatus(WorkerContext->Irp, Status, 0);
-
+    IoFreeWorkItem(WorkerContext->WorkItem);
+    ExFreePool(WorkerContext);
 }
 
 NTSTATUS
@@ -722,8 +728,7 @@
     KSPIN_CINSTANCES PinInstances;
     PPIN_WORKER_CONTEXT WorkerContext;
     PDISPATCH_CONTEXT DispatchContext;
-
-
+    PIO_WORKITEM WorkItem;
 
     IoStack = IoGetCurrentIrpStackLocation(Irp);
 
@@ -806,10 +811,7 @@
         }
     }
 
-    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 @@
         return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
     }
 
-    // FIXME
-    // mutal exclusion
-
-    /* get worker context */
-    WorkerContext = (PPIN_WORKER_CONTEXT)DeviceExtension->WorkerContext;
+    /* allocate worker context */
+    WorkerContext = ExAllocatePool(NonPagedPool, sizeof(PIN_WORKER_CONTEXT));
+    if (!WorkerContext)
+    {
+        /* no memory */
+        ExFreePool(DispatchContext);
+        return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0);
+    }
+
+    /* 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 @@
     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;

Modified: trunk/reactos/drivers/wdm/audio/sysaudio/deviface.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/sysaudio/deviface.c?rev=40646&r1=40645&r2=40646&view=diff
==============================================================================
--- trunk/reactos/drivers/wdm/audio/sysaudio/deviface.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/sysaudio/deviface.c [iso-8859-1] Wed Apr 22 
14:57:28 2009
@@ -28,7 +28,10 @@
     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 @@
     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 @@
     {
         /* 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 @@
     }
 
     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;
-
-    InsertTailList(&DeviceExtension->KsAudioDeviceList, &DeviceEntry->Entry);
-    DeviceExtension->NumberOfKsAudioDevices++;
-
+    /* insert new audio device */
+    ExInterlockedInsertTailList(&DeviceExtension->KsAudioDeviceList, 
&DeviceEntry->Entry, &DeviceExtension->Lock);
+    /* increment audio device count */
+    InterlockedIncrement((PLONG)&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 @@
     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 @@
         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 @@
         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

Modified: trunk/reactos/drivers/wdm/audio/sysaudio/main.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/sysaudio/main.c?rev=40646&r1=40645&r2=40646&view=diff
==============================================================================
--- trunk/reactos/drivers/wdm/audio/sysaudio/main.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/sysaudio/main.c [iso-8859-1] Wed Apr 22 
14:57:28 2009
@@ -118,7 +118,7 @@
     RtlZeroMemory(DeviceExtension, sizeof(SYSAUDIODEVEXT));
 
     /* Initialize the mutex */
-    KeInitializeMutex(&DeviceExtension->Mutex, 0);
+    KeInitializeSpinLock(&DeviceExtension->Lock);
 
     /* Initialize the ks audio device list */
     InitializeListHead(&DeviceExtension->KsAudioDeviceList);
@@ -128,22 +128,6 @@
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("KsAllocateDeviceHeader failed with %x\n", Status);
-        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;
     }
 

Modified: trunk/reactos/drivers/wdm/audio/sysaudio/sysaudio.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/sysaudio/sysaudio.h?rev=40646&r1=40645&r2=40646&view=diff
==============================================================================
--- trunk/reactos/drivers/wdm/audio/sysaudio/sysaudio.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/sysaudio/sysaudio.h [iso-8859-1] Wed Apr 22 
14:57:28 2009
@@ -70,13 +70,10 @@
     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;
 
@@ -113,7 +110,15 @@
     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(

Reply via email to