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
ChewInit(PDEVICE_OBJECT DeviceObject)28 VOID ChewInit(PDEVICE_OBJECT DeviceObject)
29 {
30 WorkQueueDevice = DeviceObject;
31 InitializeListHead(&WorkQueue);
32 KeInitializeSpinLock(&WorkQueueLock);
33 KeInitializeEvent(&WorkQueueClear, NotificationEvent, TRUE);
34 }
35
ChewShutdown(VOID)36 VOID ChewShutdown(VOID)
37 {
38 KeWaitForSingleObject(&WorkQueueClear, Executive, KernelMode, FALSE, NULL);
39 }
40
ChewWorkItem(PDEVICE_OBJECT DeviceObject,PVOID ChewItem)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
ChewCreate(VOID (* Worker)(PVOID),PVOID WorkerContext)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