📄 ke_x.h
字号:
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/include/ke_x.h
* PURPOSE: Internal Inlined Functions for the Kernel
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
//
// Thread Dispatcher Header DebugActive Mask
//
#define DR_MASK(x) 1 << x
#define DR_ACTIVE_MASK 0x10
#define DR_REG_MASK 0x4F
//
// Sanitizes a selector
//
FORCEINLINE
ULONG
Ke386SanitizeSeg(IN ULONG Cs,
IN KPROCESSOR_MODE Mode)
{
//
// Check if we're in kernel-mode, and force CPL 0 if so.
// Otherwise, force CPL 3.
//
return ((Mode == KernelMode) ?
(Cs & (0xFFFF & ~RPL_MASK)) :
(RPL_MASK | (Cs & 0xFFFF)));
}
//
// Sanitizes EFLAGS
//
FORCEINLINE
ULONG
Ke386SanitizeFlags(IN ULONG Eflags,
IN KPROCESSOR_MODE Mode)
{
//
// Check if we're in kernel-mode, and sanitize EFLAGS if so.
// Otherwise, also force interrupt mask on.
//
return ((Mode == KernelMode) ?
(Eflags & (EFLAGS_USER_SANITIZE | EFLAGS_INTERRUPT_MASK)) :
(EFLAGS_INTERRUPT_MASK | (Eflags & EFLAGS_USER_SANITIZE)));
}
//
// Gets a DR register from a CONTEXT structure
//
FORCEINLINE
PVOID
KiDrFromContext(IN ULONG Dr,
IN PCONTEXT Context)
{
return *(PVOID*)((ULONG_PTR)Context + KiDebugRegisterContextOffsets[Dr]);
}
//
// Gets a DR register from a KTRAP_FRAME structure
//
FORCEINLINE
PVOID*
KiDrFromTrapFrame(IN ULONG Dr,
IN PKTRAP_FRAME TrapFrame)
{
return (PVOID*)((ULONG_PTR)TrapFrame + KiDebugRegisterTrapOffsets[Dr]);
}
//
//
//
FORCEINLINE
PVOID
Ke386SanitizeDr(IN PVOID DrAddress,
IN KPROCESSOR_MODE Mode)
{
//
// Check if we're in kernel-mode, and return the address directly if so.
// Otherwise, make sure it's not inside the kernel-mode address space.
// If it is, then clear the address.
//
return ((Mode == KernelMode) ? DrAddress :
(DrAddress <= MM_HIGHEST_USER_ADDRESS) ? DrAddress : 0);
}
//
// Enters a Guarded Region
//
#define KeEnterGuardedRegion() \
{ \
PKTHREAD _Thread = KeGetCurrentThread(); \
\
/* Sanity checks */ \
ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL); \
ASSERT(_Thread == KeGetCurrentThread()); \
ASSERT((_Thread->SpecialApcDisable <= 0) && \
(_Thread->SpecialApcDisable != -32768)); \
\
/* Disable Special APCs */ \
_Thread->SpecialApcDisable--; \
}
//
// Leaves a Guarded Region
//
#define KeLeaveGuardedRegion() \
{ \
PKTHREAD _Thread = KeGetCurrentThread(); \
\
/* Sanity checks */ \
ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL); \
ASSERT(_Thread == KeGetCurrentThread()); \
ASSERT(_Thread->SpecialApcDisable < 0); \
\
/* Leave region and check if APCs are OK now */ \
if (!(++_Thread->SpecialApcDisable)) \
{ \
/* Check for Kernel APCs on the list */ \
if (!IsListEmpty(&_Thread->ApcState. \
ApcListHead[KernelMode])) \
{ \
/* Check for APC Delivery */ \
KiCheckForKernelApcDelivery(); \
} \
} \
}
//
// TODO: Guarded Mutex Routines
//
//
// Enters a Critical Region
//
#define KeEnterCriticalRegion() \
{ \
PKTHREAD _Thread = KeGetCurrentThread(); \
\
/* Sanity checks */ \
ASSERT(_Thread == KeGetCurrentThread()); \
ASSERT((_Thread->KernelApcDisable <= 0) && \
(_Thread->KernelApcDisable != -32768)); \
\
/* Disable Kernel APCs */ \
_Thread->KernelApcDisable--; \
}
//
// Leaves a Critical Region
//
#define KeLeaveCriticalRegion() \
{ \
PKTHREAD _Thread = KeGetCurrentThread(); \
\
/* Sanity checks */ \
ASSERT(_Thread == KeGetCurrentThread()); \
ASSERT(_Thread->KernelApcDisable < 0); \
\
/* Enable Kernel APCs */ \
_Thread->KernelApcDisable++; \
\
/* Check if Kernel APCs are now enabled */ \
if (!(_Thread->KernelApcDisable)) \
{ \
/* Check if we need to request an APC Delivery */ \
if (!(IsListEmpty(&_Thread->ApcState.ApcListHead[KernelMode])) && \
!(_Thread->SpecialApcDisable)) \
{ \
/* Check for the right environment */ \
KiCheckForKernelApcDelivery(); \
} \
} \
}
//
// Satisfies the wait of any dispatcher object
//
#define KiSatisfyObjectWait(Object, Thread) \
{ \
/* Special case for Mutants */ \
if ((Object)->Header.Type == MutantObject) \
{ \
/* Decrease the Signal State */ \
(Object)->Header.SignalState--; \
\
/* Check if it's now non-signaled */ \
if (!(Object)->Header.SignalState) \
{ \
/* Set the Owner Thread */ \
(Object)->OwnerThread = Thread; \
\
/* Disable APCs if needed */ \
Thread->KernelApcDisable -= (Object)->ApcDisable; \
\
/* Check if it's abandoned */ \
if ((Object)->Abandoned) \
{ \
/* Unabandon it */ \
(Object)->Abandoned = FALSE; \
\
/* Return Status */ \
Thread->WaitStatus = STATUS_ABANDONED; \
} \
\
/* Insert it into the Mutant List */ \
InsertHeadList(Thread->MutantListHead.Blink, \
&(Object)->MutantListEntry); \
} \
} \
else if (((Object)->Header.Type & TIMER_OR_EVENT_TYPE) == \
EventSynchronizationObject) \
{ \
/* Synchronization Timers and Events just get un-signaled */ \
(Object)->Header.SignalState = 0; \
} \
else if ((Object)->Header.Type == SemaphoreObject) \
{ \
/* These ones can have multiple states, so we only decrease it */ \
(Object)->Header.SignalState--; \
} \
}
//
// Satisfies the wait of a mutant dispatcher object
//
#define KiSatisfyMutantWait(Object, Thread) \
{ \
/* Decrease the Signal State */ \
(Object)->Header.SignalState--; \
\
/* Check if it's now non-signaled */ \
if (!(Object)->Header.SignalState) \
{ \
/* Set the Owner Thread */ \
(Object)->OwnerThread = Thread; \
\
/* Disable APCs if needed */ \
Thread->KernelApcDisable -= (Object)->ApcDisable; \
\
/* Check if it's abandoned */ \
if ((Object)->Abandoned) \
{ \
/* Unabandon it */ \
(Object)->Abandoned = FALSE; \
\
/* Return Status */ \
Thread->WaitStatus = STATUS_ABANDONED; \
} \
\
/* Insert it into the Mutant List */ \
InsertHeadList(Thread->MutantListHead.Blink, \
&(Object)->MutantListEntry); \
} \
}
//
// Satisfies the wait of any nonmutant dispatcher object
//
#define KiSatisfyNonMutantWait(Object, Thread) \
{ \
if (((Object)->Header.Type & TIMER_OR_EVENT_TYPE) == \
EventSynchronizationObject) \
{ \
/* Synchronization Timers and Events just get un-signaled */ \
(Object)->Header.SignalState = 0; \
} \
else if ((Object)->Header.Type == SemaphoreObject) \
{ \
/* These ones can have multiple states, so we only decrease it */ \
(Object)->Header.SignalState--; \
} \
}
//
// Recalculates the due time
//
PLARGE_INTEGER
FORCEINLINE
KiRecalculateDueTime(IN PLARGE_INTEGER OriginalDueTime,
IN PLARGE_INTEGER DueTime,
IN OUT PLARGE_INTEGER NewDueTime)
{
/* Don't do anything for absolute waits */
if (OriginalDueTime->QuadPart >= 0) return OriginalDueTime;
/* Otherwise, query the interrupt time and recalculate */
NewDueTime->QuadPart = KeQueryInterruptTime();
NewDueTime->QuadPart -= DueTime->QuadPart;
return NewDueTime;
}
//
// Determines wether a thread should be added to the wait list
//
FORCEINLINE
BOOLEAN
KiCheckThreadStackSwap(IN PKTHREAD Thread,
IN KPROCESSOR_MODE WaitMode)
{
/* Check the required conditions */
if ((WaitMode != KernelMode) &&
(Thread->EnableStackSwap) &&
(Thread->Priority >= (LOW_REALTIME_PRIORITY + 9)))
{
/* We are go for swap */
return TRUE;
}
else
{
/* Don't swap the thread */
return FALSE;
}
}
//
// Adds a thread to the wait list
//
#define KiAddThreadToWaitList(Thread, Swappable) \
{ \
/* Make sure it's swappable */ \
if (Swappable) \
{ \
/* Insert it into the PRCB's List */ \
InsertTailList(&KeGetCurrentPrcb()->WaitListHead, \
&Thread->WaitListEntry); \
} \
}
//
// Checks if a wait in progress should be interrupted by APCs or an alertable
// state.
//
FORCEINLINE
NTSTATUS
KiCheckAlertability(IN PKTHREAD Thread,
IN BOOLEAN Alertable,
IN KPROCESSOR_MODE WaitMode)
{
/* Check if the wait is alertable */
if (Alertable)
{
/* It is, first check if the thread is alerted in this mode */
if (Thread->Alerted[WaitMode])
{
/* It is, so bail out of the wait */
Thread->Alerted[WaitMode] = FALSE;
return STATUS_ALERTED;
}
else if ((WaitMode != KernelMode) &&
(!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])))
{
/* It's isn't, but this is a user wait with queued user APCs */
Thread->ApcState.UserApcPending = TRUE;
return STATUS_USER_APC;
}
else if (Thread->Alerted[KernelMode])
{
/* It isn't that either, but we're alered in kernel mode */
Thread->Alerted[KernelMode] = FALSE;
return STATUS_ALERTED;
}
}
else if ((WaitMode != KernelMode) && (Thread->ApcState.UserApcPending))
{
/* Not alertable, but this is a user wait with pending user APCs */
return STATUS_USER_APC;
}
/* Otherwise, we're fine */
return STATUS_WAIT_0;
}
FORCEINLINE
BOOLEAN
KxDelayThreadWait(IN PKTHREAD Thread,
IN BOOLEAN Alertable,
IN KPROCESSOR_MODE WaitMode)
{
BOOLEAN Swappable;
PKWAIT_BLOCK TimerBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK];
/* Setup the Wait Block */
Thread->WaitBlockList = TimerBlock;
TimerBlock->NextWaitBlock = TimerBlock;
/* Link the timer to this Wait Block */
Thread->Timer.Header.WaitListHead.Flink = &TimerBlock->WaitListEntry;
Thread->Timer.Header.WaitListHead.Blink = &TimerBlock->WaitListEntry;
/* Clear wait status */
Thread->WaitStatus = STATUS_WAIT_0;
/* Setup wait fields */
Thread->Alertable = Alertable;
Thread->WaitReason = DelayExecution;
Thread->WaitMode = WaitMode;
/* Check if we can swap the thread's stack */
Thread->WaitListEntry.Flink = NULL;
Swappable = KiCheckThreadStackSwap(Thread, WaitMode);
/* Set the wait time */
Thread->WaitTime = ((PLARGE_INTEGER)&KeTickCount)->LowPart;
return Swappable;
}
FORCEINLINE
BOOLEAN
KxMultiThreadWait(IN PKTHREAD Thread,
IN PKWAIT_BLOCK WaitBlock,
IN BOOLEAN Alertable,
IN KWAIT_REASON WaitReason,
IN KPROCESSOR_MODE WaitMode)
{
BOOLEAN Swappable;
PKTIMER ThreadTimer = &Thread->Timer;
/* Set default wait status */
Thread->WaitStatus = STATUS_WAIT_0;
/* Link wait block array to the thread */
Thread->WaitBlockList = WaitBlock;
/* Initialize the timer list */
InitializeListHead(&ThreadTimer->Header.WaitListHead);
/* Set wait settings */
Thread->Alertable = Alertable;
Thread->WaitMode = WaitMode;
Thread->WaitReason = WaitReason;
/* Check if we can swap the thread's stack */
Thread->WaitListEntry.Flink = NULL;
Swappable = KiCheckThreadStackSwap(Thread, WaitMode);
/* Set the wait time */
Thread->WaitTime = ((PLARGE_INTEGER)&KeTickCount)->LowPart;
return Swappable;
}
FORCEINLINE
BOOLEAN
KxSingleThreadWait(IN PKTHREAD Thread,
IN PKWAIT_BLOCK WaitBlock,
IN PVOID Object,
IN PLARGE_INTEGER Timeout,
IN BOOLEAN Alertable,
IN KWAIT_REASON WaitReason,
IN KPROCESSOR_MODE WaitMode)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -