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
->WaitReason
= WaitReason
;
67 CurrentThread
->WaitMode
= WaitMode
;
68 CurrentThread
->WaitIrql
= OldIrql
;
69 CurrentThread
->GateObject
= Gate
;
71 /* Insert into the Wait List */
72 InsertTailList(&Gate
->Header
.WaitListHead
, &GateWaitBlock
->WaitListEntry
);
74 /* Handle Kernel Queues */
75 if (CurrentThread
->Queue
)
77 DPRINT("Waking Queue\n");
78 KiWakeQueue(CurrentThread
->Queue
);
81 /* Block the Thread */
82 DPRINT("Blocking the Thread: %x\n", CurrentThread
);
83 KiBlockThread(&Status
,
84 CurrentThread
->Alertable
,
88 /* Check if we were executing an APC */
89 if (Status
!= STATUS_KERNEL_APC
) return;
91 DPRINT("Looping Again\n");
97 KeSignalGateBoostPriority(PKGATE Gate
)
100 PKWAIT_BLOCK WaitBlock
;
102 NTSTATUS WaitStatus
= STATUS_SUCCESS
;
104 DPRINT("KeSignalGateBoostPriority(EveGate %x)\n", Gate
);
106 /* Acquire Dispatcher Database Lock */
107 OldIrql
= KeAcquireDispatcherDatabaseLock();
109 /* Make sure we're not already signaled or that the list is empty */
110 if (Gate
->Header
.SignalState
) goto quit
;
112 /* If our wait list is empty, then signal the event and return */
113 if (IsListEmpty(&Gate
->Header
.WaitListHead
))
115 Gate
->Header
.SignalState
= 1;
120 WaitBlock
= CONTAINING_RECORD(Gate
->Header
.WaitListHead
.Flink
,
124 RemoveEntryList(&WaitBlock
->WaitListEntry
);
126 /* Get the Associated thread */
127 WaitThread
= WaitBlock
->Thread
;
129 /* Increment the Queue's active threads */
130 if (WaitThread
->Queue
)
132 DPRINT("Incrementing Queue's active threads\n");
133 WaitThread
->Queue
->CurrentCount
++;
136 /* Reschedule the Thread */
137 DPRINT("Unblocking the Thread\n");
138 KiUnblockThread(WaitThread
, &WaitStatus
, EVENT_INCREMENT
);
142 /* Release the Dispatcher Database Lock */
143 KeReleaseDispatcherDatabaseLock(OldIrql
);