- Remove some duplicated/useless code and use internal forward exports instead.

- Set kernel apc pending flag when needed in KeReleaseMutant
- Optimize check for kernel apc delivery in KeReleaseMutant
- Raise right exception in KeReleaseMutant
- Simplify KeInitializeMutant and remove some duplicated operations.
- Remove duplicated listhead initialization in KeInitiializeMutex
- Use correct increment in KeReleaseMutex

svn path=/trunk/; revision=18185
This commit is contained in:
Alex Ionescu 2005-10-01 08:58:49 +00:00
parent f57183be46
commit 35eb408157
2 changed files with 46 additions and 77 deletions

View file

@ -27,33 +27,30 @@ STDCALL
KeInitializeMutant(IN PKMUTANT Mutant, KeInitializeMutant(IN PKMUTANT Mutant,
IN BOOLEAN InitialOwner) IN BOOLEAN InitialOwner)
{ {
ULONG Signaled = TRUE; PKTHREAD CurrentThread;
PKTHREAD CurrentThread = NULL;
KIRQL OldIrql; KIRQL OldIrql;
DPRINT("KeInitializeMutant: %x\n", Mutant); DPRINT("KeInitializeMutant: %x\n", Mutant);
/* Check if we have an initial owner */ /* Check if we have an initial owner */
if (InitialOwner == TRUE) { if (InitialOwner == TRUE)
{
/* In this case, the object is not signaled */
Signaled = FALSE;
/* We also need to associate a thread */ /* We also need to associate a thread */
CurrentThread = KeGetCurrentThread(); CurrentThread = KeGetCurrentThread();
Mutant->OwnerThread = CurrentThread;
/* We're about to touch the Thread, so lock the Dispatcher */ /* We're about to touch the Thread, so lock the Dispatcher */
OldIrql = KeAcquireDispatcherDatabaseLock(); OldIrql = KeAcquireDispatcherDatabaseLock();
/* And insert it into its list */ /* And insert it into its list */
InsertTailList(&CurrentThread->MutantListHead, &Mutant->MutantListEntry); InsertTailList(&CurrentThread->MutantListHead,
&Mutant->MutantListEntry);
/* Release Dispatcher Lock */ /* Release Dispatcher Lock */
KeReleaseDispatcherDatabaseLock(OldIrql); KeReleaseDispatcherDatabaseLock(OldIrql);
DPRINT("Mutant with Initial Owner\n"); DPRINT("Mutant with Initial Owner\n");
}
} else { else
{
/* In this case, we don't have an owner yet */ /* In this case, we don't have an owner yet */
Mutant->OwnerThread = NULL; Mutant->OwnerThread = NULL;
} }
@ -62,10 +59,9 @@ KeInitializeMutant(IN PKMUTANT Mutant,
KeInitializeDispatcherHeader(&Mutant->Header, KeInitializeDispatcherHeader(&Mutant->Header,
MutantObject, MutantObject,
sizeof(KMUTANT) / sizeof(ULONG), sizeof(KMUTANT) / sizeof(ULONG),
Signaled); InitialOwner ? FALSE : TRUE);
/* Initialize the default data */ /* Initialize the default data */
Mutant->OwnerThread = CurrentThread;
Mutant->Abandoned = FALSE; Mutant->Abandoned = FALSE;
Mutant->ApcDisable = 0; Mutant->ApcDisable = 0;
} }
@ -80,18 +76,16 @@ KeInitializeMutex(IN PKMUTEX Mutex,
{ {
DPRINT("KeInitializeMutex: %x\n", Mutex); DPRINT("KeInitializeMutex: %x\n", Mutex);
/* Set up the Dispatcher Header */ /* Set up the Dispatcher Header */
KeInitializeDispatcherHeader(&Mutex->Header, KeInitializeDispatcherHeader(&Mutex->Header,
MutantObject, MutantObject,
sizeof(KMUTEX) / sizeof(ULONG), sizeof(KMUTEX) / sizeof(ULONG),
1); TRUE);
/* Initialize the default data */ /* Initialize the default data */
Mutex->OwnerThread = NULL; Mutex->OwnerThread = NULL;
Mutex->Abandoned = FALSE; Mutex->Abandoned = FALSE;
Mutex->ApcDisable = 1; Mutex->ApcDisable = 1;
InitializeListHead(&Mutex->Header.WaitListHead);
} }
/* /*
@ -105,17 +99,6 @@ KeReadStateMutant(IN PKMUTANT Mutant)
return(Mutant->Header.SignalState); return(Mutant->Header.SignalState);
} }
/*
* @implemented
*/
LONG
STDCALL
KeReadStateMutex(IN PKMUTEX Mutex)
{
/* Return the Signal State */
return(Mutex->Header.SignalState);
}
/* /*
* @implemented * @implemented
*/ */
@ -129,7 +112,6 @@ KeReleaseMutant(IN PKMUTANT Mutant,
KIRQL OldIrql; KIRQL OldIrql;
LONG PreviousState; LONG PreviousState;
PKTHREAD CurrentThread = KeGetCurrentThread(); PKTHREAD CurrentThread = KeGetCurrentThread();
DPRINT("KeReleaseMutant: %x\n", Mutant); DPRINT("KeReleaseMutant: %x\n", Mutant);
/* Lock the Dispatcher Database */ /* Lock the Dispatcher Database */
@ -139,22 +121,26 @@ KeReleaseMutant(IN PKMUTANT Mutant,
PreviousState = Mutant->Header.SignalState; PreviousState = Mutant->Header.SignalState;
/* Check if it is to be abandonned */ /* Check if it is to be abandonned */
if (Abandon == FALSE) { if (Abandon == FALSE)
{
/* Make sure that the Owner Thread is the current Thread */ /* Make sure that the Owner Thread is the current Thread */
if (Mutant->OwnerThread != CurrentThread) { if (Mutant->OwnerThread != CurrentThread)
{
DPRINT1("Trying to touch a Mutant that the caller doesn't own!\n");
/* Release the lock */
KeReleaseDispatcherDatabaseLock(OldIrql); KeReleaseDispatcherDatabaseLock(OldIrql);
DPRINT1("Trying to touch a Mutant that the caller doesn't own!\n"); /* Raise an exception */
ExRaiseStatus(STATUS_MUTANT_NOT_OWNED); ExRaiseStatus(Mutant->Abandoned ? STATUS_ABANDONED :
STATUS_MUTANT_NOT_OWNED);
} }
/* If the thread owns it, then increase the signal state */ /* If the thread owns it, then increase the signal state */
Mutant->Header.SignalState++; Mutant->Header.SignalState++;
}
} else { else
{
/* It's going to be abandonned */ /* It's going to be abandonned */
DPRINT("Abandonning the Mutant\n"); DPRINT("Abandonning the Mutant\n");
Mutant->Header.SignalState = 1; Mutant->Header.SignalState = 1;
@ -162,24 +148,27 @@ KeReleaseMutant(IN PKMUTANT Mutant,
} }
/* Check if the signal state is only single */ /* Check if the signal state is only single */
if (Mutant->Header.SignalState == 1) { if (Mutant->Header.SignalState == 1)
{
/* Check if it's below 0 now */ /* Check if it's below 0 now */
if (PreviousState <= 0) { if (PreviousState <= 0)
{
/* Remove the mutant from the list */ /* Remove the mutant from the list */
DPRINT("Removing Mutant\n"); DPRINT("Removing Mutant %p\n", Mutant);
RemoveEntryList(&Mutant->MutantListEntry); RemoveEntryList(&Mutant->MutantListEntry);
/* Reenable APCs */ /* Reenable APCs */
DPRINT("Re-enabling APCs\n"); DPRINT("Re-enabling APCs\n");
CurrentThread->KernelApcDisable += Mutant->ApcDisable; CurrentThread->KernelApcDisable += Mutant->ApcDisable;
/* Force an Interrupt if Apcs are pending */ /* Check if the thread has APCs enabled */
if (!IsListEmpty(&CurrentThread->ApcState.ApcListHead[KernelMode])) { if (!CurrentThread->KernelApcDisable)
{
/* Make sure they aren't disabled though */ /* Check if any are pending */
if (!CurrentThread->KernelApcDisable) { if (!IsListEmpty(&CurrentThread->ApcState.ApcListHead[KernelMode]))
{
/* Set Kernel APC Pending */
CurrentThread->ApcState.KernelApcPending = TRUE;
/* Request the Interrupt */ /* Request the Interrupt */
DPRINT("Requesting APC Interupt\n"); DPRINT("Requesting APC Interupt\n");
@ -193,8 +182,8 @@ KeReleaseMutant(IN PKMUTANT Mutant,
/* Check if the Wait List isn't empty */ /* Check if the Wait List isn't empty */
DPRINT("Checking whether to wake the Mutant\n"); DPRINT("Checking whether to wake the Mutant\n");
if (!IsListEmpty(&Mutant->Header.WaitListHead)) { if (!IsListEmpty(&Mutant->Header.WaitListHead))
{
/* Wake the Mutant */ /* Wake the Mutant */
DPRINT("Waking the Mutant\n"); DPRINT("Waking the Mutant\n");
KiWaitTest(&Mutant->Header, Increment); KiWaitTest(&Mutant->Header, Increment);
@ -202,13 +191,13 @@ KeReleaseMutant(IN PKMUTANT Mutant,
} }
/* If the Wait is true, then return with a Wait and don't unlock the Dispatcher Database */ /* If the Wait is true, then return with a Wait and don't unlock the Dispatcher Database */
if (Wait == FALSE) { if (Wait == FALSE)
{
/* Release the Lock */ /* Release the Lock */
KeReleaseDispatcherDatabaseLock(OldIrql); KeReleaseDispatcherDatabaseLock(OldIrql);
}
} else { else
{
/* Set a wait */ /* Set a wait */
CurrentThread->WaitNext = TRUE; CurrentThread->WaitNext = TRUE;
CurrentThread->WaitIrql = OldIrql; CurrentThread->WaitIrql = OldIrql;
@ -226,28 +215,8 @@ STDCALL
KeReleaseMutex(IN PKMUTEX Mutex, KeReleaseMutex(IN PKMUTEX Mutex,
IN BOOLEAN Wait) IN BOOLEAN Wait)
{ {
/* There's no difference at this level between the two */ /* There's no difference at this level between the two */
return KeReleaseMutant(Mutex, IO_NO_INCREMENT, FALSE, Wait); return KeReleaseMutant(Mutex, 1, FALSE, Wait);
}
/*
* @implemented
*/
NTSTATUS
STDCALL
KeWaitForMutexObject(IN PKMUTEX Mutex,
IN KWAIT_REASON WaitReason,
IN KPROCESSOR_MODE WaitMode,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Timeout)
{
/* This is a simple macro. Export the function here though */
return KeWaitForSingleObject(Mutex,
WaitReason,
WaitMode,
Alertable,
Timeout);
} }
/* EOF */ /* EOF */

View file

@ -588,7 +588,7 @@ KeQueryTimeIncrement@0
KeRaiseUserException@4 KeRaiseUserException@4
KeReadStateEvent@4 KeReadStateEvent@4
KeReadStateMutant@4 KeReadStateMutant@4
KeReadStateMutex@4 KeReadStateMutex@4=KeReadStateMutant@4
KeReadStateQueue@4 KeReadStateQueue@4
KeReadStateSemaphore@4 KeReadStateSemaphore@4
KeReadStateTimer@4 KeReadStateTimer@4
@ -645,7 +645,7 @@ KeUpdateSystemTime@8
KeUnstackDetachProcess@4 KeUnstackDetachProcess@4
KeUserModeCallback@20 KeUserModeCallback@20
KeWaitForMultipleObjects@32 KeWaitForMultipleObjects@32
KeWaitForMutexObject@20 KeWaitForMutexObject@20=KeWaitForSingleObject@20
KeWaitForSingleObject@20 KeWaitForSingleObject@20
@KefAcquireSpinLockAtDpcLevel@4 @KefAcquireSpinLockAtDpcLevel@4
@KefReleaseSpinLockFromDpcLevel@4 @KefReleaseSpinLockFromDpcLevel@4