diff --git a/xtoskrnl/includes/ke/kthread.hh b/xtoskrnl/includes/ke/kthread.hh index 4f724a4..2774a3e 100644 --- a/xtoskrnl/includes/ke/kthread.hh +++ b/xtoskrnl/includes/ke/kthread.hh @@ -22,6 +22,8 @@ namespace KE public: STATIC XTAPI VOID AttachThread(IN PKTHREAD Thread); + STATIC XTFASTCALL VOID EnterCriticalRegion(); + STATIC XTFASTCALL VOID EnterCriticalRegion(IN PKTHREAD Thread); STATIC XTAPI PETHREAD GetInitialThread(VOID); STATIC XTAPI XTSTATUS InitializeIdleThread(IN PKPROCESS IdleProcess, IN OUT PKTHREAD IdleThread, @@ -36,6 +38,8 @@ namespace KE IN PVOID EnvironmentBlock, IN PVOID Stack, IN BOOLEAN AttachToProcess); + STATIC XTFASTCALL VOID LeaveCriticalRegion(); + STATIC XTFASTCALL VOID LeaveCriticalRegion(IN PKTHREAD Thread); private: STATIC XTAPI VOID HandleSystemThreadExit(VOID); diff --git a/xtoskrnl/ke/kthread.cc b/xtoskrnl/ke/kthread.cc index dc373ab..2bd7c06 100644 --- a/xtoskrnl/ke/kthread.cc +++ b/xtoskrnl/ke/kthread.cc @@ -75,6 +75,42 @@ KE::KThread::AttachThread(IN OUT PKTHREAD Thread) } } +/** + * Disables the delivery of normal kernel APCs for the current thread. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTFASTCALL +VOID +KE::KThread::EnterCriticalRegion() +{ + /* Prevent the thread from being preempted by an APC */ + EnterCriticalRegion(KE::Processor::GetCurrentThread()); +} + +/** + * Disables the delivery of normal kernel APCs for the specified thread. + * + * @param Thread + * Supplies a pointer to the thread object whose APC delivery is to be disabled. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTFASTCALL +VOID +KE::KThread::EnterCriticalRegion(IN PKTHREAD Thread) +{ + /* Disable Kernel APCs */ + Thread->KernelApcDisable--; + + /* Prevent the compiler from reordering code */ + AR::CpuFunctions::ReadWriteBarrier(); +} + /** * Retrieves a pointer to the system's initial executive thread object. * @@ -347,6 +383,60 @@ KE::KThread::InitializeThread(IN PKPROCESS Process, return STATUS_SUCCESS; } +/** + * Re-enables the delivery of kernel APCs for the current thread. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTFASTCALL +VOID +KE::KThread::LeaveCriticalRegion() +{ + /* Allow APCs to preempt the thread */ + LeaveCriticalRegion(KE::Processor::GetCurrentThread()); +} + +/** + * Re-enables the delivery of kernel APCs for the specified thread. + * + * @param Thread + * Supplies a pointer to the thread object whose APC delivery is to be re-enabled. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTFASTCALL +VOID +KE::KThread::LeaveCriticalRegion(IN PKTHREAD Thread) +{ + /* Ensure the compiler does not reorder code */ + AR::CpuFunctions::ReadWriteBarrier(); + + /* Re-enable APC delivery */ + Thread->KernelApcDisable++; + + /* Check if APC delivery is enabled */ + if(!Thread->KernelApcDisable) + { + /* Memory barrier */ + AR::CpuFunctions::MemoryBarrier(); + + /* Check for any pending kernel APCs */ + if(!RTL::LinkedList::ListEmpty(&Thread->ApcState.ApcListHead[KernelMode])) + { + /* Check if special kernel APCs are not disabled */ + if(!Thread->SpecialApcDisable) + { + /* Initiate delivery of the pending APCs */ + KE::Apc::CheckApcDelivery(); + } + } + } +} + /** * Suspend APC-built thread NOP routine. It takes no actions. *