- 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) || \
((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 {
DISPATCHER_HEADER Header;
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
* PURPOSE: Implements Mutexes and Mutants (that silly davec...)
*
* 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)
* PURPOSE: Implements the Mutant Dispatcher Object
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES *****************************************************************/
@ -23,16 +18,15 @@
* @implemented
*/
VOID
STDCALL
NTAPI
KeInitializeMutant(IN PKMUTANT Mutant,
IN BOOLEAN InitialOwner)
{
PKTHREAD CurrentThread;
KIRQL OldIrql;
DPRINT("KeInitializeMutant: %x\n", Mutant);
/* Check if we have an initial owner */
if (InitialOwner == TRUE)
if (InitialOwner)
{
/* We also need to associate a thread */
CurrentThread = KeGetCurrentThread();
@ -47,7 +41,6 @@ KeInitializeMutant(IN PKMUTANT Mutant,
/* Release Dispatcher Lock */
KiReleaseDispatcherLock(OldIrql);
DPRINT("Mutant with Initial Owner\n");
}
else
{
@ -70,12 +63,10 @@ KeInitializeMutant(IN PKMUTANT Mutant,
* @implemented
*/
VOID
STDCALL
NTAPI
KeInitializeMutex(IN PKMUTEX Mutex,
IN ULONG Level)
{
DPRINT("KeInitializeMutex: %x\n", Mutex);
/* Set up the Dispatcher Header */
KeInitializeDispatcherHeader(&Mutex->Header,
MutantObject,
@ -92,18 +83,18 @@ KeInitializeMutex(IN PKMUTEX Mutex,
* @implemented
*/
LONG
STDCALL
NTAPI
KeReadStateMutant(IN PKMUTANT Mutant)
{
/* Return the Signal State */
return(Mutant->Header.SignalState);
return Mutant->Header.SignalState;
}
/*
* @implemented
*/
LONG
STDCALL
NTAPI
KeReleaseMutant(IN PKMUTANT Mutant,
IN KPRIORITY Increment,
IN BOOLEAN Abandon,
@ -112,7 +103,9 @@ KeReleaseMutant(IN PKMUTANT Mutant,
KIRQL OldIrql;
LONG PreviousState;
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 */
OldIrql = KiAcquireDispatcherLock();
@ -126,8 +119,6 @@ KeReleaseMutant(IN PKMUTANT Mutant,
/* Make sure that the Owner Thread is the current Thread */
if (Mutant->OwnerThread != CurrentThread)
{
DPRINT1("Trying to touch a Mutant that the caller doesn't own!\n");
/* Release the lock */
KiReleaseDispatcherLock(OldIrql);
@ -142,7 +133,6 @@ KeReleaseMutant(IN PKMUTANT Mutant,
else
{
/* It's going to be abandonned */
DPRINT("Abandonning the Mutant\n");
Mutant->Header.SignalState = 1;
Mutant->Abandoned = TRUE;
}
@ -154,43 +144,24 @@ KeReleaseMutant(IN PKMUTANT Mutant,
if (PreviousState <= 0)
{
/* Remove the mutant from the list */
DPRINT("Removing Mutant %p\n", Mutant);
RemoveEntryList(&Mutant->MutantListEntry);
/* Reenable APCs */
DPRINT("Re-enabling APCs\n");
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);
}
}
/* Save if we need to re-enable APCs */
EnableApc = Mutant->ApcDisable;
}
/* Remove the Owning Thread and wake it */
Mutant->OwnerThread = NULL;
/* Check if the Wait List isn't empty */
DPRINT("Checking whether to wake the Mutant\n");
if (!IsListEmpty(&Mutant->Header.WaitListHead))
{
/* Wake the Mutant */
DPRINT("Waking the Mutant\n");
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)
{
/* Release the Lock */
@ -203,6 +174,9 @@ KeReleaseMutant(IN PKMUTANT Mutant,
CurrentThread->WaitIrql = OldIrql;
}
/* Check if we need to re-enable APCs */
if (EnableApc) KeLeaveCriticalRegion();
/* Return the previous state */
return PreviousState;
}
@ -211,10 +185,12 @@ KeReleaseMutant(IN PKMUTANT Mutant,
* @implemented
*/
LONG
STDCALL
NTAPI
KeReleaseMutex(IN PKMUTEX Mutex,
IN BOOLEAN Wait)
{
ASSERT_MUTANT(Mutex);
/* There's no difference at this level between the two */
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
* PURPOSE: Implements kernel semaphores
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
* David Welch (welch@mcmail.com)
* PURPOSE: Implements the Semaphore Dispatcher Object
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES *****************************************************************/
@ -19,13 +18,11 @@
* @implemented
*/
VOID
STDCALL
KeInitializeSemaphore(PKSEMAPHORE Semaphore,
LONG Count,
LONG Limit)
NTAPI
KeInitializeSemaphore(IN PKSEMAPHORE Semaphore,
IN LONG Count,
IN LONG Limit)
{
DPRINT("KeInitializeSemaphore Sem: %x\n", Semaphore);
/* Simply Initialize the Header */
KeInitializeDispatcherHeader(&Semaphore->Header,
SemaphoreObject,
@ -40,51 +37,30 @@ KeInitializeSemaphore(PKSEMAPHORE Semaphore,
* @implemented
*/
LONG
STDCALL
KeReadStateSemaphore(PKSEMAPHORE Semaphore)
NTAPI
KeReadStateSemaphore(IN PKSEMAPHORE Semaphore)
{
ASSERT_SEMAPHORE(Semaphore);
/* Just return the Signal State */
return Semaphore->Header.SignalState;
}
/*
* @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
STDCALL
KeReleaseSemaphore(PKSEMAPHORE Semaphore,
KPRIORITY Increment,
LONG Adjustment,
BOOLEAN Wait)
NTAPI
KeReleaseSemaphore(IN PKSEMAPHORE Semaphore,
IN KPRIORITY Increment,
IN LONG Adjustment,
IN BOOLEAN Wait)
{
LONG InitialState, State;
KIRQL OldIrql;
PKTHREAD CurrentThread;
DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, Wait %d)\n",
Semaphore,
Increment,
Adjustment,
Wait);
ASSERT_SEMAPHORE(Semaphore);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Lock the Dispatcher Database */
OldIrql = KiAcquireDispatcherLock();
@ -111,7 +87,7 @@ KeReleaseSemaphore(PKSEMAPHORE Semaphore,
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)
{
/* Release the Lock */