|
|
//-----------------------------------------------------------------------------
//
//
// File: asyncq.cpp
//
// Description: Non-template asyncq implementations
//
// Author: Mike Swafford (MikeSwa)
//
// History:
// 2/23/99 - MikeSwa Created
//
// Copyright (C) 1999 Microsoft Corporation
//
//-----------------------------------------------------------------------------
#include "aqprecmp.h"
#include "asyncq.h"
#include "asyncq.inl"
DWORD CAsyncQueueBase::s_cAsyncQueueStaticInitRefCount = 0; DWORD CAsyncQueueBase::s_cMaxPerProcATQThreadAdjustment = 0; DWORD CAsyncQueueBase::s_cDefaultMaxAsyncThreads = 0;
// Some counters for debugging thread management
DWORD CAsyncQueueBase::s_cThreadCompletion_QueueEmpty = 0; DWORD CAsyncQueueBase::s_cThreadCompletion_CompletedScheduledItems = 0; DWORD CAsyncQueueBase::s_cThreadCompletion_UnacceptableThreadCount = 0; DWORD CAsyncQueueBase::s_cThreadCompletion_Timeout = 0; DWORD CAsyncQueueBase::s_cThreadCompletion_Failure = 0; DWORD CAsyncQueueBase::s_cThreadCompletion_Paused = 0;
// state transition table for the async queue state machine
STATE_TRANSITION CAsyncQueueBase::s_rgTransitionTable[] = { // start state normal:
{ ASYNC_QUEUE_STATUS_NORMAL, ASYNC_QUEUE_ACTION_KICK, ASYNC_QUEUE_STATUS_NORMAL }, { ASYNC_QUEUE_STATUS_NORMAL, ASYNC_QUEUE_ACTION_PAUSE, ASYNC_QUEUE_STATUS_PAUSED }, { ASYNC_QUEUE_STATUS_NORMAL, ASYNC_QUEUE_ACTION_UNPAUSE, ASYNC_QUEUE_STATUS_NORMAL }, { ASYNC_QUEUE_STATUS_NORMAL, ASYNC_QUEUE_ACTION_FREEZE, ASYNC_QUEUE_STATUS_FROZEN }, { ASYNC_QUEUE_STATUS_NORMAL, ASYNC_QUEUE_ACTION_THAW, ASYNC_QUEUE_STATUS_NORMAL }, { ASYNC_QUEUE_STATUS_NORMAL, ASYNC_QUEUE_ACTION_SHUTDOWN, ASYNC_QUEUE_STATUS_SHUTDOWN }, // start state paused:
{ ASYNC_QUEUE_STATUS_PAUSED, ASYNC_QUEUE_ACTION_KICK, ASYNC_QUEUE_STATUS_NORMAL }, { ASYNC_QUEUE_STATUS_PAUSED, ASYNC_QUEUE_ACTION_PAUSE, ASYNC_QUEUE_STATUS_PAUSED }, { ASYNC_QUEUE_STATUS_PAUSED, ASYNC_QUEUE_ACTION_UNPAUSE, ASYNC_QUEUE_STATUS_NORMAL }, { ASYNC_QUEUE_STATUS_PAUSED, ASYNC_QUEUE_ACTION_FREEZE, ASYNC_QUEUE_STATUS_FROZENPAUSED }, { ASYNC_QUEUE_STATUS_PAUSED, ASYNC_QUEUE_ACTION_THAW, ASYNC_QUEUE_STATUS_PAUSED }, { ASYNC_QUEUE_STATUS_PAUSED, ASYNC_QUEUE_ACTION_SHUTDOWN, ASYNC_QUEUE_STATUS_SHUTDOWN }, // start state frozen:
{ ASYNC_QUEUE_STATUS_FROZEN, ASYNC_QUEUE_ACTION_KICK, ASYNC_QUEUE_STATUS_NORMAL }, { ASYNC_QUEUE_STATUS_FROZEN, ASYNC_QUEUE_ACTION_PAUSE, ASYNC_QUEUE_STATUS_FROZENPAUSED }, { ASYNC_QUEUE_STATUS_FROZEN, ASYNC_QUEUE_ACTION_UNPAUSE, ASYNC_QUEUE_STATUS_FROZEN }, { ASYNC_QUEUE_STATUS_FROZEN, ASYNC_QUEUE_ACTION_FREEZE, ASYNC_QUEUE_STATUS_FROZEN }, { ASYNC_QUEUE_STATUS_FROZEN, ASYNC_QUEUE_ACTION_THAW, ASYNC_QUEUE_STATUS_NORMAL }, { ASYNC_QUEUE_STATUS_FROZEN, ASYNC_QUEUE_ACTION_SHUTDOWN, ASYNC_QUEUE_STATUS_SHUTDOWN }, // start state frozenpaused:
{ ASYNC_QUEUE_STATUS_FROZENPAUSED, ASYNC_QUEUE_ACTION_KICK, ASYNC_QUEUE_STATUS_NORMAL }, { ASYNC_QUEUE_STATUS_FROZENPAUSED, ASYNC_QUEUE_ACTION_PAUSE, ASYNC_QUEUE_STATUS_FROZENPAUSED }, { ASYNC_QUEUE_STATUS_FROZENPAUSED, ASYNC_QUEUE_ACTION_UNPAUSE, ASYNC_QUEUE_STATUS_FROZEN }, { ASYNC_QUEUE_STATUS_FROZENPAUSED, ASYNC_QUEUE_ACTION_FREEZE, ASYNC_QUEUE_STATUS_FROZENPAUSED }, { ASYNC_QUEUE_STATUS_FROZENPAUSED, ASYNC_QUEUE_ACTION_THAW, ASYNC_QUEUE_STATUS_PAUSED }, { ASYNC_QUEUE_STATUS_FROZENPAUSED, ASYNC_QUEUE_ACTION_SHUTDOWN, ASYNC_QUEUE_STATUS_SHUTDOWN }, // start state shutdown:
{ ASYNC_QUEUE_STATUS_SHUTDOWN, ASYNC_QUEUE_ACTION_KICK, ASYNC_QUEUE_STATUS_SHUTDOWN }, { ASYNC_QUEUE_STATUS_SHUTDOWN, ASYNC_QUEUE_ACTION_PAUSE, ASYNC_QUEUE_STATUS_SHUTDOWN }, { ASYNC_QUEUE_STATUS_SHUTDOWN, ASYNC_QUEUE_ACTION_UNPAUSE, ASYNC_QUEUE_STATUS_SHUTDOWN }, { ASYNC_QUEUE_STATUS_SHUTDOWN, ASYNC_QUEUE_ACTION_FREEZE, ASYNC_QUEUE_STATUS_SHUTDOWN }, { ASYNC_QUEUE_STATUS_SHUTDOWN, ASYNC_QUEUE_ACTION_THAW, ASYNC_QUEUE_STATUS_SHUTDOWN }, { ASYNC_QUEUE_STATUS_SHUTDOWN, ASYNC_QUEUE_ACTION_SHUTDOWN, ASYNC_QUEUE_STATUS_SHUTDOWN }, };
//---[ CAsyncQueueBase::getTransitionTable ]------------
//
//
// Description:
// returns the state transition table and its size to
// CStateMachineBase whenever needed.
// Parameters:
// - ppTransitionTable pointer to the state transition table
// pdwNumTransitions pointer to the number of transitions in
// the table
// Returns:
// -
// History:
// 6/5/2000 - t-toddc Created
// 12/11/2000 - MikeSwa Merged for Hg checkin
//
//------------------------------------------------------------------
void CAsyncQueueBase::getTransitionTable(const STATE_TRANSITION** ppTransitionTable, DWORD* pdwNumTransitions) { TraceFunctEnter("CAsyncQueueStateMachine::getTransitionTable"); ASSERT(ppTransitionTable && "NULL transition table pointer"); ASSERT(pdwNumTransitions && "NULL num transitions pointer"); ASSERT(s_rgTransitionTable && "transition table uninitialized");
// bail on bad input or no good transition table
if (!ppTransitionTable || !pdwNumTransitions || !s_rgTransitionTable) goto Exit;
*ppTransitionTable = s_rgTransitionTable; *pdwNumTransitions = sizeof(CAsyncQueueBase::s_rgTransitionTable) / sizeof(STATE_TRANSITION);
Exit: TraceFunctLeave(); }
//---[ CAsyncQueueBase::ThreadPoolInitialize ]---------------------------------
//
//
// Description:
// Performs static ATQ initialization. This call is ref-counted. If
// it succeeds, the caller should call ThreadPoolDeinitialze();
// Parameters:
// -
// Returns:
// -
// History:
// 3/30/2000 - MikeSwa Created
//
//-----------------------------------------------------------------------------
void CAsyncQueueBase::ThreadPoolInitialize() { TraceFunctEnterEx((LPARAM) this, "CAsyncQueueBase::ThreadPoolInitialize"); DWORD cATQMaxAsyncThreads = 0; DWORD cATQMaxTotalAsyncThreads = 0; DWORD cOurMaxAsyncThreads = 0; SYSTEM_INFO sinf;
//
// On 0 -> 1 transition, adjust ATQ according to our config
//
if (!s_cAsyncQueueStaticInitRefCount) { //
// Get max threads per proc
//
cATQMaxAsyncThreads = (DWORD)AtqGetInfo(AtqMaxPoolThreads); _ASSERT(cATQMaxAsyncThreads && "AtqGetInfo says there are no threads!"); if (!cATQMaxAsyncThreads) cATQMaxAsyncThreads = 1;
cOurMaxAsyncThreads = cATQMaxAsyncThreads;
//
// Adjust value by our config value
//
cOurMaxAsyncThreads += g_cPerProcMaxThreadPoolModifier;
//
// Get # of procs (using GetSystemInfo)
//
GetSystemInfo(&sinf); cOurMaxAsyncThreads *= sinf.dwNumberOfProcessors;
//
// We will throttle our requests at g_cMaxATQPercent
// the max number of ATQ threads
//
cOurMaxAsyncThreads = (g_cMaxATQPercent*cOurMaxAsyncThreads)/100;
if (!cOurMaxAsyncThreads) cOurMaxAsyncThreads = 1;
//
// Set static so people later on can use this calculation
//
s_cDefaultMaxAsyncThreads = cOurMaxAsyncThreads;
//
// Now we need to adjust our threads
//
s_cMaxPerProcATQThreadAdjustment = g_cPerProcMaxThreadPoolModifier;
//
// Per proc thread limit
//
if (s_cMaxPerProcATQThreadAdjustment) { AtqSetInfo(AtqMaxPoolThreads, cATQMaxAsyncThreads + s_cMaxPerProcATQThreadAdjustment); DebugTrace((LPARAM) this, "Adjusting per proc ATQ thread limit by %d (orig %d)", s_cMaxPerProcATQThreadAdjustment, cATQMaxAsyncThreads); }
_ASSERT(!(0xFF000000 & cOurMaxAsyncThreads)); //sanity check number
}
s_cAsyncQueueStaticInitRefCount++;
TraceFunctLeave(); }
//---[ CAsyncQueueBase::ThreadPoolDeinitialize ]-------------------------------
//
//
// Description:
// Will re-adjust ATQ data if we changed them during initialization
// Parameters:
// -
// Returns:
// -
// History:
// 3/30/2000 - MikeSwa Created
//
//-----------------------------------------------------------------------------
void CAsyncQueueBase::ThreadPoolDeinitialize() { TraceFunctEnterEx((LPARAM) this, "CAsyncQueueBase::ThreadPoolDeinitialize"); DWORD cATQMaxAsyncThreads = 0; DWORD cATQMaxTotalAsyncThreads = 0;
_ASSERT(s_cAsyncQueueStaticInitRefCount != 0); s_cAsyncQueueStaticInitRefCount--;
//
// If this is the last queue, adjust our configuration so back to
// the way we found it.
//
if (!s_cAsyncQueueStaticInitRefCount) { cATQMaxAsyncThreads = (DWORD)AtqGetInfo(AtqMaxPoolThreads); cATQMaxTotalAsyncThreads = (DWORD) AtqGetInfo(AtqMaxThreadLimit);
//
// Reset per-proc threads if it makes sense
//
if (s_cMaxPerProcATQThreadAdjustment && (cATQMaxAsyncThreads > s_cMaxPerProcATQThreadAdjustment)) { AtqSetInfo(AtqMaxPoolThreads, cATQMaxAsyncThreads - s_cMaxPerProcATQThreadAdjustment);
DebugTrace((LPARAM) this, "Resetting ATQ Max per proc threads to %d", cATQMaxAsyncThreads - s_cMaxPerProcATQThreadAdjustment);
s_cMaxPerProcATQThreadAdjustment = 0; }
}
// Verify that m_cThreadsNeeded has reached zero
_ASSERT(!m_cThreadsNeeded);
TraceFunctLeave(); }
|