[ros-diffs] [janderwald] 47197: [PORTCLS] - Don't request initializing delayed service request as this is the task of the miniport driver - Reimplement the service group object: - Use the initialized timer object when RequestService is called - Fix possible race conditions when adding / removing a service sink by protecting it with a lock - Acquire the service group list lock when executing the shared dpc routine

janderwald at svn.reactos.org janderwald at svn.reactos.org
Fri May 14 17:47:01 CEST 2010


Author: janderwald
Date: Fri May 14 17:47:00 2010
New Revision: 47197

URL: http://svn.reactos.org/svn/reactos?rev=47197&view=rev
Log:
[PORTCLS]
- Don't request initializing delayed service request as this is the task of the miniport driver
- Reimplement the service group object:
- Use the initialized timer object when RequestService is called
- Fix possible race conditions when adding / removing a service sink by protecting it with a lock
- Acquire the service group list lock when executing the shared dpc routine

Modified:
    trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp
    trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp
    trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp
    trunk/reactos/drivers/wdm/audio/backpln/portcls/service_group.cpp

Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp?rev=47197&r1=47196&r2=47197&view=diff
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp [iso-8859-1] Fri May 14 17:47:00 2010
@@ -602,7 +602,6 @@
             DPRINT("Failed to add pin to service group\n");
             return Status;
         }
-        m_ServiceGroup->SupportDelayedService();
     }
 
     Status = m_IrpQueue->Init(ConnectDetails, 0, 0, NULL);

Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp?rev=47197&r1=47196&r2=47197&view=diff
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp [iso-8859-1] Fri May 14 17:47:00 2010
@@ -1213,7 +1213,6 @@
         return Status;
     }
 
-    m_ServiceGroup->SupportDelayedService();
     m_Stream->SetState(KSSTATE_STOP);
     m_State = KSSTATE_STOP;
     m_CommonBufferOffset = 0;
@@ -1224,6 +1223,8 @@
     m_Delay = Int32x32To64(10, -10000);
 
     Status = m_Stream->SetNotificationFreq(10, &m_FrameSize);
+    PC_ASSERT(NT_SUCCESS(Status));
+    PC_ASSERT(m_FrameSize);
 
     SilenceBuffer = AllocateItem(NonPagedPool, m_FrameSize, TAG_PORTCLASS);
     if (!SilenceBuffer)

Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp?rev=47197&r1=47196&r2=47197&view=diff
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp [iso-8859-1] Fri May 14 17:47:00 2010
@@ -815,7 +815,6 @@
             DPRINT("Failed to add pin to service group\n");
             return Status;
         }
-        m_ServiceGroup->SupportDelayedService();
     }
 
     // delay of 10 milisec

Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/service_group.cpp
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/portcls/service_group.cpp?rev=47197&r1=47196&r2=47197&view=diff
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/service_group.cpp [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/service_group.cpp [iso-8859-1] Fri May 14 17:47:00 2010
@@ -54,12 +54,10 @@
 
     LIST_ENTRY m_ServiceSinkHead;
 
-    BOOL m_Initialized;
-    BOOL m_TimerActive;
+    BOOL m_TimerInitialized;
     KTIMER m_Timer;
     KDPC m_Dpc;
-    KEVENT m_Event;
-    LONG m_ThreadActive;
+    KSPIN_LOCK m_Lock;
 
     friend VOID NTAPI IServiceGroupDpc(IN struct _KDPC  *Dpc, IN PVOID  DeferredContext, IN PVOID  SystemArgument1, IN PVOID  SystemArgument2);
 
@@ -105,9 +103,16 @@
 
 CServiceGroup::CServiceGroup(IUnknown * OuterUnknown)
 {
+    // initialize dpc
     KeInitializeDpc(&m_Dpc, IServiceGroupDpc, (PVOID)this);
+
+    // set highest importance
     KeSetImportanceDpc(&m_Dpc, HighImportance);
-    KeInitializeEvent(&m_Event, NotificationEvent, FALSE);
+
+    // initialize service group list lock
+    KeInitializeSpinLock(&m_Lock);
+
+    // initialize service group list
     InitializeListHead(&m_ServiceSinkHead);
 }
 
@@ -119,15 +124,34 @@
 
     DPRINT("CServiceGroup::RequestService() Dpc at Level %u\n", KeGetCurrentIrql());
 
-    if (KeGetCurrentIrql() > DISPATCH_LEVEL)
-    {
-        KeInsertQueueDpc(&m_Dpc, NULL, NULL);
-        return;
-    }
-
-    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
-    KeInsertQueueDpc(&m_Dpc, NULL, NULL);
-    KeLowerIrql(OldIrql);
+    if (m_TimerInitialized)
+    {
+        LARGE_INTEGER DueTime;
+
+        // no due time
+        DueTime.QuadPart = 0LL;
+
+        // delayed service requested
+        KeSetTimer(&m_Timer, DueTime, &m_Dpc);
+    }
+    else
+    {
+        // check curent irql
+        if (KeGetCurrentIrql() > DISPATCH_LEVEL)
+        {
+            //insert dpc to queue
+            KeInsertQueueDpc(&m_Dpc, NULL, NULL);
+        }
+        else
+        {
+            // raise irql to dispatch level to make dpc fire immediately
+            KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+            // insert dpc to queue
+            KeInsertQueueDpc(&m_Dpc, NULL, NULL);
+            // lower irql to old level
+            KeLowerIrql(OldIrql);
+        }
+    }
 }
 
 //---------------------------------------------------------------
