91 lines
3.2 KiB
C
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.
|
|
}
|
|
} |