- Sync up Mm interface with WinLdr branch (introduce the concept of a memory type...
[reactos.git] / reactos / lib / drivers / chew / workqueue.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/lib/chew/workqueue.c
5 * PURPOSE: Common Highlevel Executive Worker
6 *
7 * PROGRAMMERS: arty (ayerkes@speakeasy.net)
8 */
9 #include <ntddk.h>
10 #include <chew/chew.h>
11
12 #define NDEBUG
13
14 #define FOURCC(w,x,y,z) (((w) << 24) | ((x) << 16) | ((y) << 8) | (z))
15
16 PDEVICE_OBJECT WorkQueueDevice;
17 LIST_ENTRY WorkQueue;
18 KSPIN_LOCK WorkQueueLock;
19
20 typedef struct _WORK_ITEM {
21 LIST_ENTRY Entry;
22 PIO_WORKITEM WorkItem;
23 VOID (*Worker)( PVOID Data );
24 CHAR UserSpace[1];
25 } WORK_ITEM, *PWORK_ITEM;
26
27 VOID ChewInit( PDEVICE_OBJECT DeviceObject ) {
28 WorkQueueDevice = DeviceObject;
29 InitializeListHead( &WorkQueue );
30 KeInitializeSpinLock( &WorkQueueLock );
31 }
32
33 VOID ChewShutdown() {
34 KIRQL OldIrql;
35 PLIST_ENTRY Entry;
36 PWORK_ITEM WorkItem;
37
38 KeAcquireSpinLock( &WorkQueueLock, &OldIrql );
39
40 while( !IsListEmpty( &WorkQueue ) ) {
41 Entry = RemoveHeadList( &WorkQueue );
42 WorkItem = CONTAINING_RECORD( Entry, WORK_ITEM, Entry );
43 IoFreeWorkItem( WorkItem->WorkItem );
44 ExFreePool( WorkItem );
45 }
46
47 KeReleaseSpinLock( &WorkQueueLock, OldIrql );
48 }
49
50 VOID STDCALL ChewWorkItem( PDEVICE_OBJECT DeviceObject, PVOID ChewItem ) {
51 PWORK_ITEM WorkItem = ChewItem;
52
53 RemoveEntryList( &WorkItem->Entry );
54
55 if( WorkItem->Worker )
56 WorkItem->Worker( WorkItem->UserSpace );
57
58 IoFreeWorkItem( WorkItem->WorkItem );
59 ExFreePool( WorkItem );
60 }
61
62 BOOLEAN ChewCreate
63 ( PVOID *ItemPtr, SIZE_T Bytes, VOID (*Worker)( PVOID ), PVOID UserSpace ) {
64 PWORK_ITEM Item;
65
66 if( KeGetCurrentIrql() == PASSIVE_LEVEL ) {
67 if( ItemPtr )
68 *ItemPtr = NULL;
69 Worker(UserSpace);
70 return TRUE;
71 } else {
72 Item = ExAllocatePoolWithTag
73 ( NonPagedPool,
74 sizeof( WORK_ITEM ) + Bytes - 1,
75 FOURCC('C','H','E','W') );
76
77 if( Item ) {
78 Item->WorkItem = IoAllocateWorkItem( WorkQueueDevice );
79 if( !Item->WorkItem ) {
80 ExFreePool( Item );
81 return FALSE;
82 }
83 Item->Worker = Worker;
84 if( Bytes && UserSpace )
85 RtlCopyMemory( Item->UserSpace, UserSpace, Bytes );
86
87 ExInterlockedInsertTailList
88 ( &WorkQueue, &Item->Entry, &WorkQueueLock );
89 IoQueueWorkItem
90 ( Item->WorkItem, ChewWorkItem, CriticalWorkQueue, Item );
91
92 if( ItemPtr )
93 *ItemPtr = Item;
94
95 return TRUE;
96 } else {
97 return FALSE;
98 }
99 }
100 }
101
102 VOID ChewRemove( PVOID Item ) {
103 PWORK_ITEM WorkItem = Item;
104 IoFreeWorkItem( WorkItem->WorkItem );
105 ExFreePool( WorkItem );
106 }