f1729634bdf799618ac7af498c9a649845b936c8
[reactos.git] / reactos / ntoskrnl / ex / work.c
1 /* $Id: work.c,v 1.19 2004/08/15 16:39:01 chorns Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: mkernel/kernel/work.c
6 * PURPOSE: Manage system work queues
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * REVISION HISTORY:
9 * 29/06/98: Created
10 */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <ntoskrnl.h>
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* DEFINES *******************************************************************/
19
20 #define NUMBER_OF_WORKER_THREADS (5)
21
22 /* TYPES *********************************************************************/
23
24 typedef struct _WORK_QUEUE
25 {
26 /*
27 * PURPOSE: Head of the list of waiting work items
28 */
29 LIST_ENTRY Head;
30
31 /*
32 * PURPOSE: Sychronize access to the work queue
33 */
34 KSPIN_LOCK Lock;
35
36 /*
37 * PURPOSE: Worker threads with nothing to do wait on this event
38 */
39 KSEMAPHORE Sem;
40
41 /*
42 * PURPOSE: Thread associated with work queue
43 */
44 HANDLE Thread[NUMBER_OF_WORKER_THREADS];
45 } WORK_QUEUE, *PWORK_QUEUE;
46
47 /* GLOBALS *******************************************************************/
48
49 /*
50 * PURPOSE: Queue of items waiting to be processed at normal priority
51 */
52 WORK_QUEUE EiNormalWorkQueue;
53
54 WORK_QUEUE EiCriticalWorkQueue;
55
56 WORK_QUEUE EiHyperCriticalWorkQueue;
57
58 /* FUNCTIONS ****************************************************************/
59
60 //static NTSTATUS STDCALL
61 static VOID STDCALL
62 ExWorkerThreadEntryPoint(IN PVOID context)
63 /*
64 * FUNCTION: Entry point for a worker thread
65 * ARGUMENTS:
66 * context = Parameters
67 * RETURNS: Status
68 * NOTE: To kill a worker thread you must queue an item whose callback
69 * calls PsTerminateSystemThread
70 */
71 {
72 PWORK_QUEUE queue = (PWORK_QUEUE)context;
73 PWORK_QUEUE_ITEM item;
74 PLIST_ENTRY current;
75
76 for(;;)
77 {
78 current = ExInterlockedRemoveHeadList(&queue->Head,
79 &queue->Lock);
80 if (current!=NULL)
81 {
82 item = CONTAINING_RECORD(current,WORK_QUEUE_ITEM,List);
83 item->WorkerRoutine(item->Parameter);
84 }
85 else
86 {
87 KeWaitForSingleObject((PVOID)&queue->Sem,
88 Executive,
89 KernelMode,
90 FALSE,
91 NULL);
92 DPRINT("Woke from wait\n");
93 }
94 }
95 }
96
97 static VOID ExInitializeWorkQueue(PWORK_QUEUE WorkQueue,
98 KPRIORITY Priority)
99 {
100 ULONG i;
101 PETHREAD Thread;
102
103 InitializeListHead(&WorkQueue->Head);
104 KeInitializeSpinLock(&WorkQueue->Lock);
105 KeInitializeSemaphore(&WorkQueue->Sem,
106 0,
107 256);
108 for (i=0; i<NUMBER_OF_WORKER_THREADS; i++)
109 {
110 PsCreateSystemThread(&WorkQueue->Thread[i],
111 THREAD_ALL_ACCESS,
112 NULL,
113 NULL,
114 NULL,
115 ExWorkerThreadEntryPoint,
116 WorkQueue);
117 ObReferenceObjectByHandle(WorkQueue->Thread[i],
118 THREAD_ALL_ACCESS,
119 PsThreadType,
120 KernelMode,
121 (PVOID*)&Thread,
122 NULL);
123 KeSetPriorityThread(&Thread->Tcb,
124 Priority);
125 ObDereferenceObject(Thread);
126 }
127 }
128
129 VOID INIT_FUNCTION
130 ExInitializeWorkerThreads(VOID)
131 {
132 ExInitializeWorkQueue(&EiNormalWorkQueue,
133 LOW_PRIORITY);
134 ExInitializeWorkQueue(&EiCriticalWorkQueue,
135 LOW_REALTIME_PRIORITY);
136 ExInitializeWorkQueue(&EiHyperCriticalWorkQueue,
137 HIGH_PRIORITY);
138 }
139
140 /*
141 * @implemented
142 */
143 VOID STDCALL
144 ExQueueWorkItem (PWORK_QUEUE_ITEM WorkItem,
145 WORK_QUEUE_TYPE QueueType)
146 /*
147 * FUNCTION: Inserts a work item in a queue for one of the system worker
148 * threads to process
149 * ARGUMENTS:
150 * WorkItem = Item to insert
151 * QueueType = Queue to insert it in
152 */
153 {
154 assert(WorkItem!=NULL);
155 ASSERT_IRQL(DISPATCH_LEVEL);
156
157 /*
158 * Insert the item in the appropiate queue and wake up any thread
159 * waiting for something to do
160 */
161 switch(QueueType)
162 {
163 case DelayedWorkQueue:
164 ExInterlockedInsertTailList(&EiNormalWorkQueue.Head,
165 &WorkItem->List,
166 &EiNormalWorkQueue.Lock);
167 KeReleaseSemaphore(&EiNormalWorkQueue.Sem,
168 IO_NO_INCREMENT,
169 1,
170 FALSE);
171 break;
172
173 case CriticalWorkQueue:
174 ExInterlockedInsertTailList(&EiCriticalWorkQueue.Head,
175 &WorkItem->List,
176 &EiCriticalWorkQueue.Lock);
177 KeReleaseSemaphore(&EiCriticalWorkQueue.Sem,
178 IO_NO_INCREMENT,
179 1,
180 FALSE);
181 break;
182
183 case HyperCriticalWorkQueue:
184 ExInterlockedInsertTailList(&EiHyperCriticalWorkQueue.Head,
185 &WorkItem->List,
186 &EiHyperCriticalWorkQueue.Lock);
187 KeReleaseSemaphore(&EiHyperCriticalWorkQueue.Sem,
188 IO_NO_INCREMENT,
189 1,
190 FALSE);
191 break;
192
193 #ifdef __USE_W32API
194 case MaximumWorkQueue:
195 // Unimplemented
196 break;
197 #endif
198 }
199 }
200
201 /* EOF */