You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
4.3 KiB
188 lines
4.3 KiB
//+-----------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (c) Microsoft Corporation
|
|
//
|
|
// File: kppool.cxx
|
|
//
|
|
// Contents: Routines to manage the thread pool
|
|
//
|
|
// History: 10-Jul-2001 t-ryanj Created
|
|
//
|
|
//------------------------------------------------------------------------
|
|
#include "kppool.h"
|
|
#include "kpcore.h"
|
|
|
|
#define KP_THREAD_STACKSIZE 0
|
|
#define KP_THREAD_CPUFACTOR 10
|
|
|
|
HANDLE* KpThreadPool = NULL;
|
|
ULONG KpThreadCount = 0;
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: KpInitThreadPool
|
|
//
|
|
// Synopsis: Creates the thread pool.
|
|
//
|
|
// Effects:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns: Success status. On failure, no threads are running, no
|
|
// memory is allocated.
|
|
//
|
|
// Notes: TODO: This is a bad way to do threadpools, apparently.
|
|
// Find a better one.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
KpInitThreadPool(
|
|
VOID
|
|
)
|
|
{
|
|
SYSTEM_INFO Sysinfo;
|
|
ULONG TargetThreadCount;
|
|
|
|
//
|
|
// Get system info, so we can see how many procs we've got.
|
|
//
|
|
|
|
GetSystemInfo(&Sysinfo);
|
|
|
|
//
|
|
// Let's make KP_THREAD_CPUFACTOR * numprocs threads.
|
|
//
|
|
|
|
TargetThreadCount = Sysinfo.dwNumberOfProcessors * KP_THREAD_CPUFACTOR;
|
|
|
|
//
|
|
// Make memory to keep track of all these threads.
|
|
//
|
|
|
|
DsysAssert( KpThreadPool == NULL );
|
|
|
|
KpThreadPool = (HANDLE*)KpAlloc( TargetThreadCount * sizeof(HANDLE) );
|
|
|
|
if( !KpThreadPool )
|
|
{
|
|
DebugLog( DEB_ERROR, "%s(%d): Could not allocate memory to keep track of threads.\n" __FILE__, __LINE__ );
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// Zero the memory so we can easily check if a thread creation failed.
|
|
//
|
|
|
|
RtlZeroMemory( KpThreadPool, TargetThreadCount * sizeof(HANDLE) );
|
|
|
|
//
|
|
// Create the Threads
|
|
//
|
|
|
|
DsysAssert(KpThreadCount == 0);
|
|
|
|
for( KpThreadCount = 0; KpThreadCount < TargetThreadCount; KpThreadCount++ )
|
|
{
|
|
KpThreadPool[KpThreadCount] = CreateThread( NULL,
|
|
KP_THREAD_STACKSIZE,
|
|
KpThreadCore,
|
|
NULL,
|
|
0,
|
|
NULL );
|
|
if( !KpThreadPool[KpThreadCount] )
|
|
{
|
|
DebugLog( DEB_ERROR, "%s(%d): Error creating thread: 0x%x.\n", __FILE__, __LINE__, GetLastError() );
|
|
goto Error;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
Error:
|
|
KpCleanupThreadPool();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: KpCleanupThreadPool
|
|
//
|
|
// Synopsis: Asks all threads to terminate, waits for them to do so,
|
|
// closes their handles, and frees the memory keeping track of
|
|
// the threadpool.
|
|
//
|
|
// Effects:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
VOID
|
|
KpCleanupThreadPool(
|
|
VOID
|
|
)
|
|
{
|
|
DWORD dwWaitResult;
|
|
BOOL fPostStatus;
|
|
|
|
//
|
|
// Post a terminate request for each thread.
|
|
//
|
|
|
|
for( ULONG i = KpThreadCount; i > 0; i-- )
|
|
{
|
|
fPostStatus = PostQueuedCompletionStatus(KpGlobalIocp,
|
|
0,
|
|
KPCK_TERMINATE,
|
|
NULL );
|
|
|
|
if( !fPostStatus )
|
|
{
|
|
DebugLog( DEB_ERROR, "%s(%d): Unable to post terminate request to the completion port: 0x%x.\n", __FILE__, __LINE__, GetLastError() );
|
|
// TODO: Consider if this fails.
|
|
// we'll probably want to wait for however many threads to terminate
|
|
// as we were able to post requests, then maybe try again or kill
|
|
// the rest of the threads
|
|
}
|
|
}
|
|
|
|
//
|
|
// Wait for the threads to terminate
|
|
//
|
|
|
|
dwWaitResult = WaitForMultipleObjects(KpThreadCount,
|
|
KpThreadPool,
|
|
TRUE,
|
|
INFINITE );
|
|
if( dwWaitResult == WAIT_FAILED )
|
|
{
|
|
DebugLog( DEB_ERROR, "%s(%d): Error waiting for thread terminations: 0x%x.", __FILE__, __LINE__, GetLastError() );
|
|
}
|
|
|
|
//
|
|
// Close all the handles
|
|
//
|
|
|
|
while( KpThreadCount-- )
|
|
{
|
|
CloseHandle(KpThreadPool[KpThreadCount]);
|
|
}
|
|
|
|
//
|
|
// Free the memory
|
|
//
|
|
|
|
KpFree( KpThreadPool );
|
|
KpThreadPool = NULL;
|
|
}
|