Windows2000/private/ntos/ex/callperf.c
2020-09-30 17:12:32 +02:00

91 lines
3.2 KiB
C

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
callperf.c
Abstract:
This module implements the functions necessary to collect call data.
Author:
David N. Cutler (davec) 22-May-1994
Environment:
Kernel mode only.
--*/
#include "exp.h"
VOID ExInitializeCallData (IN PCALL_PERFORMANCE_DATA CallData)
/*++
Routine Description:
This function initializes a call performance data structure.
Arguments:
CallData - Supplies a pointer to the call performance data structure that is initialized.
--*/
{
ULONG Index;
// Initialize the spinlock and listheads for the call performance data structure.
KeInitializeSpinLock(&CallData->SpinLock);
for (Index = 0; Index < CALL_HASH_TABLE_SIZE; Index += 1) {
InitializeListHead(&CallData->HashTable[Index]);
}
}
VOID ExRecordCallerInHashTable (IN PCALL_PERFORMANCE_DATA CallData, IN PVOID CallersAddress, IN PVOID CallersCaller)
/*++
Routine Description:
This function records call data in the specified call performance data structure.
Arguments:
CallData - Supplies a pointer to the call performance data structure in which the call data is recorded.
CallersAddress - Supplies the address of the caller of a fucntion.
CallersCaller - Supplies the address of the caller of a caller of a function.
--*/
{
PCALL_HASH_ENTRY HashEntry;
ULONG Hash;
PCALL_HASH_ENTRY MatchEntry;
PLIST_ENTRY NextEntry;
KIRQL OldIrql;
// If the initialization phase is not zero, then collect call performance data.
if (InitializationPhase != 0) {
// Acquire the call performance data structure spinlock.
ExAcquireSpinLock(&CallData->SpinLock, &OldIrql);
// Lookup the callers address in call performance data hash table.
// If the address does not exist in the table, then create a new entry.
Hash = (ULONG)((ULONG_PTR)CallersAddress ^ (ULONG_PTR)CallersCaller);
Hash = ((Hash > 24) ^ (Hash > 16) ^ (Hash > 8) ^ (Hash)) & (CALL_HASH_TABLE_SIZE - 1);
MatchEntry = NULL;
NextEntry = CallData->HashTable[Hash].Flink;
while (NextEntry != &CallData->HashTable[Hash]) {
HashEntry = CONTAINING_RECORD(NextEntry, CALL_HASH_ENTRY, ListEntry);
if ((HashEntry->CallersAddress == CallersAddress) && (HashEntry->CallersCaller == CallersCaller)) {
MatchEntry = HashEntry;
break;
}
NextEntry = NextEntry->Flink;
}
// If a matching caller address was found, then update the call site statistics.
// Otherwise, allocate a new hash entry and initialize call site statistics.
if (MatchEntry != NULL) {
MatchEntry->CallCount += 1;
} else {
MatchEntry = ExAllocatePoolWithTag(NonPagedPool, sizeof(CALL_HASH_ENTRY), 'CdHe');
if (MatchEntry != NULL) {
MatchEntry->CallersAddress = CallersAddress;
MatchEntry->CallersCaller = CallersCaller;
MatchEntry->CallCount = 1;
InsertTailList(&CallData->HashTable[Hash], &MatchEntry->ListEntry);
}
}
ExReleaseSpinLock(&CallData->SpinLock, OldIrql);// Release the call performance data structure spinlock.
}
}