xref: /reactos/drivers/network/tcpip/chew/workqueue.c (revision 09dde2cf)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS kernel
4  * FILE:            lib/drivers/chew/workqueue.c
5  * PURPOSE:         Common Highlevel Executive Worker
6  *
7  * PROGRAMMERS:     arty (ayerkes@speakeasy.net)
8  */
9 
10 #include <wdm.h>
11 
12 #define FOURCC(w,x,y,z) (((w) << 24) | ((x) << 16) | ((y) << 8) | (z))
13 #define CHEW_TAG FOURCC('C','H','E','W')
14 
15 PDEVICE_OBJECT WorkQueueDevice;
16 LIST_ENTRY     WorkQueue;
17 KSPIN_LOCK     WorkQueueLock;
18 KEVENT         WorkQueueClear;
19 
20 typedef struct _WORK_ITEM
21 {
22     LIST_ENTRY Entry;
23     PIO_WORKITEM WorkItem;
24     VOID (*Worker)(PVOID WorkerContext);
25     PVOID WorkerContext;
26 } WORK_ITEM, *PWORK_ITEM;
27 
28 VOID ChewInit(PDEVICE_OBJECT DeviceObject)
29 {
30     WorkQueueDevice = DeviceObject;
31     InitializeListHead(&WorkQueue);
32     KeInitializeSpinLock(&WorkQueueLock);
33     KeInitializeEvent(&WorkQueueClear, NotificationEvent, TRUE);
34 }
35 
36 VOID ChewShutdown(VOID)
37 {
38     KeWaitForSingleObject(&WorkQueueClear, Executive, KernelMode, FALSE, NULL);
39 }
40 
41 VOID NTAPI ChewWorkItem(PDEVICE_OBJECT DeviceObject, PVOID ChewItem)
42 {
43     PWORK_ITEM WorkItem = ChewItem;
44     KIRQL OldIrql;
45 
46     WorkItem->Worker(WorkItem->WorkerContext);
47 
48     IoFreeWorkItem(WorkItem->WorkItem);
49 
50     KeAcquireSpinLock(&WorkQueueLock, &OldIrql);
51     RemoveEntryList(&WorkItem->Entry);
52 
53     if (IsListEmpty(&WorkQueue))
54         KeSetEvent(&WorkQueueClear, 0, FALSE);
55 
56     KeReleaseSpinLock(&WorkQueueLock, OldIrql);
57 
58     ExFreePoolWithTag(WorkItem, CHEW_TAG);
59 }
60 
61 BOOLEAN ChewCreate(VOID (*Worker)(PVOID), PVOID WorkerContext)
62 {
63     PWORK_ITEM Item;
64     Item = ExAllocatePoolWithTag(NonPagedPool,
65                                  sizeof(WORK_ITEM),
66                                  CHEW_TAG);
67 
68     if (Item)
69     {
70         Item->WorkItem = IoAllocateWorkItem(WorkQueueDevice);
71         if (!Item->WorkItem)
72         {
73             ExFreePool(Item);
74             return FALSE;
75         }
76 
77         Item->Worker = Worker;
78         Item->WorkerContext = WorkerContext;
79         ExInterlockedInsertTailList(&WorkQueue, &Item->Entry, &WorkQueueLock);
80         KeClearEvent(&WorkQueueClear);
81         IoQueueWorkItem(Item->WorkItem, ChewWorkItem, DelayedWorkQueue, Item);
82 
83         return TRUE;
84     }
85     else
86     {
87         return FALSE;
88     }
89 }
90