Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1286 lines
31 KiB

/*++
Copyright (c) 1998-2002 Microsoft Corporation
Module Name:
counters.c
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, UlDbgReferenceSiteCounterEntry )
#pragma alloc_text( PAGE, UlDbgDereferenceSiteCounterEntry )
#endif
#pragma alloc_text( PAGE, UlGetGlobalCounters )
#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
NOT PAGEABLE -- UlGetSiteCounters
#endif
BOOLEAN g_InitCountersCalled = FALSE;
HTTP_GLOBAL_COUNTERS g_UlGlobalCounters;
FAST_MUTEX g_SiteCounterListMutex;
LIST_ENTRY g_SiteCounterListHead;
LONG g_SiteCounterListCount;
/***************************************************************************++
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 Global 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;
BOOLEAN MutexTaken = FALSE;
if (!g_InitCountersCalled)
{
goto End;
}
// Take Site Counter List Mutex
ExAcquireFastMutex(&g_SiteCounterListMutex);
MutexTaken = TRUE;
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,
GlobalListEntry
);
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:
if (MutexTaken)
{
ExReleaseFastMutex(&g_SiteCounterListMutex);
}
return;
#endif // DBG
}
///////////////////////////////////////////////////////////////////////////////
// Site Counter Entry
//
/***************************************************************************++
Routine Description:
Creates a new site counter entry for the given SiteId.
This code assumes that the config group is strictly "contained" by the
control channel. In other words, if a config group exists, it will ALWAYS
have a valid control channel.
Arguments:
pConfigGroup - The Config group on which to add the new Site Counter block
SiteId - The site id for the site counters. Does not need to be unique.
Return Value:
NTSTATUS - Completion status.
--***************************************************************************/
NTSTATUS
UlCreateSiteCounterEntry(
IN OUT PUL_CONFIG_GROUP_OBJECT pConfigGroup,
IN ULONG SiteId
)
{
NTSTATUS Status = STATUS_SUCCESS;
PUL_SITE_COUNTER_ENTRY pNewEntry;
PUL_CONTROL_CHANNEL pControlChannel;
//
// Sanity check.
//
PAGED_CODE();
ASSERT(IS_VALID_CONFIG_GROUP(pConfigGroup));
pControlChannel = pConfigGroup->pControlChannel;
ASSERT(IS_VALID_CONTROL_CHANNEL(pControlChannel));
//
// Make sure we don't clobber an existing one.
//
if( pConfigGroup->pSiteCounters )
{
UlTrace( PERF_COUNTERS,
("http!UlCreateSiteCounterEntry: Error: Site counter already exists on UL_CONFIG_GROUP_OBJECT %p\n",
pConfigGroup->pSiteCounters
));
return STATUS_OBJECTID_EXISTS;
}
//
// Check to see if the SiteId is already in the list of existing
// Site Counter Entries.
//
ASSERT(!UlpIsInSiteCounterList(pControlChannel, 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;
// Reference belongs to Config Group; covers the Control Channel's
// Site Counter List.
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(s)
//
ExAcquireFastMutex(&g_SiteCounterListMutex);
// Add to Global Site Counter List
InsertTailList(
&g_SiteCounterListHead,
&(pNewEntry->GlobalListEntry)
);
g_SiteCounterListCount++;
// Check for wrap-around of g_SiteCounterListCount
ASSERT( 0 != g_SiteCounterListCount );
// Add to Control Channel's Site Counter List
InsertTailList(
&pControlChannel->SiteCounterHead,
&(pNewEntry->ListEntry)
);
pControlChannel->SiteCounterCount++;
// Check for wrap-around of SiteCounterCount
ASSERT( 0 != pControlChannel->SiteCounterCount );
ExReleaseFastMutex(&g_SiteCounterListMutex);
}
else
{
UlTrace( PERF_COUNTERS,
("http!UlCreateSiteCounterEntry: Error: NO_MEMORY pConfigGroup %p, SiteId %d\n",
pNewEntry,
pConfigGroup,
SiteId )
);
Status = STATUS_NO_MEMORY;
}
pConfigGroup->pSiteCounters = pNewEntry;
if (pNewEntry)
{
// Rememeber Site ID
pConfigGroup->SiteId = SiteId;
}
RETURN( Status );
}
#if REFERENCE_DEBUG
/***************************************************************************++
Routine Description:
increments the refcount.
Arguments:
pEntry - the object to increment.
Return Value:
NTSTATUS - Completion status.
--***************************************************************************/
VOID
UlDbgReferenceSiteCounterEntry(
IN PUL_SITE_COUNTER_ENTRY pEntry
REFERENCE_DEBUG_FORMAL_PARAMS
)
{
//
// Sanity check.
//
PAGED_CODE();
ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
UlReferenceSiteCounterEntry(pEntry);
//
// Tracing.
//
WRITE_REF_TRACE_LOG(
g_pSiteCounterTraceLog,
REF_ACTION_REFERENCE_SITE_COUNTER_ENTRY,
pEntry->RefCount,
pEntry,
pFileName,
LineNumber
);
UlTrace(
REFCOUNT,
("http!UlReferenceSiteCounterEntry pEntry=%p refcount=%d SiteId=%d\n",
pEntry,
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
UlDbgDereferenceSiteCounterEntry(
IN PUL_SITE_COUNTER_ENTRY pEntry
REFERENCE_DEBUG_FORMAL_PARAMS
)
{
LONG refCount;
ULONG OldSiteId;
//
// Sanity check.
//
PAGED_CODE();
ASSERT( IS_VALID_SITE_COUNTER_ENTRY(pEntry) );
OldSiteId = pEntry->Counters.SiteId;
refCount = UlDereferenceSiteCounterEntry(pEntry);
//
// 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,
OldSiteId)
);
if (refCount == 0)
{
UlTrace(
PERF_COUNTERS,
("http!UlDereferenceSiteCounter: Removing pEntry=%p SiteId=%d\n",
pEntry,
OldSiteId)
);
}
}
#endif // REFERENCE_DEBUG
///////////////////////////////////////////////////////////////////////////////
// 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(
IN OUT PVOID pCounter,
IN ULONG BlockSize,
OUT PULONG pBytesWritten
)
{
PAGED_CODE();
ASSERT( pBytesWritten );
UlTraceVerbose(PERF_COUNTERS,
("http!UlGetGlobalCounters\n"));
if ( (BlockSize < sizeof(HTTP_GLOBAL_COUNTERS))
|| !pCounter )
{
//
// Tell the caller how many bytes are required.
//
*pBytesWritten = sizeof(HTTP_GLOBAL_COUNTERS);
RETURN( STATUS_BUFFER_OVERFLOW );
}
RtlCopyMemory(
pCounter,
&g_UlGlobalCounters,
sizeof(g_UlGlobalCounters)
);
*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(
IN PUL_CONTROL_CHANNEL pControlChannel,
IN OUT PVOID pCounter,
IN ULONG BlockSize,
OUT PULONG pBytesWritten,
OUT PULONG pBlocksWritten OPTIONAL
)
{
NTSTATUS Status;
ULONG i;
ULONG BytesNeeded;
ULONG BytesToGo;
ULONG BlocksSeen;
PUCHAR pBlock;
PLIST_ENTRY pEntry;
PUL_SITE_COUNTER_ENTRY pCounterEntry;
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;
// grab Site Counter Mutex
ExAcquireFastMutex(&g_SiteCounterListMutex);
BytesNeeded =
pControlChannel->SiteCounterCount * sizeof(HTTP_SITE_COUNTERS);
if ( (BytesNeeded > BlockSize)
|| !pCounter )
{
// Need more space
*pBytesWritten = BytesNeeded;
Status = STATUS_BUFFER_OVERFLOW;
goto End;
}
if (IsListEmpty(&pControlChannel->SiteCounterHead))
{
// No counters to return.
goto End;
}
//
// Walk list of Site Counter Entries
//
pEntry = pControlChannel->SiteCounterHead.Flink;
while (pEntry != &pControlChannel->SiteCounterHead)
{
pCounterEntry = CONTAINING_RECORD(
pEntry,
UL_SITE_COUNTER_ENTRY,
ListEntry
);
ASSERT(BytesToGo >= sizeof(HTTP_SITE_COUNTERS));
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:
// Release Mutex
ExReleaseFastMutex(&g_SiteCounterListMutex);
//
// 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 DBG
///////////////////////////////////////////////////////////////////////////////
// Global Counter functions
//
/***************************************************************************++
Routine Description:
Increment a Global (cache) performance counter.
Arguments:
Ctr - ID of Counter to increment
--***************************************************************************/
VOID
UlIncCounterDbg(
HTTP_GLOBAL_COUNTER_ID Ctr
)
{
ASSERT( g_InitCountersCalled );
ASSERT( Ctr < HttpGlobalCounterMaximum ); // REVIEW: signed/unsigned issues?
UlTraceVerbose( PERF_COUNTERS,
("http!UlIncCounter (Ctr == %d)\n", Ctr) );
UlIncCounterRtl(Ctr);
} // UlIncCounter
/***************************************************************************++
Routine Description:
Decrement a Global (cache) performance counter.
Arguments:
Ctr - ID of Counter to decrement
--***************************************************************************/
VOID
UlDecCounterDbg(
HTTP_GLOBAL_COUNTER_ID Ctr
)
{
ASSERT( g_InitCountersCalled );
ASSERT( Ctr < HttpGlobalCounterMaximum ); // REVIEW: signed/unsigned issues?
UlTraceVerbose( PERF_COUNTERS,
("http!UlDecCounter (Ctr == %d)\n", Ctr));
UlDecCounterRtl(Ctr);
}
/***************************************************************************++
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
UlAddCounterDbg(
HTTP_GLOBAL_COUNTER_ID Ctr,
ULONG Value
)
{
ASSERT( g_InitCountersCalled );
ASSERT( Ctr < HttpGlobalCounterMaximum ); // REVIEW: signed/unsigned issues?
UlTraceVerbose( PERF_COUNTERS,
("http!UlAddCounter (Ctr == %d, Value == %d)\n", Ctr, Value));
UlAddCounterRtl(Ctr, 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
)
{
ASSERT( g_InitCountersCalled );
ASSERT( Ctr < HttpGlobalCounterMaximum ); // REVIEW: signed/unsigned issues?
UlTraceVerbose(PERF_COUNTERS,
("http!UlResetCounter (Ctr == %d)\n", Ctr));
UlResetCounterRtl(Ctr);
} // UlResetCounter
///////////////////////////////////////////////////////////////////////////////
// Site Counter functions
//
// NOTE: There is no Dbg implementation for the following:
// UlIncSiteNonCriticalCounterUlong
// UlIncSiteNonCriticalCounterUlonglong
/***************************************************************************++
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
UlIncSiteCounterDbg(
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(
IN PUL_CONTROL_CHANNEL pControlChannel,
IN ULONG SiteId)
{
PLIST_ENTRY pEntry;
PUL_SITE_COUNTER_ENTRY pCounterEntry;
BOOLEAN IsFound = FALSE;
//
// Take Site Counter mutex
//
ExAcquireFastMutex(&g_SiteCounterListMutex);
if ( IsListEmpty(&pControlChannel->SiteCounterHead) )
{
ASSERT(0 == pControlChannel->SiteCounterCount);
// Good! No counters left behind!
goto End;
}
//
// Walk list of Site Counter Entries
//
pEntry = pControlChannel->SiteCounterHead.Flink;
while (pEntry != &pControlChannel->SiteCounterHead)
{
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:
//
// Release Site Counter mutex
//
ExReleaseFastMutex(&g_SiteCounterListMutex);
return IsFound;
}