@@ -140,17 +164,32 @@
     IN PSERVICESINK pServiceSink)
 {
     PGROUP_ENTRY Entry;
-
+    KIRQL OldLevel;
+
+    // sanity check
     PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
 
+    // allocate service sink entry
     Entry = (PGROUP_ENTRY)AllocateItem(NonPagedPool, sizeof(GROUP_ENTRY), TAG_PORTCLASS);
     if (!Entry)
+    {
+        // out of memory
         return STATUS_INSUFFICIENT_RESOURCES;
-
+    }
+
+    // initialize service sink entry
     Entry->pServiceSink = pServiceSink;
+    // increment reference count
     pServiceSink->AddRef();
 
+    // acquire service group list lock
+    KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+    // insert into service sink list
     InsertTailList(&m_ServiceSinkHead, &Entry->Entry);
+
+    // release service group list lock
+    KeReleaseSpinLock(&m_Lock, OldLevel);
 
     return STATUS_SUCCESS;
 }
@@ -162,22 +201,44 @@
 {
     PLIST_ENTRY CurEntry;
     PGROUP_ENTRY Entry;
-
+    KIRQL OldLevel;
+
+    // sanity check
     PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
 
+    // acquire service group list lock
+    KeAcquireSpinLock(&m_Lock, &OldLevel);
+
+    // grab first entry
     CurEntry = m_ServiceSinkHead.Flink;
+
+    // loop list until the passed entry is found
     while (CurEntry != &m_ServiceSinkHead)
     {
+        // grab entry
         Entry = CONTAINING_RECORD(CurEntry, GROUP_ENTRY, Entry);
+
+        // check if it matches the passed entry
         if (Entry->pServiceSink == pServiceSink)
         {
+            // remove entry from list
             RemoveEntryList(&Entry->Entry);
+
+            // release service sink reference
             pServiceSink->Release();
+
+            // free service sink entry
             FreeItem(Entry, TAG_PORTCLASS);
-            return;
+
+            // leave loop
+            break;
         }
+        // move to next entry
         CurEntry = CurEntry->Flink;
     }
+
+    // release service group list lock
+    KeReleaseSpinLock(&m_Lock, OldLevel);
 
 }
 
@@ -194,73 +255,40 @@
     PGROUP_ENTRY Entry;
     CServiceGroup * This = (CServiceGroup*)DeferredContext;
 
+    // acquire service group list lock
+    KeAcquireSpinLockAtDpcLevel(&This->m_Lock);
+
+    // grab first entry
     CurEntry = This->m_ServiceSinkHead.Flink;
+
+    // loop the list and call the attached service sink/group
     while (CurEntry != &This->m_ServiceSinkHead)
     {
+        //grab current entry
         Entry = (PGROUP_ENTRY)CONTAINING_RECORD(CurEntry, GROUP_ENTRY, Entry);
+
+        // call service sink/group
         Entry->pServiceSink->RequestService();
+
+        // move to next entry
         CurEntry = CurEntry->Flink;
     }
