Standardize comment headers. Patch by Trevor McCort
[reactos.git] / reactos / ntoskrnl / ex / work.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ex/work.c
6 * PURPOSE: Manage system work queues
7 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* DEFINES *******************************************************************/
18
19 #define NUMBER_OF_WORKER_THREADS (5)
20
21 /* TYPES *********************************************************************/
22
23 /* GLOBALS *******************************************************************/
24
25 /*
26 * PURPOSE: Queue of items waiting to be processed at normal priority
27 */
28 KQUEUE EiNormalWorkQueue;
29
30 KQUEUE EiCriticalWorkQueue;
31
32 KQUEUE EiHyperCriticalWorkQueue;
33
34 /* FUNCTIONS ****************************************************************/
35
36 //static NTSTATUS STDCALL
37 static VOID STDCALL
38 ExWorkerThreadEntryPoint(IN PVOID context)
39 /*
40 * FUNCTION: Entry point for a worker thread
41 * ARGUMENTS:
42 * context = Parameters
43 * RETURNS: Status
44 * NOTE: To kill a worker thread you must queue an item whose callback
45 * calls PsTerminateSystemThread
46 */
47 {
48
49 PWORK_QUEUE_ITEM item;
50 PLIST_ENTRY current;
51
52 while (TRUE)
53 {
54 current = KeRemoveQueue( (PKQUEUE)context, KernelMode, NULL );
55
56 /* can't happend since we do a KernelMode wait (and we're a system thread) */
57 ASSERT((NTSTATUS)current != STATUS_USER_APC);
58
59 /* this should never happend either, since we wait with NULL timeout,
60 * but there's a slight possibility that STATUS_TIMEOUT is returned
61 * at queue rundown in NT (unlikely) -Gunnar
62 */
63 ASSERT((NTSTATUS)current != STATUS_TIMEOUT);
64
65 /* based on INVALID_WORK_QUEUE_ITEM bugcheck desc. */
66 if (current->Flink == NULL || current->Blink == NULL)
67 {
68 KeBugCheck(INVALID_WORK_QUEUE_ITEM);
69 }
70
71 /* "reinitialize" item (same as done in ExInitializeWorkItem) */
72 current->Flink = NULL;
73
74 item = CONTAINING_RECORD( current, WORK_QUEUE_ITEM, List);
75 item->WorkerRoutine(item->Parameter);
76
77 if (KeGetCurrentIrql() != PASSIVE_LEVEL)
78 {
79 KeBugCheck(IRQL_NOT_LESS_OR_EQUAL);
80 }
81 }
82
83 }
84
85 static VOID ExInitializeWorkQueue(PKQUEUE WorkQueue,
86 KPRIORITY Priority)
87 {
88 ULONG i;
89 PETHREAD Thread;
90 HANDLE hThread;
91
92
93 for (i=0; i<NUMBER_OF_WORKER_THREADS; i++)
94 {
95
96 PsCreateSystemThread(&hThread,
97 THREAD_ALL_ACCESS,
98 NULL,
99 NULL,
100 NULL,
101 ExWorkerThreadEntryPoint,
102 WorkQueue);
103 ObReferenceObjectByHandle(hThread,
104 THREAD_ALL_ACCESS,
105 PsThreadType,
106 KernelMode,
107 (PVOID*)&Thread,
108 NULL);
109 KeSetPriorityThread(&Thread->Tcb,
110 Priority);
111 ObDereferenceObject(Thread);
112 ZwClose(hThread);
113 }
114 }
115
116 VOID INIT_FUNCTION
117 ExInitializeWorkerThreads(VOID)
118 {
119 KeInitializeQueue( &EiNormalWorkQueue, NUMBER_OF_WORKER_THREADS );
120 KeInitializeQueue( &EiCriticalWorkQueue , NUMBER_OF_WORKER_THREADS );
121 KeInitializeQueue( &EiHyperCriticalWorkQueue , NUMBER_OF_WORKER_THREADS );
122
123 ExInitializeWorkQueue(&EiNormalWorkQueue,
124 LOW_PRIORITY);
125 ExInitializeWorkQueue(&EiCriticalWorkQueue,
126 LOW_REALTIME_PRIORITY);
127 ExInitializeWorkQueue(&EiHyperCriticalWorkQueue,
128 HIGH_PRIORITY);
129 }
130
131 /*
132 * @implemented
133 */
134 VOID STDCALL
135 ExQueueWorkItem (PWORK_QUEUE_ITEM WorkItem,
136 WORK_QUEUE_TYPE QueueType)
137 /*
138 * FUNCTION: Inserts a work item in a queue for one of the system worker
139 * threads to process
140 * ARGUMENTS:
141 * WorkItem = Item to insert
142 * QueueType = Queue to insert it in
143 */
144 {
145 ASSERT(WorkItem!=NULL);
146 ASSERT_IRQL(DISPATCH_LEVEL);
147 ASSERT(WorkItem->List.Flink == NULL);
148 /*
149 * Insert the item in the appropiate queue and wake up any thread
150 * waiting for something to do
151 */
152 switch(QueueType)
153 {
154 case DelayedWorkQueue:
155 KeInsertQueue (
156 &EiNormalWorkQueue,
157 &WorkItem->List
158 );
159 break;
160
161 case CriticalWorkQueue:
162 KeInsertQueue (
163 &EiCriticalWorkQueue,
164 &WorkItem->List
165 );
166 break;
167
168 case HyperCriticalWorkQueue:
169 KeInsertQueue (
170 &EiHyperCriticalWorkQueue,
171 &WorkItem->List
172 );
173 break;
174
175 default:
176 break;
177
178 }
179 }
180
181 /* EOF */