2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/ke/gate.c
5 * PURPOSE: Implements the Gate Dispatcher Object
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
10 /* INCLUDES *****************************************************************/
14 #include <internal/debug.h>
16 /* FUNCTIONS ****************************************************************/
20 KeInitializeGate(PKGATE Gate
)
22 DPRINT("KeInitializeGate(Gate %x)\n", Gate
);
24 /* Initialize the Dispatcher Header */
25 KeInitializeDispatcherHeader(&Gate
->Header
,
27 sizeof(Gate
) / sizeof(ULONG
),
33 KeWaitForGate(PKGATE Gate
,
34 KWAIT_REASON WaitReason
,
35 KPROCESSOR_MODE WaitMode
)
38 PKTHREAD CurrentThread
= KeGetCurrentThread();
39 PKWAIT_BLOCK GateWaitBlock
;
42 DPRINT("KeWaitForGate(Gate %x)\n", Gate
);
46 /* Lock the APC Queue */
47 OldIrql
= KeAcquireDispatcherDatabaseLock();
49 /* Check if it's already signaled */
50 if (Gate
->Header
.SignalState
)
53 Gate
->Header
.SignalState
= 0;
55 /* Unlock the Queue and return */
56 KeReleaseDispatcherDatabaseLock(OldIrql
);
60 /* Setup a Wait Block */
61 GateWaitBlock
= &CurrentThread
->WaitBlock
[0];
62 GateWaitBlock
->Object
= (PVOID
)Gate
;
63 GateWaitBlock
->Thread
= CurrentThread
;
65 /* Set the Thread Wait Data */
66 CurrentThread
->WaitIrql
= OldIrql
;
67 CurrentThread
->GateObject
= Gate
;
69 /* Insert into the Wait List */
70 InsertTailList(&Gate
->Header
.WaitListHead
,
71 &GateWaitBlock
->WaitListEntry
);
73 /* Handle Kernel Queues */
74 if (CurrentThread
->Queue
)
76 DPRINT("Waking Queue\n");
77 KiWakeQueue(CurrentThread
->Queue
);
80 /* Setup the wait information */
81 CurrentThread
->WaitMode
= WaitMode
;
82 CurrentThread
->WaitReason
= WaitReason
;
83 CurrentThread
->WaitTime
= ((PLARGE_INTEGER
)&KeTickCount
)->LowPart
;
84 CurrentThread
->State
= Waiting
;
86 /* Find a new thread to run */
87 DPRINT("Swapping threads\n");
88 Status
= KiSwapThread();
90 /* Check if we were executing an APC */
91 if (Status
!= STATUS_KERNEL_APC
) return;
93 DPRINT("Looping Again\n");
99 KeSignalGateBoostPriority(PKGATE Gate
)
102 PKWAIT_BLOCK WaitBlock
;
104 NTSTATUS WaitStatus
= STATUS_SUCCESS
;
106 DPRINT("KeSignalGateBoostPriority(EveGate %x)\n", Gate
);
108 /* Acquire Dispatcher Database Lock */
109 OldIrql
= KeAcquireDispatcherDatabaseLock();
111 /* Make sure we're not already signaled or that the list is empty */
112 if (Gate
->Header
.SignalState
) goto quit
;
114 /* If our wait list is empty, then signal the event and return */
115 if (IsListEmpty(&Gate
->Header
.WaitListHead
))
117 Gate
->Header
.SignalState
= 1;
122 WaitBlock
= CONTAINING_RECORD(Gate
->Header
.WaitListHead
.Flink
,
126 RemoveEntryList(&WaitBlock
->WaitListEntry
);
128 /* Get the Associated thread */
129 WaitThread
= WaitBlock
->Thread
;
131 /* Increment the Queue's active threads */
132 if (WaitThread
->Queue
)
134 DPRINT("Incrementing Queue's active threads\n");
135 WaitThread
->Queue
->CurrentCount
++;
138 /* Reschedule the Thread */
139 DPRINT("Unblocking the Thread\n");
140 KiUnblockThread(WaitThread
, &WaitStatus
, EVENT_INCREMENT
);
144 /* Release the Dispatcher Database Lock */
145 KeReleaseDispatcherDatabaseLock(OldIrql
);