https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2e76fb9fe13436a542cc647bd3cd4a016a6690b6

commit 2e76fb9fe13436a542cc647bd3cd4a016a6690b6
Author:     Thomas Faber <[email protected]>
AuthorDate: Thu Oct 28 10:59:20 2021 -0400
Commit:     Thomas Faber <[email protected]>
CommitDate: Sat Nov 20 14:58:51 2021 -0500

    [NTOS:IO] Use a guarded region in IopQueueIrpToThread.
    
    We're protecting against IopCompleteRequest, which is a special
    kernel APC. So this is a little bit faster than raising the IRQL.
---
 ntoskrnl/include/internal/io_x.h | 17 +++++++++++------
 ntoskrnl/include/internal/ke_x.h | 36 ++++++++++++++++++------------------
 2 files changed, 29 insertions(+), 24 deletions(-)

diff --git a/ntoskrnl/include/internal/io_x.h b/ntoskrnl/include/internal/io_x.h
index 7cf42e9dc02..88b19160448 100644
--- a/ntoskrnl/include/internal/io_x.h
+++ b/ntoskrnl/include/internal/io_x.h
@@ -48,22 +48,27 @@ FORCEINLINE
 VOID
 IopQueueIrpToThread(IN PIRP Irp)
 {
-    KIRQL OldIrql;
+    PETHREAD Thread = Irp->Tail.Overlay.Thread;
 
-    /* Raise to APC Level */
-    KeRaiseIrql(APC_LEVEL, &OldIrql);
+    /* Disable special kernel APCs so we can't race with IopCompleteRequest.
+     * IRP's thread must be the current thread */
+    KeEnterGuardedRegionThread(&Thread->Tcb);
 
     /* Insert it into the list */
-    InsertHeadList(&Irp->Tail.Overlay.Thread->IrpList, &Irp->ThreadListEntry);
+    InsertHeadList(&Thread->IrpList, &Irp->ThreadListEntry);
 
-    /* Lower irql */
-    KeLowerIrql(OldIrql);
+    /* Leave the guarded region */
+    KeLeaveGuardedRegionThread(&Thread->Tcb);
 }
 
 FORCEINLINE
 VOID
 IopUnQueueIrpFromThread(IN PIRP Irp)
 {
+    /* Special kernel APCs must be disabled so we can't race with
+     * IopCompleteRequest (or because we are called from there) */
+    ASSERT(KeAreAllApcsDisabled());
+
     /* Remove it from the list and reset it */
     if (IsListEmpty(&Irp->ThreadListEntry))
         return;
diff --git a/ntoskrnl/include/internal/ke_x.h b/ntoskrnl/include/internal/ke_x.h
index 7a00fba8f9c..70fa05e1d12 100644
--- a/ntoskrnl/include/internal/ke_x.h
+++ b/ntoskrnl/include/internal/ke_x.h
@@ -28,12 +28,12 @@ KeGetPreviousMode(VOID)
 {                                                                           \
     /* Sanity checks */                                                     \
     ASSERT(KeGetCurrentIrql() <= APC_LEVEL);                                \
-    ASSERT(_Thread == KeGetCurrentThread());                                \
-    ASSERT((_Thread->SpecialApcDisable <= 0) &&                             \
-           (_Thread->SpecialApcDisable != -32768));                         \
+    ASSERT((_Thread) == KeGetCurrentThread());                              \
+    ASSERT(((_Thread)->SpecialApcDisable <= 0) &&                           \
+           ((_Thread)->SpecialApcDisable != -32768));                       \
                                                                             \
     /* Disable Special APCs */                                              \
-    _Thread->SpecialApcDisable--;                                           \
+    (_Thread)->SpecialApcDisable--;                                         \
 }
 
 #define KeEnterGuardedRegion()                                              \
@@ -49,14 +49,14 @@ KeGetPreviousMode(VOID)
 {                                                                           \
     /* Sanity checks */                                                     \
     ASSERT(KeGetCurrentIrql() <= APC_LEVEL);                                \
-    ASSERT(_Thread == KeGetCurrentThread());                                \
-    ASSERT(_Thread->SpecialApcDisable < 0);                                 \
+    ASSERT((_Thread) == KeGetCurrentThread());                              \
+    ASSERT((_Thread)->SpecialApcDisable < 0);                               \
                                                                             \
     /* Leave region and check if APCs are OK now */                         \
-    if (!(++_Thread->SpecialApcDisable))                                    \
+    if (!(++(_Thread)->SpecialApcDisable))                                  \
     {                                                                       \
         /* Check for Kernel APCs on the list */                             \
-        if (!IsListEmpty(&_Thread->ApcState.                                \
+        if (!IsListEmpty(&(_Thread)->ApcState.                              \
                          ApcListHead[KernelMode]))                          \
         {                                                                   \
             /* Check for APC Delivery */                                    \
@@ -77,12 +77,12 @@ KeGetPreviousMode(VOID)
 #define KeEnterCriticalRegionThread(_Thread)                                \
 {                                                                           \
     /* Sanity checks */                                                     \
-    ASSERT(_Thread == KeGetCurrentThread());                                \
-    ASSERT((_Thread->KernelApcDisable <= 0) &&                              \
-           (_Thread->KernelApcDisable != -32768));                          \
+    ASSERT((_Thread) == KeGetCurrentThread());                              \
+    ASSERT(((_Thread)->KernelApcDisable <= 0) &&                            \
+           ((_Thread)->KernelApcDisable != -32768));                        \
                                                                             \
     /* Disable Kernel APCs */                                               \
-    _Thread->KernelApcDisable--;                                            \
+    (_Thread)->KernelApcDisable--;                                          \
 }
 
 #define KeEnterCriticalRegion()                                             \
@@ -97,18 +97,18 @@ KeGetPreviousMode(VOID)
 #define KeLeaveCriticalRegionThread(_Thread)                                \
 {                                                                           \
     /* Sanity checks */                                                     \
-    ASSERT(_Thread == KeGetCurrentThread());                                \
-    ASSERT(_Thread->KernelApcDisable < 0);                                  \
+    ASSERT((_Thread) == KeGetCurrentThread());                              \
+    ASSERT((_Thread)->KernelApcDisable < 0);                                \
                                                                             \
     /* Enable Kernel APCs */                                                \
-    _Thread->KernelApcDisable++;                                            \
+    (_Thread)->KernelApcDisable++;                                          \
                                                                             \
     /* Check if Kernel APCs are now enabled */                              \
-    if (!(_Thread->KernelApcDisable))                                       \
+    if (!((_Thread)->KernelApcDisable))                                     \
     {                                                                       \
         /* Check if we need to request an APC Delivery */                   \
-        if (!(IsListEmpty(&_Thread->ApcState.ApcListHead[KernelMode])) &&   \
-            !(_Thread->SpecialApcDisable))                                  \
+        if (!(IsListEmpty(&(_Thread)->ApcState.ApcListHead[KernelMode])) && \
+            !((_Thread)->SpecialApcDisable))                                \
         {                                                                   \
             /* Check for the right environment */                           \
             KiCheckForKernelApcDelivery();                                  \

Reply via email to