diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ex/callperf.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to '')
-rw-r--r-- | private/ntos/ex/callperf.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/private/ntos/ex/callperf.c b/private/ntos/ex/callperf.c new file mode 100644 index 000000000..7caad7b31 --- /dev/null +++ b/private/ntos/ex/callperf.c @@ -0,0 +1,169 @@ +/*++ + +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. + +Revision History: + +--*/ + +#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. + +Return Value: + + None. + +--*/ + +{ + + 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. + +Return Value: + + None. + +--*/ + +{ + + 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)CallersAddress ^ (ULONG)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); + } + } + + // + // Release the call performance data structure spinlock. + // + + ExReleaseSpinLock(&CallData->SpinLock, OldIrql); + } + + return; +} |