summaryrefslogtreecommitdiffstats
path: root/private/ntos/ex/callperf.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ex/callperf.c
downloadNT4.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.c169
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;
+}