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(); \