|
|
/*++
Copyright (c) 1998-2001 Microsoft Corporation
Module Name:
counters.cxx
Abstract:
Contains the performance monitoring counter management code
Author:
Eric Stenson (ericsten) 25-Sep-2000
Revision History:
--*/
#include "precomp.h"
#include "countersp.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text( INIT, UlInitializeCounters )
#pragma alloc_text( PAGE, UlTerminateCounters )
#pragma alloc_text( PAGE, UlCreateSiteCounterEntry )
#if REFERENCE_DEBUG
#pragma alloc_text( PAGE, UlReferenceSiteCounterEntry )
#pragma alloc_text( PAGE, UlDereferenceSiteCounterEntry )
#endif
#pragma alloc_text( PAGE, UlGetGlobalCounters )
#pragma alloc_text( PAGE, UlGetSiteCounters )
#endif // ALLOC_PRAGMA
#if 0
NOT PAGEABLE -- UlIncCounter NOT PAGEABLE -- UlDecCounter NOT PAGEABLE -- UlAddCounter NOT PAGEABLE -- UlResetCounter
NOT PAGEABLE -- UlIncSiteCounter NOT PAGEABLE -- UlDecSiteCounter NOT PAGEABLE -- UlAddSiteCounter NOT PAGEABLE -- UlResetSiteCounter NOT PAGEABLE -- UlMaxSiteCounter NOT PAGEABLE -- UlMaxSiteCounter64 #endif
BOOLEAN g_InitCountersCalled = FALSE; HTTP_GLOBAL_COUNTERS g_UlGlobalCounters; FAST_MUTEX g_SiteCounterListMutex; LIST_ENTRY g_SiteCounterListHead = {NULL,NULL}; LONG g_SiteCounterListCount = 0;
/***************************************************************************++
Routine Description:
Performs global initialization of the global (cache) and instance (per site) counters.
Return Value:
NTSTATUS - Completion status.
--***************************************************************************/ NTSTATUS UlInitializeCounters( VOID ) { NTSTATUS Status = STATUS_SUCCESS;
//
// Sanity check.
//
PAGED_CODE();
ASSERT( !g_InitCountersCalled );
UlTrace(PERF_COUNTERS, ("http!UlInitializeCounters\n"));
if (!g_InitCountersCalled) { //
// zero out global counter block
//
RtlZeroMemory(&g_UlGlobalCounters, sizeof(HTTP_GLOBAL_COUNTERS));
//
// init Site Counter list
//
ExInitializeFastMutex(&g_SiteCounterListMutex); InitializeListHead(&g_SiteCounterListHead); g_SiteCounterListCount = 0;
// done!
g_InitCountersCalled = TRUE; }
RETURN( Status );
} // UlInitializeCounters
/***************************************************************************++
Routine Description:
Performs global cleanup of the global (cache) and instance (per site) counters.
--***************************************************************************/ VOID UlTerminateCounters( VOID ) { //
// [debug only] Walk list of counters and check the ref count for each counter block.
//
#if DBG
PLIST_ENTRY pEntry; PUL_SITE_COUNTER_ENTRY pCounterEntry;
if (!g_InitCountersCalled) { goto End; }
if (IsListEmpty(&g_SiteCounterListHead)) { ASSERT(0 == g_SiteCounterListCount); // Good! No counters left behind!
goto End; }
//
// Walk list of Site Counter Entries
//
pEntry = g_SiteCounterListHead.Flink; while (pEntry != &g_SiteCounterListHead) { pCounterEntry = CONTAINING_RECORD( pEntry, UL_SITE_COUNTER_ENTRY, ListEntry );
ASSERT(IS_VALID_SITE_COUNTER_ENTRY(pCounterEntry));
UlTrace(PERF_COUNTERS, ("http!UlTerminateCounters: Error: pCounterEntry %p SiteId %d RefCount %d\n", pCounterEntry, pCounterEntry->Counters.SiteId, pCounterEntry->RefCount ));
pEntry = pEntry->Flink; }
End: return; #endif // DBG
}
///////////////////////////////////////////////////////////////////////////////
// Site Counter Entry
//
/***************************************************************************++
Routine Description:
Creates a new site counter entry for the given SiteId.
Arguments:
SiteId - the site id for the site counters.
Return Value:
NTSTATUS - Completion status.
--***************************************************************************/ NTSTATUS UlCreateSiteCounterEntry( IN OUT PUL_CONFIG_GROUP_OBJECT pConfigGroup, ULONG SiteId ) { NTSTATUS Status; PUL_SITE_COUNTER_ENTRY pNewEntry;
//
// Sanity check.
//
PAGED_CODE();
ASSERT( pConfigGroup != NULL );
//
// Setup locals so we know how to cleanup on exit.
//
Status = STATUS_SUCCESS;
//
// [debug only] Check to see if the SiteId is already
// in the list of existing Site Counter Entries.
//
ASSERT(!UlpIsInSiteCounterList(SiteId));
// Alloc new struct w/space from Non Paged Pool
pNewEntry = UL_ALLOCATE_STRUCT( NonPagedPool, UL_SITE_COUNTER_ENTRY, UL_SITE_COUNTER_ENTRY_POOL_TAG); if (pNewEntry) {
UlTrace( PERF_COUNTERS, ("http!UlCreateSiteCounterEntry: pNewEntry %p, pConfigGroup %p, SiteId %d\n", pNewEntry, pConfigGroup, SiteId ) );
pNewEntry->Signature = UL_SITE_COUNTER_ENTRY_POOL_TAG;
pNewEntry->RefCount = 1;
// Zero out counters
RtlZeroMemory(&(pNewEntry->Counters), sizeof(HTTP_SITE_COUNTERS));
// Set Site ID
pNewEntry->Counters.SiteId = SiteId;
// Init Counter Mutex
ExInitializeFastMutex(&(pNewEntry->EntryMutex));
// Add to Site Counter List
ExAcquireFastMutex(&g_SiteCounterListMutex);
InsertTailList( &g_SiteCounterListHead, &(pNewEntry->ListEntry) ); g_SiteCounterListCount++;
ExReleaseFastMutex(&g_SiteCounterListMutex);
// Check for wrap-around of Site List count.
ASSERT( 0 != g_SiteCounterListCount ); } else { UlTrace( PERF_COUNTERS, ("http!UlCreateSiteCounterEntry: Error: NO_MEMORY pConfigGroup %p, SiteId %d\n", pNewEntry, pConfigGroup, SiteId ) );
Status = STATUS_NO_MEMORY; }
pConfigGroup->pSiteCounters = pNewEntry;
RETURN( Status ); }
#if REFERENCE_DEBUG
/***************************************************************************++
Routine Description:
increments the refcount.
Arguments:
pEntry - the object to increment.
Return Value:
NTSTATUS - Completion status.
--***************************************************************************/ VOID UlReferenceSiteCounterEntry( IN PUL_SITE_COUNTER_ENTRY pEntry REFERENCE_DEBUG_FORMAL_PARAMS ) { LONG refCount;
//
// Sanity check.
//
PAGED_CODE();
ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
refCount = InterlockedIncrement( &pEntry->RefCount );
//
// Tracing.
//
WRITE_REF_TRACE_LOG( g_pSiteCounterTraceLog, REF_ACTION_REFERENCE_SITE_COUNTER_ENTRY, refCount, pEntry, pFileName, LineNumber );
UlTrace( REFCOUNT, ("http!UlReferenceSiteCounterEntry pEntry=%p refcount=%d SiteId=%d\n", pEntry, refCount, pEntry->Counters.SiteId) );
} // UlReferenceAppPool
/***************************************************************************++
Routine Description:
decrements the refcount. if it hits 0, destruct's the site counter entry block.
Arguments:
pEntry - the object to decrement.
Return Value:
NTSTATUS - Completion status.
--***************************************************************************/ VOID UlDereferenceSiteCounterEntry( IN PUL_SITE_COUNTER_ENTRY pEntry REFERENCE_DEBUG_FORMAL_PARAMS ) { LONG refCount; NTSTATUS Status;
//
// Sanity check.
//
PAGED_CODE();
ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
refCount = InterlockedDecrement( &pEntry->RefCount );
//
// Tracing.
//
WRITE_REF_TRACE_LOG( g_pSiteCounterTraceLog, REF_ACTION_DEREFERENCE_SITE_COUNTER_ENTRY, refCount, pEntry, pFileName, LineNumber );
UlTrace( REFCOUNT, ("http!UlDereferenceSiteCounter pEntry=%p refcount=%d SiteId=%d\n", pEntry, refCount, pEntry->Counters.SiteId) );
//
// Remove from the list if we hit zero
//
if (refCount == 0) { ASSERT( 0 != g_SiteCounterListCount );
UlTrace( PERF_COUNTERS, ("http!UlDereferenceSiteCounter: Removing pEntry=%p SiteId=%d\n", pEntry, pEntry->Counters.SiteId) );
// Remove from list
ExAcquireFastMutex(&g_SiteCounterListMutex);
RemoveEntryList(&pEntry->ListEntry); pEntry->ListEntry.Flink = pEntry->ListEntry.Blink = NULL; g_SiteCounterListCount--;
ExReleaseFastMutex(&g_SiteCounterListMutex);
// Release memory
UL_FREE_POOL_WITH_SIG(pEntry, UL_SITE_COUNTER_ENTRY_POOL_TAG);
}
} #endif
///////////////////////////////////////////////////////////////////////////////
// Collection
//
/***************************************************************************++
Routine Description:
Gets the Global (cache) counters.
Arguments: pCounter - pointer to block of memory where the counter data should be written.
BlockSize - Maximum size available at pCounter.
pBytesWritten - On success, count of bytes written into the block of memory at pCounter. On failure, the required count of bytes for the memory at pCounter.
Return Value:
NTSTATUS - Completion status.
--***************************************************************************/ NTSTATUS UlGetGlobalCounters( PVOID IN OUT pCounter, ULONG IN BlockSize, PULONG OUT pBytesWritten ) { ULONG i;
PAGED_CODE();
ASSERT( pBytesWritten );
UlTraceVerbose(PERF_COUNTERS, ("http!UlGetGlobalCounters\n"));
if (BlockSize < sizeof(HTTP_GLOBAL_COUNTERS)) { //
// Tell the caller how many bytes are required.
//
*pBytesWritten = sizeof(HTTP_GLOBAL_COUNTERS); RETURN( STATUS_BUFFER_TOO_SMALL ); }
RtlCopyMemory( pCounter, &g_UlGlobalCounters, sizeof(g_UlGlobalCounters) );
//
// Zero out any counters that must be zeroed.
//
for ( i = 0; i < HttpGlobalCounterMaximum; i++ ) { if (TRUE == aIISULGlobalDescription[i].WPZeros) { // Zero it out
UlResetCounter((HTTP_GLOBAL_COUNTER_ID) i); } }
*pBytesWritten = sizeof(HTTP_GLOBAL_COUNTERS);
RETURN( STATUS_SUCCESS );
} // UlpGetGlobalCounters
/***************************************************************************++
Routine Description:
Gets the Site (instance) counters for all sites
Arguments:
pCounter - pointer to block of memory where the counter data should be written.
BlockSize - Maximum size available at pCounter.
pBytesWritten - On success, count of bytes written into the block of memory at pCounter. On failure, the required count of bytes for the memory at pCounter.
pBlocksWritten - (optional) On success, count of site counter blocks written to pCounter.
Return Value:
NTSTATUS - Completion status.
--***************************************************************************/ NTSTATUS UlGetSiteCounters( PVOID IN OUT pCounter, ULONG IN BlockSize, PULONG OUT pBytesWritten, PULONG OUT pBlocksWritten OPTIONAL ) { NTSTATUS Status; ULONG i; ULONG BytesNeeded; ULONG BytesToGo; ULONG BlocksSeen; PUCHAR pBlock; PLIST_ENTRY pEntry; PUL_SITE_COUNTER_ENTRY pCounterEntry;
PAGED_CODE();
ASSERT( pBytesWritten );
UlTraceVerbose(PERF_COUNTERS, ("http!UlGetSiteCounters\n"));
//
// Setup locals so we know how to cleanup on exit.
//
Status = STATUS_SUCCESS; BytesToGo = BlockSize; BlocksSeen = 0; pBlock = (PUCHAR) pCounter;
BytesNeeded = g_SiteCounterListCount * sizeof(HTTP_SITE_COUNTERS);
if (BytesNeeded > BlockSize) { // Need more space
*pBytesWritten = BytesNeeded; Status = STATUS_BUFFER_TOO_SMALL; goto End; }
if (IsListEmpty(&g_SiteCounterListHead)) { // No counters to return.
goto End; }
//
// NOTE: g_SiteCounterListHead is the only member of
// the list which isn't contained within a UL_SITE_COUNTER_ENTRY.
//
pEntry = g_SiteCounterListHead.Flink;
//
// Walk list of Site Counter Entries
//
while (pEntry != &g_SiteCounterListHead) { pCounterEntry = CONTAINING_RECORD( pEntry, UL_SITE_COUNTER_ENTRY, ListEntry );
if (BytesToGo < sizeof(HTTP_SITE_COUNTERS)) { // NOTE: the only way this can happen is if someone
// added a site to the end of the site list before
// we finished walking the counter list.
*pBytesWritten = BlockSize + sizeof(HTTP_SITE_COUNTERS); Status = STATUS_BUFFER_TOO_SMALL; goto End; }
RtlCopyMemory(pBlock, &(pCounterEntry->Counters), sizeof(HTTP_SITE_COUNTERS) );
//
// Zero out any counters that must be zeroed.
//
for ( i = 0; i < HttpSiteCounterMaximum; i++ ) { if (TRUE == aIISULSiteDescription[i].WPZeros) { // Zero it out
UlResetSiteCounter(pCounterEntry, (HTTP_SITE_COUNTER_ID) i); } }
//
// Continue to next block
//
pBlock += sizeof(HTTP_SITE_COUNTERS); BytesToGo -= sizeof(HTTP_SITE_COUNTERS); BlocksSeen++;
pEntry = pEntry->Flink; }
End:
//
// Set callers values
//
if (STATUS_SUCCESS == Status) { // REVIEW: If we failed, *pBytesWritten already contains
// the bytes required value.
*pBytesWritten = DIFF(pBlock - ((PUCHAR)pCounter)); }
if (pBlocksWritten) { *pBlocksWritten = BlocksSeen; }
RETURN( Status );
} // UlpGetSiteCounters
#if REFERENCE_DEBUG
///////////////////////////////////////////////////////////////////////////////
// Global Counter functions
//
/***************************************************************************++
Routine Description:
Increment a Global (cache) performance counter.
Arguments:
Ctr - ID of Counter to increment
--***************************************************************************/ VOID UlIncCounter( HTTP_GLOBAL_COUNTER_ID Ctr ) { PCHAR pCtr;
ASSERT( g_InitCountersCalled ); ASSERT( Ctr < HttpGlobalCounterMaximum ); // REVIEW: signed/unsigned issues?
UlTraceVerbose( PERF_COUNTERS, ("http!UlIncCounter (Ctr == %d)\n", Ctr) );
//
// figure out offset of Ctr in g_UlGlobalCounters
//
pCtr = (PCHAR) &g_UlGlobalCounters; pCtr += aIISULGlobalDescription[Ctr].Offset;
// figure out data size of Ctr and do
// apropriate thread-safe increment
if (sizeof(ULONG) == aIISULGlobalDescription[Ctr].Size) { // ULONG
InterlockedIncrement((PLONG) pCtr); } else { // ULONGLONG
UlInterlockedIncrement64((PLONGLONG) pCtr); }
} // UlIncCounter
/***************************************************************************++
Routine Description:
Decrement a Global (cache) performance counter.
Arguments:
Ctr - ID of Counter to decrement
--***************************************************************************/ VOID UlDecCounter( HTTP_GLOBAL_COUNTER_ID Ctr ) { PCHAR pCtr;
ASSERT( g_InitCountersCalled ); ASSERT( Ctr < HttpGlobalCounterMaximum ); // REVIEW: signed/unsigned issues?
UlTraceVerbose( PERF_COUNTERS, ("http!UlDecCounter (Ctr == %d)\n", Ctr)); //
// figure out offset of Ctr in g_UlGlobalCounters
//
pCtr = (PCHAR) &g_UlGlobalCounters; pCtr += aIISULGlobalDescription[Ctr].Offset;
// figure out data size of Ctr and do
// apropriate thread-safe increment
if (sizeof(ULONG) == aIISULGlobalDescription[Ctr].Size) { // ULONG
InterlockedDecrement((PLONG) pCtr); } else { // ULONGLONG
UlInterlockedDecrement64((PLONGLONG) pCtr); } }
/***************************************************************************++
Routine Description:
Add a ULONG value to a Global (cache) performance counter.
Arguments:
Ctr - ID of counter to which the Value should be added
Value - The amount to add to the counter
--***************************************************************************/ VOID UlAddCounter( HTTP_GLOBAL_COUNTER_ID Ctr, ULONG Value ) { PCHAR pCtr;
ASSERT( g_InitCountersCalled ); ASSERT( Ctr < HttpGlobalCounterMaximum ); // REVIEW: signed/unsigned issues?
UlTraceVerbose( PERF_COUNTERS, ("http!UlAddCounter (Ctr == %d, Value == %d)\n", Ctr, Value)); //
// figure out offset of Ctr in g_UlGlobalCounters
//
pCtr = (PCHAR) &g_UlGlobalCounters; pCtr += aIISULGlobalDescription[Ctr].Offset;
//
// figure out data size of Ctr and do
// apropriate thread-safe increment
//
if (sizeof(ULONG) == aIISULGlobalDescription[Ctr].Size) { // ULONG
InterlockedExchangeAdd((PLONG) pCtr, Value); } else { // ULONGLONG
UlInterlockedAdd64((PLONGLONG) pCtr, Value); }
} // UlAddCounter
/***************************************************************************++
Routine Description:
Zero-out a Global (cache) performance counter.
Arguments:
Ctr - ID of Counter to be reset.
--***************************************************************************/ VOID UlResetCounter( HTTP_GLOBAL_COUNTER_ID Ctr ) { // Special Case
PCHAR pCtr;
ASSERT( g_InitCountersCalled ); ASSERT( Ctr < HttpGlobalCounterMaximum ); // REVIEW: signed/unsigned issues?
UlTraceVerbose(PERF_COUNTERS, ("http!UlResetCounter (Ctr == %d)\n", Ctr)); //
// figure out offset of Ctr in g_UlGlobalCounters
//
pCtr = (PCHAR) &g_UlGlobalCounters; pCtr += aIISULGlobalDescription[Ctr].Offset;
//
// do apropriate "set" for data size of Ctr
//
if (sizeof(ULONG) == aIISULGlobalDescription[Ctr].Size) { // ULONG
InterlockedExchange((PLONG) pCtr, 0); } else { // ULONGLONG
LONGLONG localCtr; LONGLONG originalCtr; LONGLONG localZero = 0;
do {
localCtr = *((volatile LONGLONG *) pCtr);
originalCtr = InterlockedCompareExchange64( (PLONGLONG) pCtr, localZero, localCtr );
} while (originalCtr != localCtr);
} } // UlResetCounter
///////////////////////////////////////////////////////////////////////////////
// Site Counter functions
//
/***************************************************************************++
Routine Description:
Increment a NonCritical Site performance counter.
Arguments:
pEntry - pointer to Site Counter entry
CounterId - ID of Counter to increment
Returns:
Nothing
--***************************************************************************/ VOID UlIncSiteNonCriticalCounterUlong( PUL_SITE_COUNTER_ENTRY pEntry, HTTP_SITE_COUNTER_ID CounterId ) { PCHAR pCounter; PLONG plValue;
pCounter = (PCHAR) &(pEntry->Counters); pCounter += aIISULSiteDescription[CounterId].Offset;
plValue = (PLONG) pCounter; ++(*plValue); }
/***************************************************************************++
Routine Description:
Increment a NonCritical Site performance counter.
Arguments:
pEntry - pointer to Site Counter entry
CounterId - ID of Counter to increment
Returns:
Nothing
--***************************************************************************/ VOID UlIncSiteNonCriticalCounterUlonglong( PUL_SITE_COUNTER_ENTRY pEntry, HTTP_SITE_COUNTER_ID CounterId ) { PCHAR pCounter; PLONGLONG pllValue;
pCounter = (PCHAR) &(pEntry->Counters); pCounter += aIISULSiteDescription[CounterId].Offset;
pllValue = (PLONGLONG) pCounter; ++(*pllValue); }
/***************************************************************************++
Routine Description:
Increment a Site performance counter.
Arguments:
pEntry - pointer to Site Counter entry
Ctr - ID of Counter to increment
Returns:
Value of counter after incrementing
--***************************************************************************/ LONGLONG UlIncSiteCounter( PUL_SITE_COUNTER_ENTRY pEntry, HTTP_SITE_COUNTER_ID Ctr ) { PCHAR pCtr; LONGLONG llValue;
ASSERT( g_InitCountersCalled ); ASSERT( Ctr < HttpSiteCounterMaximum ); // REVIEW: signed/unsigned issues?
ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
UlTraceVerbose( PERF_COUNTERS, ("http!UlIncSiteCounter Ctr=%d SiteId=%d\n", Ctr, pEntry->Counters.SiteId ));
//
// figure out offset of Ctr in HTTP_SITE_COUNTERS
//
pCtr = (PCHAR) &(pEntry->Counters); pCtr += aIISULSiteDescription[Ctr].Offset;
// figure out data size of Ctr and do
// apropriate thread-safe increment
if (sizeof(ULONG) == aIISULSiteDescription[Ctr].Size) { // ULONG
llValue = (LONGLONG) InterlockedIncrement((PLONG) pCtr); } else { // ULONGLONG
llValue = UlInterlockedIncrement64((PLONGLONG) pCtr); }
return llValue; }
/***************************************************************************++
Routine Description:
Decrement a Site performance counter.
Arguments:
pEntry - pointer to Site Counter entry
Ctr - ID of Counter to decrement
--***************************************************************************/ VOID UlDecSiteCounter( PUL_SITE_COUNTER_ENTRY pEntry, HTTP_SITE_COUNTER_ID Ctr ) { PCHAR pCtr;
ASSERT( g_InitCountersCalled ); ASSERT( Ctr < HttpSiteCounterMaximum ); // REVIEW: signed/unsigned issues?
ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
UlTraceVerbose( PERF_COUNTERS, ("http!UlDecSiteCounter Ctr=%d SiteId=%d\n", Ctr, pEntry->Counters.SiteId ));
//
// figure out offset of Ctr in HTTP_SITE_COUNTERS
//
pCtr = (PCHAR) &(pEntry->Counters); pCtr += aIISULSiteDescription[Ctr].Offset;
// figure out data size of Ctr and do
// apropriate thread-safe increment
if (sizeof(ULONG) == aIISULSiteDescription[Ctr].Size) { // ULONG
InterlockedDecrement((PLONG) pCtr); } else { // ULONGLONG
UlInterlockedDecrement64((PLONGLONG) pCtr); } }
/***************************************************************************++
Routine Description:
Add a ULONG value to a 32-bit site performance counter.
Arguments:
pEntry - pointer to Site Counter entry
Ctr - ID of counter to which the Value should be added
Value - The amount to add to the counter
--***************************************************************************/ VOID UlAddSiteCounter( PUL_SITE_COUNTER_ENTRY pEntry, HTTP_SITE_COUNTER_ID Ctr, ULONG Value ) { PCHAR pCtr;
ASSERT( g_InitCountersCalled ); ASSERT( Ctr < HttpSiteCounterMaximum ); // REVIEW: signed/unsigned issues?
ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
UlTraceVerbose( PERF_COUNTERS, ("http!UlAddSiteCounter Ctr=%d SiteId=%d Value=%d\n", Ctr, pEntry->Counters.SiteId, Value ));
//
// figure out offset of Ctr in HTTP_SITE_COUNTERS
//
pCtr = (PCHAR) &(pEntry->Counters); pCtr += aIISULSiteDescription[Ctr].Offset;
// figure out data size of Ctr and do
// apropriate thread-safe increment
ASSERT(sizeof(ULONG) == aIISULSiteDescription[Ctr].Size); InterlockedExchangeAdd((PLONG) pCtr, Value); }
/***************************************************************************++
Routine Description:
Add a ULONGLONG value to a 64-bit site performance counter.
Arguments:
pEntry - pointer to Site Counter entry
Ctr - ID of counter to which the Value should be added
Value - The amount to add to the counter
--***************************************************************************/ VOID UlAddSiteCounter64( PUL_SITE_COUNTER_ENTRY pEntry, HTTP_SITE_COUNTER_ID Ctr, ULONGLONG llValue ) { PCHAR pCtr;
ASSERT( g_InitCountersCalled ); ASSERT( Ctr < HttpSiteCounterMaximum ); // REVIEW: signed/unsigned issues?
ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
UlTraceVerbose( PERF_COUNTERS, ("http!UlAddSiteCounter64 Ctr=%d SiteId=%d Value=%I64d\n", Ctr, pEntry->Counters.SiteId, llValue ));
//
// figure out offset of Ctr in HTTP_SITE_COUNTERS
//
pCtr = (PCHAR) &(pEntry->Counters); pCtr += aIISULSiteDescription[Ctr].Offset;
ASSERT(sizeof(ULONGLONG) == aIISULSiteDescription[Ctr].Size); UlInterlockedAdd64((PLONGLONG) pCtr, llValue); }
/***************************************************************************++
Routine Description:
Reset a Site performance counter.
Arguments:
pEntry - pointer to Site Counter entry
Ctr - ID of counter to be reset
--***************************************************************************/ VOID UlResetSiteCounter( PUL_SITE_COUNTER_ENTRY pEntry, HTTP_SITE_COUNTER_ID Ctr ) { PCHAR pCtr;
ASSERT( g_InitCountersCalled ); ASSERT( Ctr < HttpSiteCounterMaximum ); // REVIEW: signed/unsigned issues?
ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
UlTraceVerbose( PERF_COUNTERS, ("http!UlResetSiteCounter Ctr=%d SiteId=%d\n", Ctr, pEntry->Counters.SiteId ));
//
// figure out offset of Ctr in HTTP_SITE_COUNTERS
//
pCtr = (PCHAR) &(pEntry->Counters); pCtr += aIISULSiteDescription[Ctr].Offset;
//
// do apropriate "set" for data size of Ctr
//
if (sizeof(ULONG) == aIISULSiteDescription[Ctr].Size) { // ULONG
InterlockedExchange((PLONG) pCtr, 0); } else { // ULONGLONG
LONGLONG localCtr; LONGLONG originalCtr; LONGLONG localZero = 0;
do {
localCtr = *((volatile LONGLONG *) pCtr);
originalCtr = InterlockedCompareExchange64( (PLONGLONG) pCtr, localZero, localCtr );
} while (originalCtr != localCtr);
}
}
/***************************************************************************++
Routine Description:
Determine if a new maximum value of a Site performance counter has been hit and set the counter to the new maximum if necessary. (ULONG version)
Arguments:
pEntry - pointer to Site Counter entry
Ctr - ID of counter
Value - possible new maximum (NOTE: Assumes that the counter Ctr is a 32-bit value)
--***************************************************************************/ VOID UlMaxSiteCounter( PUL_SITE_COUNTER_ENTRY pEntry, HTTP_SITE_COUNTER_ID Ctr, ULONG Value ) { PCHAR pCtr;
ASSERT( g_InitCountersCalled ); ASSERT( Ctr < HttpSiteCounterMaximum ); // REVIEW: signed/unsigned issues?
ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
UlTraceVerbose( PERF_COUNTERS, ("http!UlMaxSiteCounter Ctr=%d SiteId=%d Value=%d\n", Ctr, pEntry->Counters.SiteId, Value ));
//
// figure out offset of Ctr in HTTP_SITE_COUNTERS
//
pCtr = (PCHAR) &(pEntry->Counters); pCtr += aIISULSiteDescription[Ctr].Offset;
// Grab counter block mutex
ExAcquireFastMutex(&pEntry->EntryMutex);
if (Value > (ULONG) *pCtr) { InterlockedExchange((PLONG) pCtr, Value); }
// Release counter block mutex
ExReleaseFastMutex(&pEntry->EntryMutex);
}
/***************************************************************************++
Routine Description:
Determine if a new maximum value of a Site performance counter has been hit and set the counter to the new maximum if necessary. (LONGLONG version)
Arguments:
pEntry - pointer to Site Counter entry
Ctr - ID of counter
Value - possible new maximum (NOTE: Assumes that the counter Ctr is a 64-bit value)
--***************************************************************************/ VOID UlMaxSiteCounter64( PUL_SITE_COUNTER_ENTRY pEntry, HTTP_SITE_COUNTER_ID Ctr, LONGLONG llValue ) { PCHAR pCtr;
ASSERT( g_InitCountersCalled ); ASSERT( Ctr < HttpSiteCounterMaximum ); // REVIEW: signed/unsigned issues?
ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
UlTraceVerbose( PERF_COUNTERS, ("http!UlMaxSiteCounter64 Ctr=%d SiteId=%d Value=%I64d\n", Ctr, pEntry->Counters.SiteId, llValue ));
//
// figure out offset of Ctr in HTTP_SITE_COUNTERS
//
pCtr = (PCHAR) &(pEntry->Counters); pCtr += aIISULSiteDescription[Ctr].Offset;
// Grab counter block mutex
ExAcquireFastMutex(&pEntry->EntryMutex);
if (llValue > (LONGLONG) *pCtr) { *((PLONGLONG) pCtr) = llValue; #if 0
// REVIEW: There *must* be a better way to do this...
// REVIEW: I want to do: (LONGLONG) *pCtr = llValue;
// REVIEW: But casting something seems to make it a constant.
// REVIEW: Also, there isn't an "InterlockedExchange64" for x86.
// REVIEW: Any suggestions? --EricSten
RtlCopyMemory( pCtr, &llValue, sizeof(LONGLONG) ); #endif // 0
}
// Release counter block mutex
ExReleaseFastMutex(&pEntry->EntryMutex);
} #endif
/***************************************************************************++
Routine Description:
Predicate to test if a site counter entry already exists for the given SiteId
Arguments:
SiteId - ID of site
Return Value:
TRUE if found
FALSE if not found
--***************************************************************************/ BOOLEAN UlpIsInSiteCounterList(ULONG SiteId) { PLIST_ENTRY pEntry; PUL_SITE_COUNTER_ENTRY pCounterEntry; BOOLEAN IsFound = FALSE;
if (IsListEmpty(&g_SiteCounterListHead)) { ASSERT(0 == g_SiteCounterListCount); // Good! No counters left behind!
goto End; }
//
// Walk list of Site Counter Entries
//
pEntry = g_SiteCounterListHead.Flink; while (pEntry != &g_SiteCounterListHead) { pCounterEntry = CONTAINING_RECORD( pEntry, UL_SITE_COUNTER_ENTRY, ListEntry );
ASSERT(IS_VALID_SITE_COUNTER_ENTRY(pCounterEntry));
if (SiteId == pCounterEntry->Counters.SiteId) { IsFound = TRUE; goto End; }
pEntry = pEntry->Flink; }
End: return IsFound;
}
|