mirror of https://github.com/tongzx/nt5src
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.
1421 lines
32 KiB
1421 lines
32 KiB
/*++
|
|
|
|
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;
|
|
|
|
}
|