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;
|
LIST_ENTRY ThreadListHead;
|
||||||
} KQUEUE, *PKQUEUE;
|
} KQUEUE, *PKQUEUE;
|
||||||
|
|
||||||
|
typedef struct _KGATE
|
||||||
|
{
|
||||||
|
DISPATCHER_HEADER Header;
|
||||||
|
} KGATE, *PKGATE;
|
||||||
|
|
||||||
struct _KDPC;
|
struct _KDPC;
|
||||||
|
|
||||||
typedef struct _KTIMER
|
typedef struct _KTIMER
|
||||||
|
|
|
@ -85,7 +85,10 @@ typedef struct _KTHREAD
|
||||||
CHAR WaitMode; /* 55 */
|
CHAR WaitMode; /* 55 */
|
||||||
UCHAR WaitNext; /* 56 */
|
UCHAR WaitNext; /* 56 */
|
||||||
UCHAR WaitReason; /* 57 */
|
UCHAR WaitReason; /* 57 */
|
||||||
PKWAIT_BLOCK WaitBlockList; /* 58 */
|
union { /* 58 */
|
||||||
|
PKWAIT_BLOCK WaitBlockList; /* 58 */
|
||||||
|
PKGATE GateObject; /* 58 */
|
||||||
|
}; /* 58 */
|
||||||
LIST_ENTRY WaitListEntry; /* 5C */
|
LIST_ENTRY WaitListEntry; /* 5C */
|
||||||
ULONG WaitTime; /* 64 */
|
ULONG WaitTime; /* 64 */
|
||||||
CHAR BasePriority; /* 68 */
|
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