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