ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

worker.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.