mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Kernel Gates. Ultra-lightweight and exclusive Wait Objects used in NT 5.2+ as high-speed events. Code is untested, so it's not added to the build until I'm back in May.
svn path=/trunk/; revision=14603
This commit is contained in:
parent
b9df1e262e
commit
3b6c6f0a94
3 changed files with 158 additions and 1 deletions
|
@ -88,6 +88,11 @@ typedef struct _KQUEUE
|
|||
LIST_ENTRY ThreadListHead;
|
||||
} KQUEUE, *PKQUEUE;
|
||||
|
||||
typedef struct _KGATE
|
||||
{
|
||||
DISPATCHER_HEADER Header;
|
||||
} KGATE, *PKGATE;
|
||||
|
||||
struct _KDPC;
|
||||
|
||||
typedef struct _KTIMER
|
||||
|
|
|
@ -85,7 +85,10 @@ typedef struct _KTHREAD
|
|||
CHAR WaitMode; /* 55 */
|
||||
UCHAR WaitNext; /* 56 */
|
||||
UCHAR WaitReason; /* 57 */
|
||||
PKWAIT_BLOCK WaitBlockList; /* 58 */
|
||||
union { /* 58 */
|
||||
PKWAIT_BLOCK WaitBlockList; /* 58 */
|
||||
PKGATE GateObject; /* 58 */
|
||||
}; /* 58 */
|
||||
LIST_ENTRY WaitListEntry; /* 5C */
|
||||
ULONG WaitTime; /* 64 */
|
||||
CHAR BasePriority; /* 68 */
|
||||
|
|
149
reactos/ntoskrnl/ke/gate.c
Normal file
149
reactos/ntoskrnl/ke/gate.c
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Kernel
|
||||
* FILE: ntoskrnl/ke/gate.c
|
||||
* PURPOSE: Implements the Gate Dispatcher Object
|
||||
*
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
KeInitializeGate(PKGATE Gate)
|
||||
{
|
||||
DPRINT1("KeInitializeGate(Gate %x)\n", Gate);
|
||||
|
||||
/* Initialize the Dispatcher Header */
|
||||
KeInitializeDispatcherHeader(&Gate->Header,
|
||||
GateObject,
|
||||
sizeof(Gate) / sizeof(ULONG),
|
||||
0);
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
KeWaitForGate(PKGATE Gate,
|
||||
KWAIT_REASON WaitReason,
|
||||
KPROCESSOR_MODE WaitMode)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PKTHREAD CurrentThread = KeGetCurrentThread();
|
||||
PKWAIT_BLOCK GateWaitBlock;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT1("KeWaitForGate(Gate %x)\n", Gate);
|
||||
|
||||
do
|
||||
{
|
||||
/* Lock the APC Queue */
|
||||
KeAcquireSpinLock(&CurrentThread->ApcQueueLock, &OldIrql);
|
||||
|
||||
/* Check if it's already signaled */
|
||||
if (!Gate->Header.SignalState)
|
||||
{
|
||||
/* Unsignal it */
|
||||
Gate->Header.SignalState = 0;
|
||||
|
||||
/* Unlock the Queue and return */
|
||||
KeReleaseSpinLock(&CurrentThread->ApcQueueLock, OldIrql);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Setup a Wait Block */
|
||||
GateWaitBlock = &CurrentThread->WaitBlock[0];
|
||||
GateWaitBlock->Object = (PVOID)Gate;
|
||||
GateWaitBlock->Thread = CurrentThread;
|
||||
|
||||
/* Set the Thread Wait Data */
|
||||
CurrentThread->WaitReason = WaitReason;
|
||||
CurrentThread->WaitMode = WaitMode;
|
||||
CurrentThread->WaitIrql = OldIrql;
|
||||
CurrentThread->GateObject = Gate;
|
||||
|
||||
/* Insert into the Wait List */
|
||||
InsertTailList(&Gate->Header.WaitListHead, &GateWaitBlock->WaitListEntry);
|
||||
|
||||
/* Handle Kernel Queues */
|
||||
if (CurrentThread->Queue)
|
||||
{
|
||||
DPRINT1("Waking Queue\n");
|
||||
KiWakeQueue(CurrentThread->Queue);
|
||||
}
|
||||
|
||||
/* Unlock the Queue*/
|
||||
KeReleaseSpinLock(&CurrentThread->ApcQueueLock, OldIrql);
|
||||
|
||||
/* Block the Thread */
|
||||
DPRINT1("Blocking the Thread: %x\n", CurrentThread);
|
||||
KiBlockThread(&Status,
|
||||
CurrentThread->Alertable,
|
||||
WaitMode,
|
||||
WaitReason);
|
||||
|
||||
/* Check if we were executing an APC */
|
||||
if (Status != STATUS_KERNEL_APC) return;
|
||||
|
||||
DPRINT1("Looping Again\n");
|
||||
} while (TRUE);
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
KeSignalGateBoostPriority(PKGATE Gate)
|
||||
{
|
||||
PKTHREAD WaitThread;
|
||||
PKWAIT_BLOCK WaitBlock;
|
||||
KIRQL OldIrql;
|
||||
NTSTATUS WaitStatus = STATUS_SUCCESS;
|
||||
|
||||
DPRINT1("KeSignalGateBoostPriority(EveGate %x)\n", Gate);
|
||||
|
||||
/* Acquire Dispatcher Database Lock */
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
/* Make sure we're not already signaled or that the list is empty */
|
||||
if (Gate->Header.SignalState) goto quit;
|
||||
|
||||
/* If our wait list is empty, then signal the event and return */
|
||||
if (IsListEmpty(&Gate->Header.WaitListHead))
|
||||
{
|
||||
Gate->Header.SignalState = 1;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
/* Get WaitBlock */
|
||||
WaitBlock = CONTAINING_RECORD(Gate->Header.WaitListHead.Flink,
|
||||
KWAIT_BLOCK,
|
||||
WaitListEntry);
|
||||
/* Remove it */
|
||||
RemoveEntryList(&WaitBlock->WaitListEntry);
|
||||
|
||||
/* Get the Associated thread */
|
||||
WaitThread = WaitBlock->Thread;
|
||||
|
||||
/* Increment the Queue's active threads */
|
||||
if (WaitThread->Queue)
|
||||
{
|
||||
DPRINT1("Incrementing Queue's active threads\n");
|
||||
WaitThread->Queue->CurrentCount++;
|
||||
}
|
||||
|
||||
/* Reschedule the Thread */
|
||||
DPRINT1("Unblocking the Thread\n");
|
||||
KiUnblockThread(WaitThread, &WaitStatus, EVENT_INCREMENT);
|
||||
return;
|
||||
|
||||
quit:
|
||||
/* Release the Dispatcher Database Lock */
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Reference in a new issue