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
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;
|
|
|
|
}
|