2005-04-13 01:12:08 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Kernel
|
2006-07-13 04:20:18 +00:00
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
2005-04-13 01:12:08 +00:00
|
|
|
* FILE: ntoskrnl/ke/gate.c
|
|
|
|
* PURPOSE: Implements the Gate Dispatcher Object
|
2006-07-13 04:20:18 +00:00
|
|
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
2005-04-13 01:12:08 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
|
|
|
#include <ntoskrnl.h>
|
|
|
|
#define NDEBUG
|
2008-08-30 16:31:06 +00:00
|
|
|
#include <debug.h>
|
2005-04-13 01:12:08 +00:00
|
|
|
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
|
2005-05-09 01:38:29 +00:00
|
|
|
VOID
|
2005-04-13 01:12:08 +00:00
|
|
|
FASTCALL
|
2006-07-13 04:20:18 +00:00
|
|
|
KeInitializeGate(IN PKGATE Gate)
|
2005-04-13 01:12:08 +00:00
|
|
|
{
|
|
|
|
/* Initialize the Dispatcher Header */
|
2011-10-07 16:18:52 +00:00
|
|
|
Gate->Header.Type = GateObject;
|
|
|
|
Gate->Header.Signalling = FALSE;
|
|
|
|
Gate->Header.Size = sizeof(KGATE) / sizeof(ULONG);
|
|
|
|
Gate->Header.SignalState = 0;
|
|
|
|
InitializeListHead(&(Gate->Header.WaitListHead));
|
2005-04-13 01:12:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FASTCALL
|
2006-07-11 15:36:44 +00:00
|
|
|
KeWaitForGate(IN PKGATE Gate,
|
|
|
|
IN KWAIT_REASON WaitReason,
|
|
|
|
IN KPROCESSOR_MODE WaitMode)
|
2005-04-13 01:12:08 +00:00
|
|
|
{
|
2006-09-10 18:26:50 +00:00
|
|
|
KLOCK_QUEUE_HANDLE ApcLock;
|
2006-09-14 05:53:51 +00:00
|
|
|
PKTHREAD Thread = KeGetCurrentThread();
|
2005-04-13 01:12:08 +00:00
|
|
|
PKWAIT_BLOCK GateWaitBlock;
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
LONG_PTR Status;
|
2006-09-14 05:53:51 +00:00
|
|
|
PKQUEUE Queue;
|
2006-07-11 15:36:44 +00:00
|
|
|
ASSERT_GATE(Gate);
|
|
|
|
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-07-11 15:36:44 +00:00
|
|
|
/* Start wait loop */
|
2005-05-09 01:38:29 +00:00
|
|
|
do
|
2005-04-13 01:12:08 +00:00
|
|
|
{
|
2006-09-10 18:26:50 +00:00
|
|
|
/* Acquire the APC lock */
|
2019-12-30 14:34:38 +00:00
|
|
|
KiAcquireApcLockRaiseToSynch(Thread, &ApcLock);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-07-11 15:36:44 +00:00
|
|
|
/* Check if a kernel APC is pending and we're below APC_LEVEL */
|
2006-09-14 05:53:51 +00:00
|
|
|
if ((Thread->ApcState.KernelApcPending) &&
|
|
|
|
!(Thread->SpecialApcDisable) &&
|
2006-09-10 18:26:50 +00:00
|
|
|
(ApcLock.OldIrql < APC_LEVEL))
|
2006-07-11 15:36:44 +00:00
|
|
|
{
|
2006-09-10 18:26:50 +00:00
|
|
|
/* Release the lock, this will fire the APC */
|
|
|
|
KiReleaseApcLock(&ApcLock);
|
2005-04-13 01:12:08 +00:00
|
|
|
}
|
2006-07-11 15:36:44 +00:00
|
|
|
else
|
2005-04-13 01:12:08 +00:00
|
|
|
{
|
2006-09-14 05:53:51 +00:00
|
|
|
/* Check if we have a queue and lock the dispatcher if so */
|
|
|
|
Queue = Thread->Queue;
|
2019-12-30 14:34:38 +00:00
|
|
|
if (Queue) KiAcquireDispatcherLockAtSynchLevel();
|
2006-09-14 05:53:51 +00:00
|
|
|
|
|
|
|
/* Lock the thread */
|
|
|
|
KiAcquireThreadLock(Thread);
|
|
|
|
|
|
|
|
/* Lock the gate */
|
|
|
|
KiAcquireDispatcherObject(&Gate->Header);
|
|
|
|
|
2006-07-11 15:36:44 +00:00
|
|
|
/* Check if it's already signaled */
|
|
|
|
if (Gate->Header.SignalState)
|
|
|
|
{
|
|
|
|
/* Unsignal it */
|
|
|
|
Gate->Header.SignalState = 0;
|
|
|
|
|
2006-09-14 05:53:51 +00:00
|
|
|
/* Release the gate and thread locks */
|
|
|
|
KiReleaseDispatcherObject(&Gate->Header);
|
|
|
|
KiReleaseThreadLock(Thread);
|
|
|
|
|
2007-03-11 00:42:18 +00:00
|
|
|
/* Release the gate lock */
|
2019-12-30 14:34:38 +00:00
|
|
|
if (Queue) KiReleaseDispatcherLockFromSynchLevel();
|
2007-03-11 00:42:18 +00:00
|
|
|
|
2006-09-10 18:26:50 +00:00
|
|
|
/* Release the APC lock and return */
|
|
|
|
KiReleaseApcLock(&ApcLock);
|
2007-01-15 21:34:36 +00:00
|
|
|
break;
|
2006-07-11 15:36:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Setup a Wait Block */
|
2006-09-14 05:53:51 +00:00
|
|
|
GateWaitBlock = &Thread->WaitBlock[0];
|
2006-07-11 15:36:44 +00:00
|
|
|
GateWaitBlock->Object = (PVOID)Gate;
|
2006-09-14 05:53:51 +00:00
|
|
|
GateWaitBlock->Thread = Thread;
|
2006-07-11 15:36:44 +00:00
|
|
|
|
|
|
|
/* Set the Thread Wait Data */
|
2006-09-14 05:53:51 +00:00
|
|
|
Thread->WaitMode = WaitMode;
|
|
|
|
Thread->WaitReason = WaitReason;
|
|
|
|
Thread->WaitIrql = ApcLock.OldIrql;
|
|
|
|
Thread->State = GateWait;
|
|
|
|
Thread->GateObject = Gate;
|
2006-07-11 15:36:44 +00:00
|
|
|
|
|
|
|
/* Insert into the Wait List */
|
|
|
|
InsertTailList(&Gate->Header.WaitListHead,
|
|
|
|
&GateWaitBlock->WaitListEntry);
|
|
|
|
|
2006-09-14 05:53:51 +00:00
|
|
|
/* Release the gate lock */
|
|
|
|
KiReleaseDispatcherObject(&Gate->Header);
|
|
|
|
|
|
|
|
/* Set swap busy */
|
|
|
|
KiSetThreadSwapBusy(Thread);
|
|
|
|
|
|
|
|
/* Release the thread lock */
|
|
|
|
KiReleaseThreadLock(Thread);
|
|
|
|
|
|
|
|
/* Check if we had a queue */
|
|
|
|
if (Queue)
|
|
|
|
{
|
|
|
|
/* Wake it up */
|
2006-09-14 15:48:02 +00:00
|
|
|
KiActivateWaiterQueue(Queue);
|
2006-09-14 05:53:51 +00:00
|
|
|
|
|
|
|
/* Release the dispatcher lock */
|
2019-12-30 14:34:38 +00:00
|
|
|
KiReleaseDispatcherLockFromSynchLevel();
|
2006-09-14 05:53:51 +00:00
|
|
|
}
|
2006-07-11 15:36:44 +00:00
|
|
|
|
2006-09-10 18:26:50 +00:00
|
|
|
/* Release the APC lock but stay at DPC level */
|
2019-12-30 14:34:38 +00:00
|
|
|
KiReleaseApcLockFromSynchLevel(&ApcLock);
|
2006-09-10 18:26:50 +00:00
|
|
|
|
2006-07-11 15:36:44 +00:00
|
|
|
/* Find a new thread to run */
|
2006-09-14 05:53:51 +00:00
|
|
|
Status = KiSwapThread(Thread, KeGetCurrentPrcb());
|
2006-07-11 15:36:44 +00:00
|
|
|
|
2007-01-15 21:34:36 +00:00
|
|
|
/* Make sure we weren't executing an APC */
|
|
|
|
if (Status == STATUS_SUCCESS) return;
|
2005-04-13 01:12:08 +00:00
|
|
|
}
|
|
|
|
} while (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FASTCALL
|
2006-07-13 04:20:18 +00:00
|
|
|
KeSignalGateBoostPriority(IN PKGATE Gate)
|
2005-04-13 01:12:08 +00:00
|
|
|
{
|
|
|
|
PKTHREAD WaitThread;
|
|
|
|
PKWAIT_BLOCK WaitBlock;
|
|
|
|
KIRQL OldIrql;
|
2006-07-11 15:36:44 +00:00
|
|
|
ASSERT_GATE(Gate);
|
|
|
|
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-09-14 05:53:51 +00:00
|
|
|
/* Start entry loop */
|
|
|
|
for (;;)
|
2006-09-10 18:26:50 +00:00
|
|
|
{
|
2006-09-14 05:53:51 +00:00
|
|
|
/* Raise to synch level */
|
|
|
|
OldIrql = KeRaiseIrqlToSynchLevel();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-09-14 05:53:51 +00:00
|
|
|
/* Lock the gate */
|
|
|
|
KiAcquireDispatcherObject(&Gate->Header);
|
|
|
|
|
|
|
|
/* Make sure we're not already signaled or that the list is empty */
|
2007-01-15 21:34:36 +00:00
|
|
|
if (Gate->Header.SignalState) break;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-09-14 05:53:51 +00:00
|
|
|
/* Check if our wait list is empty */
|
|
|
|
if (IsListEmpty(&Gate->Header.WaitListHead))
|
|
|
|
{
|
|
|
|
/* It is, so signal the event */
|
|
|
|
Gate->Header.SignalState = 1;
|
2007-01-15 21:34:36 +00:00
|
|
|
break;
|
2006-09-14 05:53:51 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Get WaitBlock */
|
|
|
|
WaitBlock = CONTAINING_RECORD(Gate->Header.WaitListHead.Flink,
|
|
|
|
KWAIT_BLOCK,
|
|
|
|
WaitListEntry);
|
|
|
|
|
|
|
|
/* Get the Associated thread */
|
|
|
|
WaitThread = WaitBlock->Thread;
|
|
|
|
|
|
|
|
/* Check to see if the waiting thread is locked */
|
2007-04-11 08:43:34 +00:00
|
|
|
if (KiTryThreadLock(WaitThread))
|
2006-09-14 05:53:51 +00:00
|
|
|
{
|
|
|
|
/* Unlock the gate */
|
|
|
|
KiReleaseDispatcherObject(&Gate->Header);
|
|
|
|
|
|
|
|
/* Lower IRQL and loop again */
|
|
|
|
KeLowerIrql(OldIrql);
|
|
|
|
continue;
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-09-14 05:53:51 +00:00
|
|
|
/* Remove it */
|
|
|
|
RemoveEntryList(&WaitBlock->WaitListEntry);
|
2005-04-13 01:12:08 +00:00
|
|
|
|
2006-09-14 05:53:51 +00:00
|
|
|
/* Clear wait status */
|
2007-01-15 21:34:36 +00:00
|
|
|
WaitThread->WaitStatus = STATUS_SUCCESS;
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-09-14 05:53:51 +00:00
|
|
|
/* Set state and CPU */
|
|
|
|
WaitThread->State = DeferredReady;
|
|
|
|
WaitThread->DeferredProcessor = KeGetCurrentPrcb()->Number;
|
|
|
|
|
|
|
|
/* Release the gate lock */
|
|
|
|
KiReleaseDispatcherObject(&Gate->Header);
|
|
|
|
|
|
|
|
/* Release the thread lock */
|
|
|
|
KiReleaseThreadLock(WaitThread);
|
|
|
|
|
|
|
|
/* FIXME: Boosting */
|
|
|
|
|
|
|
|
/* Check if we have a queue */
|
|
|
|
if (WaitThread->Queue)
|
|
|
|
{
|
|
|
|
/* Acquire the dispatcher lock */
|
2019-12-30 14:34:38 +00:00
|
|
|
KiAcquireDispatcherLockAtSynchLevel();
|
2006-09-14 05:53:51 +00:00
|
|
|
|
|
|
|
/* Check if we still have one */
|
|
|
|
if (WaitThread->Queue)
|
|
|
|
{
|
|
|
|
/* Increment active threads */
|
|
|
|
WaitThread->Queue->CurrentCount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Release lock */
|
2019-12-30 14:34:38 +00:00
|
|
|
KiReleaseDispatcherLockFromSynchLevel();
|
2006-09-14 05:53:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Make the thread ready */
|
|
|
|
KiReadyThread(WaitThread);
|
|
|
|
|
|
|
|
/* Exit the dispatcher */
|
|
|
|
KiExitDispatcher(OldIrql);
|
2007-01-15 21:34:36 +00:00
|
|
|
return;
|
2006-09-14 05:53:51 +00:00
|
|
|
}
|
2006-07-11 15:36:44 +00:00
|
|
|
}
|
2005-04-13 01:12:08 +00:00
|
|
|
|
2006-09-14 05:53:51 +00:00
|
|
|
/* If we got here, then there's no rescheduling. */
|
|
|
|
KiReleaseDispatcherObject(&Gate->Header);
|
|
|
|
KeLowerIrql(OldIrql);
|
2005-04-13 01:12:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|