[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.
This commit is contained in:
Thomas Faber 2021-10-28 10:59:20 -04:00
parent 8d10682307
commit 2e76fb9fe1
No known key found for this signature in database
GPG key ID: 076E7C3D44720826
2 changed files with 29 additions and 24 deletions

View file

@ -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;

View file

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