Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

822 lines
16 KiB

/*++
Copyright (c) 2002 Microsoft Corporation
Module Name:
kx.h
Abstract:
This module contains the public (external) header file for the kernel
that must be included after all other header files.
WARNING: There is code in windows\core\ntgdi\gre\i386\locka.asm that
mimics the functions to enter and leave critical regions.
This is very unfortunate since any changes to the subject
routines must be reflected in locka.asm also.
Author:
David N. Cutler (davec) 9-Jul-2002
--*/
#ifndef _KX_
#define _KX_
VOID
KiCheckForKernelApcDelivery (
VOID
);
VOID
FASTCALL
KiWaitForGuardedMutexEvent (
IN PKGUARDED_MUTEX Mutex
);
FORCEINLINE
VOID
KeEnterGuardedRegionThread (
IN PKTHREAD Thread
)
/*++
Routine Description:
This function disables special kernel APC's for the current thread.
N.B. The following code does not require any interlocks. There are
two cases of interest: 1) On an MP system, the thread cannot
be running on two processors as once, and 2) if the thread is
is interrupted to deliver a kernel mode APC which also calls
this routine, the values read and stored will stack and unstack
properly.
Arguments:
Thread - Supplies a pointer to the current thread.
N.B. This must be a pointer to the current thread.
Return Value:
None.
--*/
{
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
ASSERT(Thread == KeGetCurrentThread());
ASSERT((Thread->SpecialApcDisable <= 0) && (Thread->SpecialApcDisable != -32768));
Thread->SpecialApcDisable -= 1;
KeMemoryBarrierWithoutFence();
return;
}
FORCEINLINE
VOID
KeEnterGuardedRegion (
VOID
)
/*++
Routine Description:
This function disables special kernel APC's for the current thread.
N.B. The following code does not require any interlocks. There are
two cases of interest: 1) On an MP system, the thread cannot
be running on two processors as once, and 2) if the thread is
is interrupted to deliver a kernel mode APC which also calls
this routine, the values read and stored will stack and unstack
properly.
Arguments:
None.
Return Value:
None.
--*/
{
KeEnterGuardedRegionThread(KeGetCurrentThread());
return;
}
FORCEINLINE
VOID
KeLeaveGuardedRegionThread (
IN PKTHREAD Thread
)
/*++
Routine Description:
This function enables special kernel APC's.
N.B. The following code does not require any interlocks. There are
two cases of interest: 1) On an MP system, the thread cannot
be running on two processors as once, and 2) if the thread is
is interrupted to deliver a kernel mode APC which also calls
this routine, the values read and stored will stack and unstack
properly.
Arguments:
Thread - Supplies a pointer to the current thread.
N.B. This must be a pointer to the current thread.
Return Value:
None.
--*/
{
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
ASSERT(Thread == KeGetCurrentThread());
ASSERT(Thread->SpecialApcDisable < 0);
KeMemoryBarrierWithoutFence();
if ((Thread->SpecialApcDisable = Thread->SpecialApcDisable + 1) == 0) {
KeMemoryBarrier();
if (Thread->ApcState.ApcListHead[KernelMode].Flink !=
&Thread->ApcState.ApcListHead[KernelMode]) {
KiCheckForKernelApcDelivery();
}
}
return;
}
FORCEINLINE
VOID
KeLeaveGuardedRegion (
VOID
)
/*++
Routine Description:
This function enables special kernel APC's.
N.B. The following code does not require any interlocks. There are
two cases of interest: 1) On an MP system, the thread cannot
be running on two processors as once, and 2) if the thread is
is interrupted to deliver a kernel mode APC which also calls
this routine, the values read and stored will stack and unstack
properly.
Arguments:
None.
Return Value:
None.
--*/
{
KeLeaveGuardedRegionThread(KeGetCurrentThread());
return;
}
FORCEINLINE
VOID
KeEnterCriticalRegionThread (
PKTHREAD Thread
)
/*++
Routine Description:
This function disables kernel APC's for the current thread.
N.B. The following code does not require any interlocks. There are
two cases of interest: 1) On an MP system, the thread cannot
be running on two processors as once, and 2) if the thread is
is interrupted to deliver a kernel mode APC which also calls
this routine, the values read and stored will stack and unstack
properly.
Arguments:
Thread - Supplies a pointer to the current thread.
N.B. This must be a pointer to the current thread.
Return Value:
None.
--*/
{
ASSERT(Thread == KeGetCurrentThread());
ASSERT((Thread->KernelApcDisable <= 0) && (Thread->KernelApcDisable != -32768));
Thread->KernelApcDisable -= 1;
KeMemoryBarrierWithoutFence();
return;
}
FORCEINLINE
VOID
KeEnterCriticalRegion (
VOID
)
/*++
Routine Description:
This function disables kernel APC's for the current thread.
N.B. The following code does not require any interlocks. There are
two cases of interest: 1) On an MP system, the thread cannot
be running on two processors as once, and 2) if the thread is
is interrupted to deliver a kernel mode APC which also calls
this routine, the values read and stored will stack and unstack
properly.
Arguments:
None.
Return Value:
None.
--*/
{
KeEnterCriticalRegionThread(KeGetCurrentThread());
return;
}
FORCEINLINE
VOID
KeLeaveCriticalRegionThread (
IN PKTHREAD Thread
)
/*++
Routine Description:
This function enables normal kernel APC's for the current thread.
N.B. The following code does not require any interlocks. There are
two cases of interest: 1) On an MP system, the thread cannot
be running on two processors as once, and 2) if the thread is
is interrupted to deliver a kernel mode APC which also calls
this routine, the values read and stored will stack and unstack
properly.
Arguments:
Thread - Supplies a pointer to the current thread.
N.B. This must be a pointer to the current thread.
Return Value:
None.
--*/
{
ASSERT(Thread == KeGetCurrentThread());
ASSERT(Thread->KernelApcDisable < 0);
KeMemoryBarrierWithoutFence();
if ((Thread->KernelApcDisable = Thread->KernelApcDisable + 1) == 0) {
KeMemoryBarrier();
if (Thread->ApcState.ApcListHead[KernelMode].Flink !=
&Thread->ApcState.ApcListHead[KernelMode]) {
if (Thread->SpecialApcDisable == 0) {
KiCheckForKernelApcDelivery();
}
}
}
return;
}
FORCEINLINE
VOID
KeLeaveCriticalRegion (
VOID
)
/*++
Routine Description:
This function enables normal kernel APC's for the current thread.
N.B. The following code does not require any interlocks. There are
two cases of interest: 1) On an MP system, the thread cannot
be running on two processors as once, and 2) if the thread is
is interrupted to deliver a kernel mode APC which also calls
this routine, the values read and stored will stack and unstack
properly.
Arguments:
None.
Return Value:
None.
--*/
{
KeLeaveCriticalRegionThread(KeGetCurrentThread());
return;
}
FORCEINLINE
BOOLEAN
KeAreApcsDisabled (
VOID
)
/*++
Routine description:
This function returns whether kernel are disabled for the current thread.
Arguments:
None.
Return Value:
If either the kernel or special APC disable count is nonzero, then a value
of TRUE is returned. Otherwise, a value of FALSE is returned.
--*/
{
return (BOOLEAN)(KeGetCurrentThread()->CombinedApcDisable != 0);
}
FORCEINLINE
BOOLEAN
KeAreAllApcsDisabled (
VOID
)
/*++
Routine description:
This function returns whether all APCs are disabled for the current thread.
Arguments:
None.
Return Value:
If either the special APC disable count is nonzero or the IRQL is greater
than or equal to APC_LEVEL, then a value of TRUE is returned. Otherwise,
a value of FALSE is returned.
--*/
{
return (BOOLEAN)((KeGetCurrentThread()->SpecialApcDisable != 0) ||
(KeGetCurrentIrql() >= APC_LEVEL));
}
FORCEINLINE
VOID
KeInitializeGuardedMutex (
IN PKGUARDED_MUTEX Mutex
)
/*++
Routine Description:
This function initializes a guarded mutex.
Arguments:
Mutex - Supplies a pointer to a guarded mutex.
Return Value:
None.
--*/
{
Mutex->Owner = NULL;
Mutex->Count = 1;
Mutex->Contention = 0;
KeInitializeEvent(&Mutex->Event, SynchronizationEvent, FALSE);
return;
}
FORCEINLINE
VOID
KeAcquireGuardedMutex (
IN PKGUARDED_MUTEX Mutex
)
/*++
Routine Description:
This function enters a guarded region and acquires ownership of a guarded
mutex.
Arguments:
Mutex - Supplies a pointer to a guarded mutex.
Return Value:
None.
--*/
{
PKTHREAD Thread;
//
// Enter a guarded region and decrement the ownership count to determine
// if the guarded mutex is owned.
//
Thread = KeGetCurrentThread();
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
ASSERT(Mutex->Owner != Thread);
KeEnterGuardedRegionThread(Thread);
if (InterlockedDecrementAcquire(&Mutex->Count) != 0) {
//
// The guarded mutex is owned.
//
// Increment contention count and wait for ownership to be granted.
//
KiWaitForGuardedMutexEvent(Mutex);
}
//
// Grant ownership of the guarded mutext to the current thread.
//
Mutex->Owner = Thread;
#if DBG
Mutex->SpecialApcDisable = Thread->SpecialApcDisable;
#endif
return;
}
FORCEINLINE
VOID
KeReleaseGuardedMutex (
IN PKGUARDED_MUTEX Mutex
)
/*++
Routine Description:
This function releases ownership of a guarded mutex and leaves a guarded
region.
Arguments:
Mutex - Supplies a pointer to a guarded mutex.
Return Value:
None.
--*/
{
PKTHREAD Thread;
//
// Clear the owner thread and increment the guarded mutex count to
// detemine if there are any threads waiting for ownership to be
// granted.
//
Thread = KeGetCurrentThread();
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
ASSERT(Mutex->Owner == Thread);
ASSERT(Thread->SpecialApcDisable == Mutex->SpecialApcDisable);
Mutex->Owner = NULL;
if (InterlockedIncrementRelease(&Mutex->Count) <= 0) {
//
// There are one or more threads waiting for ownership of the guarded
// mutex.
//
KeSetEventBoostPriority(&Mutex->Event, NULL);
}
//
// Leave guarded region.
//
KeLeaveGuardedRegionThread(Thread);
return;
}
FORCEINLINE
BOOLEAN
KeTryToAcquireGuardedMutex (
IN PKGUARDED_MUTEX Mutex
)
/*++
Routine Description:
This function attempts to acquire ownership of a guarded mutex, and if
successful, enters a guarded region.
Arguments:
Mutex - Supplies a pointer to a guarded mutex.
Return Value:
If the guarded mutex was successfully acquired, then a value of TRUE
is returned as the function value. Otherwise, a value of FALSE is
returned.
--*/
{
PKTHREAD Thread;
//
// Enater a guarded region and attempt to acquire ownership of the guarded
// mutex.
//
Thread = KeGetCurrentThread();
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
KeEnterGuardedRegionThread(Thread);
if (InterlockedCompareExchange(&Mutex->Count, 0, 1) != 1) {
//
// The guarded mutex is owned.
//
// Leave guarded region and return FALSE.
//
KeLeaveGuardedRegionThread(Thread);
return FALSE;
} else {
//
// Grant ownership of the guarded mutex to the current thread and
// return TRUE.
//
Mutex->Owner = Thread;
#if DBG
Mutex->SpecialApcDisable = Thread->SpecialApcDisable;
#endif
return TRUE;
}
}
FORCEINLINE
VOID
KeAcquireGuardedMutexUnsafe (
IN PKGUARDED_MUTEX Mutex
)
/*++
Routine Description:
This function acquires ownership of a guarded mutex, but does enter a
guarded region.
Arguments:
Mutex - Supplies a pointer to a guarded mutex.
Return Value:
None.
--*/
{
PKTHREAD Thread;
//
// Decrement the ownership count to determine if the guarded mutex is
// owned.
//
Thread = KeGetCurrentThread();
ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
(Thread->SpecialApcDisable < 0) ||
(Thread->Teb == NULL) ||
(Thread->Teb >= MM_SYSTEM_RANGE_START));
ASSERT(Mutex->Owner != Thread);
if (InterlockedDecrement(&Mutex->Count) != 0) {
//
// The guarded mutex is owned.
//
// Increment contention count and wait for ownership to be granted.
//
KiWaitForGuardedMutexEvent(Mutex);
}
//
// Grant ownership of the guarded mutex to the current thread.
//
Mutex->Owner = Thread;
return;
}
FORCEINLINE
VOID
KeReleaseGuardedMutexUnsafe (
IN PKGUARDED_MUTEX Mutex
)
/*++
Routine Description:
This function releases ownership of a guarded mutex, and does not leave
a guarded region.
Arguments:
Mutex - Supplies a pointer to a guarded mutex.
Return Value:
None.
--*/
{
PKTHREAD Thread;
//
// Clear the owner thread and increment the guarded mutex count to
// determine if there are any threads waiting for ownership to be
// granted.
//
Thread = KeGetCurrentThread();
ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
(Thread->SpecialApcDisable < 0) ||
(Thread->Teb == NULL) ||
(Thread->Teb >= MM_SYSTEM_RANGE_START));
ASSERT(Mutex->Owner == Thread);
Mutex->Owner = NULL;
if (InterlockedIncrement(&Mutex->Count) <= 0) {
//
// There are one or more threads waiting for ownership of the guarded
// mutex.
//
KeSetEventBoostPriority(&Mutex->Event, NULL);
}
return;
}
FORCEINLINE
PKTHREAD
KeGetOwnerGuardedMutex (
IN PKGUARDED_MUTEX Mutex
)
/*++
Routine Description:
This function returns the owner of the specified guarded mutex.
Arguments:
Mutex - Supplies a pointer to a guarded mutex.
Return Value:
If the guarded mutex is owned, then a pointer to the owner thread is
returned. Otherwise, NULL is returned.
--*/
{
return Mutex->Owner;
}
FORCEINLINE
BOOLEAN
KeIsGuardedMutexOwned (
IN PKGUARDED_MUTEX Mutex
)
/*++
Routine Description:
This function tests whether the specified guarded mutext is owned.
Arguments:
Mutex - Supplies a pointer to a guarded mutex.
Return Value:
A value of TRUE is returned if the guarded mutex is owned. Otherwise,
a value of FALSE is returned.
--*/
{
return (BOOLEAN)(Mutex->Count != 1);
}
#endif