- Add ASSERT_MUTANT and ASSERT_SEMAPHORE to our DDK.

- Cleanup mutex.c and sem.c. No real code changes, just add ASSERTs, STDCALL->NTAPI, IN/OUT decoration.
- One change though, in KeReleaseMutant, use KeLeaveCriticalRegion instead of manually writing down the code, it's more readable this way.

svn path=/trunk/; revision=24039
This commit is contained in:
Alex Ionescu 2006-09-10 18:47:53 +00:00
parent da15ddafc8
commit b5c8cf43e7
3 changed files with 48 additions and 90 deletions

View file

@ -1226,6 +1226,12 @@ typedef struct _KTIMER {
ASSERT(((E)->Header.Type == TimerNotificationObject) || \ ASSERT(((E)->Header.Type == TimerNotificationObject) || \
((E)->Header.Type == TimerSynchronizationObject)) ((E)->Header.Type == TimerSynchronizationObject))
#define ASSERT_MUTANT(E) \
ASSERT((E)->Header.Type == MutantObject)
#define ASSERT_SEMAPHORE(E) \
ASSERT((E)->Header.Type == SemaphoreObject)
typedef struct _KMUTANT { typedef struct _KMUTANT {
DISPATCHER_HEADER Header; DISPATCHER_HEADER Header;
LIST_ENTRY MutantListEntry; LIST_ENTRY MutantListEntry;

View file

@ -1,14 +1,9 @@
/* /*
* COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Kernel
* PROJECT: ReactOS kernel * LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/ke/mutex.c * FILE: ntoskrnl/ke/mutex.c
* PURPOSE: Implements Mutexes and Mutants (that silly davec...) * PURPOSE: Implements the Mutant Dispatcher Object
* * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* PROGRAMMERS:
* Alex Ionescu (alex@relsoft.net) - Reorganized/commented some of the code.
* Simplified some functions, fixed some return values and
* corrected some minor bugs, added debug output.
* David Welch (welch@mcmail.com)
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
@ -23,16 +18,15 @@
* @implemented * @implemented
*/ */
VOID VOID
STDCALL NTAPI
KeInitializeMutant(IN PKMUTANT Mutant, KeInitializeMutant(IN PKMUTANT Mutant,
IN BOOLEAN InitialOwner) IN BOOLEAN InitialOwner)
{ {
PKTHREAD CurrentThread; PKTHREAD CurrentThread;
KIRQL OldIrql; KIRQL OldIrql;
DPRINT("KeInitializeMutant: %x\n", Mutant);
/* Check if we have an initial owner */ /* Check if we have an initial owner */
if (InitialOwner == TRUE) if (InitialOwner)
{ {
/* We also need to associate a thread */ /* We also need to associate a thread */
CurrentThread = KeGetCurrentThread(); CurrentThread = KeGetCurrentThread();
@ -47,7 +41,6 @@ KeInitializeMutant(IN PKMUTANT Mutant,
/* Release Dispatcher Lock */ /* Release Dispatcher Lock */
KiReleaseDispatcherLock(OldIrql); KiReleaseDispatcherLock(OldIrql);
DPRINT("Mutant with Initial Owner\n");
} }
else else
{ {
@ -70,12 +63,10 @@ KeInitializeMutant(IN PKMUTANT Mutant,
* @implemented * @implemented
*/ */
VOID VOID
STDCALL NTAPI
KeInitializeMutex(IN PKMUTEX Mutex, KeInitializeMutex(IN PKMUTEX Mutex,
IN ULONG Level) IN ULONG Level)
{ {
DPRINT("KeInitializeMutex: %x\n", Mutex);
/* Set up the Dispatcher Header */ /* Set up the Dispatcher Header */
KeInitializeDispatcherHeader(&Mutex->Header, KeInitializeDispatcherHeader(&Mutex->Header,
MutantObject, MutantObject,
@ -92,18 +83,18 @@ KeInitializeMutex(IN PKMUTEX Mutex,
* @implemented * @implemented
*/ */
LONG LONG
STDCALL NTAPI
KeReadStateMutant(IN PKMUTANT Mutant) KeReadStateMutant(IN PKMUTANT Mutant)
{ {
/* Return the Signal State */ /* Return the Signal State */
return(Mutant->Header.SignalState); return Mutant->Header.SignalState;
} }
/* /*
* @implemented * @implemented
*/ */
LONG LONG
STDCALL NTAPI
KeReleaseMutant(IN PKMUTANT Mutant, KeReleaseMutant(IN PKMUTANT Mutant,
IN KPRIORITY Increment, IN KPRIORITY Increment,
IN BOOLEAN Abandon, IN BOOLEAN Abandon,
@ -112,7 +103,9 @@ KeReleaseMutant(IN PKMUTANT Mutant,
KIRQL OldIrql; KIRQL OldIrql;
LONG PreviousState; LONG PreviousState;
PKTHREAD CurrentThread = KeGetCurrentThread(); PKTHREAD CurrentThread = KeGetCurrentThread();
DPRINT("KeReleaseMutant: %x\n", Mutant); BOOLEAN EnableApc = FALSE;
ASSERT_MUTANT(Mutant);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Lock the Dispatcher Database */ /* Lock the Dispatcher Database */
OldIrql = KiAcquireDispatcherLock(); OldIrql = KiAcquireDispatcherLock();
@ -126,8 +119,6 @@ KeReleaseMutant(IN PKMUTANT Mutant,
/* 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 */ /* Release the lock */
KiReleaseDispatcherLock(OldIrql); KiReleaseDispatcherLock(OldIrql);
@ -142,7 +133,6 @@ KeReleaseMutant(IN PKMUTANT Mutant,
else else
{ {
/* It's going to be abandonned */ /* It's going to be abandonned */
DPRINT("Abandonning the Mutant\n");
Mutant->Header.SignalState = 1; Mutant->Header.SignalState = 1;
Mutant->Abandoned = TRUE; Mutant->Abandoned = TRUE;
} }
@ -154,43 +144,24 @@ KeReleaseMutant(IN PKMUTANT Mutant,
if (PreviousState <= 0) if (PreviousState <= 0)
{ {
/* Remove the mutant from the list */ /* Remove the mutant from the list */
DPRINT("Removing Mutant %p\n", Mutant);
RemoveEntryList(&Mutant->MutantListEntry); RemoveEntryList(&Mutant->MutantListEntry);
/* Reenable APCs */ /* Save if we need to re-enable APCs */
DPRINT("Re-enabling APCs\n"); EnableApc = Mutant->ApcDisable;
CurrentThread->KernelApcDisable += Mutant->ApcDisable;
/* Check if the thread has APCs enabled */
if (!CurrentThread->KernelApcDisable)
{
/* Check if any are pending */
if (!IsListEmpty(&CurrentThread->ApcState.ApcListHead[KernelMode]))
{
/* Set Kernel APC Pending */
CurrentThread->ApcState.KernelApcPending = TRUE;
/* Request the Interrupt */
DPRINT("Requesting APC Interupt\n");
HalRequestSoftwareInterrupt(APC_LEVEL);
}
}
} }
/* Remove the Owning Thread and wake it */ /* Remove the Owning Thread and wake it */
Mutant->OwnerThread = NULL; Mutant->OwnerThread = NULL;
/* Check if the Wait List isn't empty */ /* Check if the Wait List isn't empty */
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");
KiWaitTest(&Mutant->Header, Increment); KiWaitTest(&Mutant->Header, Increment);
} }
} }
/* If the Wait is true, then return with a Wait and don't unlock the Dispatcher Database */ /* Check if the caller wants to wait after this release */
if (Wait == FALSE) if (Wait == FALSE)
{ {
/* Release the Lock */ /* Release the Lock */
@ -203,6 +174,9 @@ KeReleaseMutant(IN PKMUTANT Mutant,
CurrentThread->WaitIrql = OldIrql; CurrentThread->WaitIrql = OldIrql;
} }
/* Check if we need to re-enable APCs */
if (EnableApc) KeLeaveCriticalRegion();
/* Return the previous state */ /* Return the previous state */
return PreviousState; return PreviousState;
} }
@ -211,10 +185,12 @@ KeReleaseMutant(IN PKMUTANT Mutant,
* @implemented * @implemented
*/ */
LONG LONG
STDCALL NTAPI
KeReleaseMutex(IN PKMUTEX Mutex, KeReleaseMutex(IN PKMUTEX Mutex,
IN BOOLEAN Wait) IN BOOLEAN Wait)
{ {
ASSERT_MUTANT(Mutex);
/* There's no difference at this level between the two */ /* There's no difference at this level between the two */
return KeReleaseMutant(Mutex, 1, FALSE, Wait); return KeReleaseMutant(Mutex, 1, FALSE, Wait);
} }

View file

@ -1,10 +1,9 @@
/* /*
* COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Kernel
* PROJECT: ReactOS kernel * LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/ke/sem.c * FILE: ntoskrnl/ke/sem.c
* PURPOSE: Implements kernel semaphores * PURPOSE: Implements the Semaphore Dispatcher Object
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* David Welch (welch@mcmail.com)
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
@ -19,13 +18,11 @@
* @implemented * @implemented
*/ */
VOID VOID
STDCALL NTAPI
KeInitializeSemaphore(PKSEMAPHORE Semaphore, KeInitializeSemaphore(IN PKSEMAPHORE Semaphore,
LONG Count, IN LONG Count,
LONG Limit) IN LONG Limit)
{ {
DPRINT("KeInitializeSemaphore Sem: %x\n", Semaphore);
/* Simply Initialize the Header */ /* Simply Initialize the Header */
KeInitializeDispatcherHeader(&Semaphore->Header, KeInitializeDispatcherHeader(&Semaphore->Header,
SemaphoreObject, SemaphoreObject,
@ -40,51 +37,30 @@ KeInitializeSemaphore(PKSEMAPHORE Semaphore,
* @implemented * @implemented
*/ */
LONG LONG
STDCALL NTAPI
KeReadStateSemaphore(PKSEMAPHORE Semaphore) KeReadStateSemaphore(IN PKSEMAPHORE Semaphore)
{ {
ASSERT_SEMAPHORE(Semaphore);
/* Just return the Signal State */ /* Just return the Signal State */
return Semaphore->Header.SignalState; return Semaphore->Header.SignalState;
} }
/* /*
* @implemented * @implemented
*
* FUNCTION: KeReleaseSemaphore releases a given semaphore object. This
* routine supplies a runtime priority boost for waiting threads. If this
* call sets the semaphore to the Signaled state, the semaphore count is
* augmented by the given value. The caller can also specify whether it
* will call one of the KeWaitXXX routines as soon as KeReleaseSemaphore
* returns control.
* ARGUMENTS:
* Semaphore = Points to an initialized semaphore object for which the
* caller provides the storage.
* Increment = Specifies the priority increment to be applied if
* releasing the semaphore causes a wait to be
* satisfied.
* Adjustment = Specifies a value to be added to the current semaphore
* count. This value must be positive
* Wait = Specifies whether the call to KeReleaseSemaphore is to be
* followed immediately by a call to one of the KeWaitXXX.
* RETURNS: If the return value is zero, the previous state of the semaphore
* object is Not-Signaled.
*/ */
LONG LONG
STDCALL NTAPI
KeReleaseSemaphore(PKSEMAPHORE Semaphore, KeReleaseSemaphore(IN PKSEMAPHORE Semaphore,
KPRIORITY Increment, IN KPRIORITY Increment,
LONG Adjustment, IN LONG Adjustment,
BOOLEAN Wait) IN BOOLEAN Wait)
{ {
LONG InitialState, State; LONG InitialState, State;
KIRQL OldIrql; KIRQL OldIrql;
PKTHREAD CurrentThread; PKTHREAD CurrentThread;
ASSERT_SEMAPHORE(Semaphore);
DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, Wait %d)\n", ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
Semaphore,
Increment,
Adjustment,
Wait);
/* Lock the Dispatcher Database */ /* Lock the Dispatcher Database */
OldIrql = KiAcquireDispatcherLock(); OldIrql = KiAcquireDispatcherLock();
@ -111,7 +87,7 @@ KeReleaseSemaphore(PKSEMAPHORE Semaphore,
KiWaitTest(&Semaphore->Header, Increment); KiWaitTest(&Semaphore->Header, Increment);
} }
/* If the Wait is true, then return with a Wait and don't unlock the Dispatcher Database */ /* Check if the caller wants to wait after this release */
if (Wait == FALSE) if (Wait == FALSE)
{ {
/* Release the Lock */ /* Release the Lock */