/*++ Copyright (c) 1997 Microsoft Corporation Module Name: ThreadPool.c Abstract: Work queue management functions. --*/ #define WIN32_LEAN_AND_MEAN #include #include #include "threadpool.h" // // Structure to create simple linked list // typedef struct { EXTENSION_CONTROL_BLOCK *pECB; // Data for list entry DWORD dwNextEntry; // Pointer to next entry } ECB_QUEUE_ENTRY; // // Array that is a simple linked list // ECB_QUEUE_ENTRY ECBqueue[WORK_QUEUE_ENTRIES]; // // Index of next ECBqueue entry to use, and last Entry in use. // DWORD dwCurrentEntry, dwLastEntry; // // Flag to indicate that there are no other entries in the ECBqueue // BOOL fQueueEmpty; BOOL InitThreadPool( void ) /*++ Purpose: Initialize our thread pool. --*/ { DWORD i; DWORD dwThreadID; // // Create Semaphore in nonsignaled state // if ( (hWorkSem = CreateSemaphore( NULL, 0, 0x7fffffff, NULL )) == NULL ) { return FALSE; } InitializeCriticalSection( &csQueueLock ); fQueueEmpty = TRUE; // // Create Pool Threads // for ( i = 0; i < POOL_THREADS; i++ ) { if ( CreateThread( NULL, 0, WorkerFunction, (LPVOID) i, 0, &dwThreadID ) == NULL ) { return FALSE; } } // // Clear work queue // ZeroMemory( ECBqueue, WORK_QUEUE_ENTRIES * sizeof (ECB_QUEUE_ENTRY) ); return TRUE; } BOOL AddWorkQueueEntry( IN EXTENSION_CONTROL_BLOCK * pECB ) /*++ Purpose: Add single work unit to the queue Arguments: pECB - pointer to the extension control block Returns: TRUE if the unit was successfully queued FALSE if queue is full --*/ { DWORD i; for ( i = 0; i < WORK_QUEUE_ENTRIES; i++ ) { if ( ECBqueue[i].pECB == NULL ) { if ( fQueueEmpty ) { dwCurrentEntry = i; fQueueEmpty = FALSE; } else { ECBqueue[dwLastEntry].dwNextEntry = i; } ECBqueue[i].pECB = pECB; dwLastEntry = i; return TRUE; } } // If no NULL queue entry found, indicate failure return FALSE; } BOOL GetWorkQueueEntry( OUT EXTENSION_CONTROL_BLOCK ** ppECB ) /*++ Purpose: Arguments: Returns: --*/ { if ( (*ppECB = ECBqueue[dwCurrentEntry].pECB) == NULL ) { return FALSE; } else { ECBqueue[dwCurrentEntry].pECB = NULL; if (dwCurrentEntry == dwLastEntry) // If this is only pending item fQueueEmpty = TRUE; else dwCurrentEntry = ECBqueue[dwCurrentEntry].dwNextEntry; } return TRUE; }