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