/** * Frees resources used by a work queue. * * \param WorkQueue A work queue object. */ VOID PhDeleteWorkQueue( __inout PPH_WORK_QUEUE WorkQueue ) { PLIST_ENTRY listEntry; PPH_WORK_QUEUE_ITEM workQueueItem; #ifdef DEBUG PhAcquireQueuedLockExclusive(&PhDbgWorkQueueListLock); RemoveEntryList(&WorkQueue->DbgListEntry); PhReleaseQueuedLockExclusive(&PhDbgWorkQueueListLock); #endif // Wait for all worker threads to exit. WorkQueue->Terminating = TRUE; NtReleaseSemaphore(WorkQueue->SemaphoreHandle, WorkQueue->CurrentThreads, NULL); PhWaitForRundownProtection(&WorkQueue->RundownProtect); // Free all un-executed work items. listEntry = WorkQueue->QueueListHead.Flink; while (listEntry != &WorkQueue->QueueListHead) { workQueueItem = CONTAINING_RECORD(listEntry, PH_WORK_QUEUE_ITEM, ListEntry); listEntry = listEntry->Flink; PhFreeToFreeList(&PhWorkQueueItemFreeList, workQueueItem); } NtClose(WorkQueue->SemaphoreHandle); }
/** * Frees resources used by a work queue. * * \param WorkQueue A work queue object. */ VOID PhDeleteWorkQueue( _Inout_ PPH_WORK_QUEUE WorkQueue ) { PLIST_ENTRY listEntry; PPH_WORK_QUEUE_ITEM workQueueItem; #ifdef DEBUG ULONG index; #endif #ifdef DEBUG PhAcquireQueuedLockExclusive(&PhDbgWorkQueueListLock); if ((index = PhFindItemList(PhDbgWorkQueueList, WorkQueue)) != -1) PhRemoveItemList(PhDbgWorkQueueList, index); PhReleaseQueuedLockExclusive(&PhDbgWorkQueueListLock); #endif // Wait for all worker threads to exit. WorkQueue->Terminating = TRUE; MemoryBarrier(); if (WorkQueue->SemaphoreHandle) NtReleaseSemaphore(WorkQueue->SemaphoreHandle, WorkQueue->CurrentThreads, NULL); PhWaitForRundownProtection(&WorkQueue->RundownProtect); // Free all un-executed work items. listEntry = WorkQueue->QueueListHead.Flink; while (listEntry != &WorkQueue->QueueListHead) { workQueueItem = CONTAINING_RECORD(listEntry, PH_WORK_QUEUE_ITEM, ListEntry); listEntry = listEntry->Flink; PhpDestroyWorkQueueItem(workQueueItem); } if (WorkQueue->SemaphoreHandle) NtClose(WorkQueue->SemaphoreHandle); }