-}
-
-
-#if 0
-VOID
-NTAPI
-ServiceGroupThread(IN PVOID StartContext)
-{
-    NTSTATUS Status;
-    KWAIT_BLOCK WaitBlockArray[2];
-    PVOID WaitObjects[2];
-    CServiceGroup * This = (CServiceGroup*)StartContext;
-
-    // Set thread state
-    InterlockedIncrement(&This->m_ThreadActive);
-
-    // Setup the wait objects
-    WaitObjects[0] = &m_Timer;
-    WaitObjects[1] = &m_Event;
-
-    do
-    {
-        // Wait on our objects
-        Status = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, Executive, KernelMode, FALSE, NULL, WaitBlockArray);
-
-        switch(Status)
-        {
-            case STATUS_WAIT_0:
-                IServiceGroupDpc(&This->m_Dpc, (PVOID)This, NULL, NULL);
-                break;
-            case STATUS_WAIT_1:
-                PsTerminateSystemThread(STATUS_SUCCESS);
-                return;
-        }
-    }while(TRUE);
-}
-
-#endif
+
+    // release service group list lock
+    KeReleaseSpinLockFromDpcLevel(&This->m_Lock);
+}
+
 VOID
 NTAPI
 CServiceGroup::SupportDelayedService()
 {
-    //NTSTATUS Status;
-    //HANDLE ThreadHandle;
-
     PC_ASSERT_IRQL(DISPATCH_LEVEL);
 
-    if (m_Initialized)
-        return;
-
-    KeInitializeTimerEx(&m_Timer, NotificationTimer);
-
-#if 0
-    Status = PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, NULL, 0, NULL, ServiceGroupThread, (PVOID)This);
-    if (NT_SUCCESS(Status))
-    {
-        ZwClose(ThreadHandle);
-        m_Initialized = TRUE;
-    }
-#endif
+    // initialize the timer
+    KeInitializeTimer(&m_Timer);
+
+    // use the timer to perform service requests
+    m_TimerInitialized = TRUE;
 }
 
 VOID
@@ -270,17 +298,14 @@
 {
     LARGE_INTEGER DueTime;
 
+    // sanity check
     PC_ASSERT_IRQL(DISPATCH_LEVEL);
+    PC_ASSERT(m_TimerInitialized);
 
     DueTime.QuadPart = ullDelay;
 
-    if (m_Initialized)
-    {
-        if (KeGetCurrentIrql() <= DISPATCH_LEVEL)
-            KeSetTimer(&m_Timer, DueTime, &m_Dpc);
-        else
-            KeInsertQueueDpc(&m_Dpc, NULL, NULL);
-    }
+    // set the timer
+    KeSetTimer(&m_Timer, DueTime, &m_Dpc);
 }
 
 VOID
@@ -288,11 +313,10 @@
 CServiceGroup::CancelDelayedService()
 {
     PC_ASSERT_IRQL(DISPATCH_LEVEL);
-
-    if (m_Initialized)
-    {
-        KeCancelTimer(&m_Timer);
-    }
+    PC_ASSERT(m_TimerInitialized);
+
+    // cancel the timer
+    KeCancelTimer(&m_Timer);
 }
 
 NTSTATUS
@@ -303,19 +327,31 @@
 {
     CServiceGroup * This;
     NTSTATUS Status;
+
     DPRINT("PcNewServiceGroup entered\n");
 
+    //FIXME support aggregation
+    PC_ASSERT(OuterUnknown == NULL);
+
+    // allocate a service group object
     This = new(NonPagedPool, TAG_PORTCLASS)CServiceGroup(OuterUnknown);
+
     if (!This)
+    {
+        // out of memory
         return STATUS_INSUFFICIENT_RESOURCES;
-
+    }
+
+    // request IServiceSink interface
     Status = This->QueryInterface(IID_IServiceSink, (PVOID*)OutServiceGroup);
 
     if (!NT_SUCCESS(Status))
     {
+        // failed to acquire service sink interface
         delete This;
         return Status;
     }
 
+    // done
     return Status;
 }




More information about the Ros-diffs mailing list