/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: drivers/lib/chew/workqueue.c * PURPOSE: Common Highlevel Executive Worker * * PROGRAMMERS: arty (ayerkes@speakeasy.net) */ #include #include #define NDEBUG #define FOURCC(w,x,y,z) (((w) << 24) | ((x) << 16) | ((y) << 8) | (z)) PDEVICE_OBJECT WorkQueueDevice; LIST_ENTRY WorkQueue; KSPIN_LOCK WorkQueueLock; typedef struct _WORK_ITEM { LIST_ENTRY Entry; PIO_WORKITEM WorkItem; VOID (*Worker)( PVOID Data ); CHAR UserSpace[1]; } WORK_ITEM, *PWORK_ITEM; VOID ChewInit( PDEVICE_OBJECT DeviceObject ) { WorkQueueDevice = DeviceObject; InitializeListHead( &WorkQueue ); KeInitializeSpinLock( &WorkQueueLock ); } VOID ChewShutdown() { KIRQL OldIrql; PLIST_ENTRY Entry; PWORK_ITEM WorkItem; KeAcquireSpinLock( &WorkQueueLock, &OldIrql ); while( !IsListEmpty( &WorkQueue ) ) { Entry = RemoveHeadList( &WorkQueue ); WorkItem = CONTAINING_RECORD( Entry, WORK_ITEM, Entry ); IoFreeWorkItem( WorkItem->WorkItem ); ExFreePool( WorkItem ); } KeReleaseSpinLock( &WorkQueueLock, OldIrql ); } VOID STDCALL ChewWorkItem( PDEVICE_OBJECT DeviceObject, PVOID ChewItem ) { PWORK_ITEM WorkItem = ChewItem; RemoveEntryList( &WorkItem->Entry ); if( WorkItem->Worker ) WorkItem->Worker( WorkItem->UserSpace ); IoFreeWorkItem( WorkItem->WorkItem ); ExFreePool( WorkItem ); } BOOLEAN ChewCreate ( PVOID *ItemPtr, SIZE_T Bytes, VOID (*Worker)( PVOID ), PVOID UserSpace ) { PWORK_ITEM Item; if( KeGetCurrentIrql() == PASSIVE_LEVEL ) { if( ItemPtr ) *ItemPtr = NULL; Worker(UserSpace); return TRUE; } else { Item = ExAllocatePoolWithTag ( NonPagedPool, sizeof( WORK_ITEM ) + Bytes - 1, FOURCC('C','H','E','W') ); if( Item ) { Item->WorkItem = IoAllocateWorkItem( WorkQueueDevice ); if( !Item->WorkItem ) { ExFreePool( Item ); return FALSE; } Item->Worker = Worker; if( Bytes && UserSpace ) RtlCopyMemory( Item->UserSpace, UserSpace, Bytes ); ExInterlockedInsertTailList ( &WorkQueue, &Item->Entry, &WorkQueueLock ); IoQueueWorkItem ( Item->WorkItem, ChewWorkItem, CriticalWorkQueue, Item ); if( ItemPtr ) *ItemPtr = Item; return TRUE; } else { return FALSE; } } } VOID ChewRemove( PVOID Item ) { PWORK_ITEM WorkItem = Item; IoFreeWorkItem( WorkItem->WorkItem ); ExFreePool( WorkItem ); }