Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenworker.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Kernel Streaming 00004 * FILE: drivers/ksfilter/ks/worker.c 00005 * PURPOSE: KS Allocator functions 00006 * PROGRAMMER: Johannes Anderwald 00007 */ 00008 00009 00010 #include "priv.h" 00011 00012 /* =============================================================== 00013 Worker Management Functions 00014 */ 00015 00016 typedef struct 00017 { 00018 WORK_QUEUE_ITEM WorkItem; 00019 00020 KEVENT Event; 00021 KSPIN_LOCK Lock; 00022 WORK_QUEUE_TYPE Type; 00023 LONG Counter; 00024 LONG QueuedWorkItemCount; 00025 LIST_ENTRY QueuedWorkItems; 00026 00027 PWORK_QUEUE_ITEM CountedWorkItem; 00028 }KSIWORKER, *PKSIWORKER; 00029 00030 VOID 00031 NTAPI 00032 WorkItemRoutine( 00033 IN PVOID Context) 00034 { 00035 PKSIWORKER KsWorker; 00036 KIRQL OldLevel; 00037 PWORK_QUEUE_ITEM WorkItem; 00038 PLIST_ENTRY Entry; 00039 00040 00041 /* get ks worker implementation */ 00042 KsWorker = (PKSIWORKER)Context; 00043 00044 /* acquire back the lock */ 00045 KeAcquireSpinLock(&KsWorker->Lock, &OldLevel); 00046 00047 do 00048 { 00049 /* sanity check */ 00050 ASSERT(!IsListEmpty(&KsWorker->QueuedWorkItems)); 00051 00052 /* remove first entry */ 00053 Entry = RemoveHeadList(&KsWorker->QueuedWorkItems); 00054 /* get offset to work item */ 00055 WorkItem = (PWORK_QUEUE_ITEM)CONTAINING_RECORD(Entry, WORK_QUEUE_ITEM, List); 00056 00057 /* release lock as the callback might call one KsWorker functions */ 00058 KeReleaseSpinLock(&KsWorker->Lock, OldLevel); 00059 00060 /* now dispatch the work */ 00061 WorkItem->WorkerRoutine(WorkItem->Parameter); 00062 00063 /* acquire back the lock */ 00064 KeAcquireSpinLock(&KsWorker->Lock, &OldLevel); 00065 00066 /* decrement queued work item count */ 00067 InterlockedDecrement(&KsWorker->QueuedWorkItemCount); 00068 00069 }while(KsWorker->QueuedWorkItemCount); 00070 00071 /* release the lock */ 00072 KeReleaseSpinLock(&KsWorker->Lock, OldLevel); 00073 00074 /* signal completion event */ 00075 KeSetEvent(&KsWorker->Event, IO_NO_INCREMENT, FALSE); 00076 00077 } 00078 00079 00080 /* 00081 @implemented 00082 */ 00083 KSDDKAPI 00084 NTSTATUS 00085 NTAPI 00086 KsRegisterWorker( 00087 IN WORK_QUEUE_TYPE WorkQueueType, 00088 OUT PKSWORKER* Worker) 00089 { 00090 PKSIWORKER KsWorker; 00091 00092 00093 if (WorkQueueType != CriticalWorkQueue && 00094 WorkQueueType != DelayedWorkQueue && 00095 WorkQueueType != HyperCriticalWorkQueue) 00096 { 00097 return STATUS_INVALID_PARAMETER; 00098 } 00099 00100 /* allocate worker context */ 00101 KsWorker = AllocateItem(NonPagedPool, sizeof(KSIWORKER)); 00102 if (!KsWorker) 00103 return STATUS_INSUFFICIENT_RESOURCES; 00104 00105 /* initialze the work ctx */ 00106 ExInitializeWorkItem(&KsWorker->WorkItem, WorkItemRoutine, (PVOID)KsWorker); 00107 /* setup type */ 00108 KsWorker->Type = WorkQueueType; 00109 /* Initialize work item queue */ 00110 InitializeListHead(&KsWorker->QueuedWorkItems); 00111 /* initialize work item lock */ 00112 KeInitializeSpinLock(&KsWorker->Lock); 00113 /* initialize event */ 00114 KeInitializeEvent(&KsWorker->Event, NotificationEvent, FALSE); 00115 00116 *Worker = KsWorker; 00117 return STATUS_SUCCESS; 00118 } 00119 00120 /* 00121 @implemented 00122 */ 00123 KSDDKAPI 00124 VOID 00125 NTAPI 00126 KsUnregisterWorker( 00127 IN PKSWORKER Worker) 00128 { 00129 PKSIWORKER KsWorker; 00130 KIRQL OldIrql; 00131 00132 if (!Worker) 00133 return; 00134 00135 /* get ks worker implementation */ 00136 KsWorker = (PKSIWORKER)Worker; 00137 /* acquire spinlock */ 00138 KeAcquireSpinLock(&KsWorker->Lock, &OldIrql); 00139 /* fake status running to avoid work items to be queued by the counted worker */ 00140 KsWorker->Counter = 1; 00141 /* is there currently a work item active */ 00142 if (KsWorker->QueuedWorkItemCount) 00143 { 00144 /* release the lock */ 00145 KeReleaseSpinLock(&KsWorker->Lock, OldIrql); 00146 /* wait for the worker routine to finish */ 00147 KeWaitForSingleObject(&KsWorker->Event, Executive, KernelMode, FALSE, NULL); 00148 } 00149 else 00150 { 00151 /* no work item active, just release the lock */ 00152 KeReleaseSpinLock(&KsWorker->Lock, OldIrql); 00153 } 00154 /* free worker context */ 00155 FreeItem(KsWorker); 00156 } 00157 00158 /* 00159 @implemented 00160 */ 00161 KSDDKAPI 00162 NTSTATUS 00163 NTAPI 00164 KsRegisterCountedWorker( 00165 IN WORK_QUEUE_TYPE WorkQueueType, 00166 IN PWORK_QUEUE_ITEM CountedWorkItem, 00167 OUT PKSWORKER* Worker) 00168 { 00169 NTSTATUS Status; 00170 PKSIWORKER KsWorker; 00171 00172 /* check for counted work item parameter */ 00173 if (!CountedWorkItem) 00174 return STATUS_INVALID_PARAMETER_2; 00175 00176 /* create the work ctx */ 00177 Status = KsRegisterWorker(WorkQueueType, Worker); 00178 /* check for success */ 00179 if (NT_SUCCESS(Status)) 00180 { 00181 /* get ks worker implementation */ 00182 KsWorker = *(PKSIWORKER*)Worker; 00183 /* store counted work item */ 00184 KsWorker->CountedWorkItem = CountedWorkItem; 00185 } 00186 00187 return Status; 00188 } 00189 00190 /* 00191 @implemented 00192 */ 00193 KSDDKAPI 00194 ULONG 00195 NTAPI 00196 KsDecrementCountedWorker( 00197 IN PKSWORKER Worker) 00198 { 00199 PKSIWORKER KsWorker; 00200 LONG Counter; 00201 00202 /* did the caller pass a work ctx */ 00203 if (!Worker) 00204 return STATUS_INVALID_PARAMETER; 00205 00206 /* get ks worker implementation */ 00207 KsWorker = (PKSIWORKER)Worker; 00208 /* decrement counter */ 00209 Counter = InterlockedDecrement(&KsWorker->Counter); 00210 /* return result */ 00211 return Counter; 00212 } 00213 00214 /* 00215 @implemented 00216 */ 00217 KSDDKAPI 00218 ULONG 00219 NTAPI 00220 KsIncrementCountedWorker( 00221 IN PKSWORKER Worker) 00222 { 00223 PKSIWORKER KsWorker; 00224 LONG Counter; 00225 00226 /* did the caller pass a work ctx */ 00227 if (!Worker) 00228 return STATUS_INVALID_PARAMETER; 00229 00230 /* get ks worker implementation */ 00231 KsWorker = (PKSIWORKER)Worker; 00232 /* increment counter */ 00233 Counter = InterlockedIncrement(&KsWorker->Counter); 00234 if (Counter == 1) 00235 { 00236 /* this is the first work item in list, so queue a real work item */ 00237 KsQueueWorkItem(Worker, KsWorker->CountedWorkItem); 00238 } 00239 00240 /* return current counter */ 00241 return Counter; 00242 } 00243 00244 /* 00245 @implemented 00246 */ 00247 KSDDKAPI 00248 NTSTATUS 00249 NTAPI 00250 KsQueueWorkItem( 00251 IN PKSWORKER Worker, 00252 IN PWORK_QUEUE_ITEM WorkItem) 00253 { 00254 PKSIWORKER KsWorker; 00255 KIRQL OldIrql; 00256 00257 /* check for all parameters */ 00258 if (!Worker || !WorkItem) 00259 return STATUS_INVALID_PARAMETER; 00260 00261 /* get ks worker implementation */ 00262 KsWorker = (PKSIWORKER)Worker; 00263 /* lock the work queue */ 00264 KeAcquireSpinLock(&KsWorker->Lock, &OldIrql); 00265 /* insert work item to list */ 00266 InsertTailList(&KsWorker->QueuedWorkItems, &WorkItem->List); 00267 /* increment active count */ 00268 InterlockedIncrement(&KsWorker->QueuedWorkItemCount); 00269 /* is this the first work item */ 00270 if (KsWorker->QueuedWorkItemCount == 1) 00271 { 00272 /* clear event */ 00273 KeClearEvent(&KsWorker->Event); 00274 /* it is, queue it */ 00275 ExQueueWorkItem(&KsWorker->WorkItem, KsWorker->Type); 00276 } 00277 /* release lock */ 00278 KeReleaseSpinLock(&KsWorker->Lock, OldIrql); 00279 00280 return STATUS_SUCCESS; 00281 } Generated on Sun May 27 2012 04:27:58 for ReactOS by
1.7.6.1
|