diff --git a/reactos/ntoskrnl/Makefile b/reactos/ntoskrnl/Makefile index 18b781efbad..ac8c7987a52 100644 --- a/reactos/ntoskrnl/Makefile +++ b/reactos/ntoskrnl/Makefile @@ -33,7 +33,7 @@ else OBJECTS_KDBG := endif ifeq ($(DBG_OR_KDBG), 1) -OBJECTS_KDBG := $(OBJECTS_KDBG) dbg/kdb_symbols.o dbg/profile.o +OBJECTS_KDBG := $(OBJECTS_KDBG) dbg/kdb_symbols.o endif TARGET_ASFLAGS = -I./include @@ -233,14 +233,12 @@ OBJECTS_PS = \ # Executive Subsystem (Ex) OBJECTS_EX = \ - ex/btree.o \ ex/callback.o \ ex/error.o \ ex/event.o \ ex/evtpair.o \ ex/fmutex.o \ ex/handle.o \ - ex/hashtab.o \ ex/init.o \ ex/interlck.o \ ex/list.o \ @@ -250,7 +248,6 @@ OBJECTS_EX = \ ex/profile.o \ ex/resource.o \ ex/rundown.o \ - ex/stree.o \ ex/sem.o \ ex/synch.o \ ex/sysinfo.o \ diff --git a/reactos/ntoskrnl/dbg/kdb.h b/reactos/ntoskrnl/dbg/kdb.h index 0bbbfa2974f..c9b631d51a5 100644 --- a/reactos/ntoskrnl/dbg/kdb.h +++ b/reactos/ntoskrnl/dbg/kdb.h @@ -255,19 +255,6 @@ BOOLEAN KdbpAttachToProcess( PVOID ProcessId); -/* from profile.c */ - -VOID -KdbInitProfiling(); -VOID -KdbInitProfiling2(); -VOID -KdbDisableProfiling(); -VOID -KdbEnableProfiling(); -VOID -KdbProfileInterrupt(ULONG_PTR Eip); - /* other functions */ #define KdbpSafeReadMemory(dst, src, size) MmSafeCopyFromUser(dst, src, size) diff --git a/reactos/ntoskrnl/dbg/profile.c b/reactos/ntoskrnl/dbg/profile.c deleted file mode 100755 index 3b2350541b5..00000000000 --- a/reactos/ntoskrnl/dbg/profile.c +++ /dev/null @@ -1,478 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/dbg/profile.c - * PURPOSE: Kernel profiling - * - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - */ - -/* INCLUDES *****************************************************************/ - -#include -#include "kdb.h" - -#define NDEBUG -#include - -/* FUNCTIONS *****************************************************************/ - -#define PROFILE_SESSION_LENGTH 30 /* Session length in seconds */ - -typedef struct _PROFILE_DATABASE_ENTRY -{ - ULONG_PTR Address; -} PROFILE_DATABASE_ENTRY, *PPROFILE_DATABASE_ENTRY; - -#define PDE_BLOCK_ENTRIES ((PAGE_SIZE - (sizeof(LIST_ENTRY) + sizeof(ULONG))) / sizeof(PROFILE_DATABASE_ENTRY)) - -typedef struct _PROFILE_DATABASE_BLOCK -{ - LIST_ENTRY ListEntry; - ULONG UsedEntries; - PROFILE_DATABASE_ENTRY Entries[PDE_BLOCK_ENTRIES]; -} PROFILE_DATABASE_BLOCK, *PPROFILE_DATABASE_BLOCK; - -typedef struct _PROFILE_DATABASE -{ - LIST_ENTRY ListHead; -} PROFILE_DATABASE, *PPROFILE_DATABASE; - -typedef struct _SAMPLE_GROUP_INFO -{ - ULONG_PTR Address; - ULONG Count; - CHAR Description[128]; - LIST_ENTRY ListEntry; -} SAMPLE_GROUP_INFO, *PSAMPLE_GROUP_INFO; - -static volatile BOOLEAN KdbProfilingInitialized = FALSE; -static volatile BOOLEAN KdbProfilingEnabled = FALSE; -static volatile BOOLEAN KdbProfilingSuspended = FALSE; -static PPROFILE_DATABASE KdbProfileDatabase = NULL; -static KDPC KdbProfilerCollectorDpc; -static HANDLE KdbProfilerThreadHandle; -static CLIENT_ID KdbProfilerThreadCid; -static HANDLE KdbProfilerLogFile; -static KTIMER KdbProfilerTimer; -static KMUTEX KdbProfilerLock; -static BOOLEAN KdbEnableProfiler = FALSE; - -VOID -KdbDeleteProfileDatabase(PPROFILE_DATABASE ProfileDatabase) -{ - PLIST_ENTRY current = NULL; - - current = RemoveHeadList(&ProfileDatabase->ListHead); - while (current != &ProfileDatabase->ListHead) - { - PPROFILE_DATABASE_BLOCK block = CONTAINING_RECORD( - current, PROFILE_DATABASE_BLOCK, ListEntry); - ExFreePool(block); - current = RemoveHeadList(&ProfileDatabase->ListHead); - } -} - -VOID -KdbAddEntryToProfileDatabase(PPROFILE_DATABASE ProfileDatabase, ULONG_PTR Address) -{ - PPROFILE_DATABASE_BLOCK block; - - if (IsListEmpty(&ProfileDatabase->ListHead)) - { - block = ExAllocatePool(NonPagedPool, sizeof(PROFILE_DATABASE_BLOCK)); - ASSERT(block); - block->UsedEntries = 0; - InsertTailList(&ProfileDatabase->ListHead, &block->ListEntry); - block->Entries[block->UsedEntries++].Address = Address; - return; - } - - block = CONTAINING_RECORD(ProfileDatabase->ListHead.Blink, PROFILE_DATABASE_BLOCK, ListEntry); - if (block->UsedEntries >= PDE_BLOCK_ENTRIES) - { - block = ExAllocatePool(NonPagedPool, sizeof(PROFILE_DATABASE_BLOCK)); - ASSERT(block); - block->UsedEntries = 0; - InsertTailList(&ProfileDatabase->ListHead, &block->ListEntry); - } - block->Entries[block->UsedEntries++].Address = Address; -} - -VOID INIT_FUNCTION -KdbInitProfiling() -{ - KdbEnableProfiler = TRUE; -} - -VOID INIT_FUNCTION -KdbInitProfiling2() -{ - if (KdbEnableProfiler) - { - KdbEnableProfiling(); - KdbProfilingInitialized = TRUE; - } -} - -VOID -KdbSuspendProfiling() -{ - KdbProfilingSuspended = TRUE; -} - -VOID -KdbResumeProfiling() -{ - KdbProfilingSuspended = FALSE; -} - -BOOLEAN -KdbProfilerGetSymbolInfo(PVOID address, OUT PCH NameBuffer) -{ - PLIST_ENTRY current_entry; - MODULE_TEXT_SECTION* current; - extern LIST_ENTRY ModuleTextListHead; - ULONG_PTR RelativeAddress; - NTSTATUS Status; - CHAR FileName[256]; - CHAR FunctionName[256]; - - current_entry = ModuleTextListHead.Flink; - - while (current_entry != &ModuleTextListHead && - current_entry != NULL) - { - current = - CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry); - - if (address >= (PVOID)current->Base && - address < (PVOID)(current->Base + current->Length)) - { - RelativeAddress = (ULONG_PTR) address - current->Base; - Status = KdbSymGetAddressInformation(current->RosSymInfo, - RelativeAddress, - NULL, - FileName, - FunctionName); - if (NT_SUCCESS(Status)) - { - sprintf(NameBuffer, "%s (%s)", FunctionName, FileName); - return(TRUE); - } - return(TRUE); - } - current_entry = current_entry->Flink; - } - return(FALSE); -} - -PLIST_ENTRY -KdbProfilerLargestSampleGroup(PLIST_ENTRY SamplesListHead) -{ - PLIST_ENTRY current; - PLIST_ENTRY largest; - ULONG count; - - count = 0; - largest = SamplesListHead->Flink; - current = SamplesListHead->Flink; - while (current != SamplesListHead) - { - PSAMPLE_GROUP_INFO sgi = CONTAINING_RECORD( - current, SAMPLE_GROUP_INFO, ListEntry); - - if (sgi->Count > count) - { - largest = current; - count = sgi->Count; - } - - current = current->Flink; - } - if (count == 0) - { - return NULL; - } - return largest; -} - -VOID -KdbProfilerWriteString(PCH String) -{ - IO_STATUS_BLOCK Iosb; - NTSTATUS Status; - ULONG Length; - - Length = strlen(String); - Status = NtWriteFile(KdbProfilerLogFile, - NULL, - NULL, - NULL, - &Iosb, - String, - Length, - NULL, - NULL); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtWriteFile() failed with status 0x%.08x\n", Status); - } -} - -NTSTATUS -KdbProfilerWriteSampleGroups(PLIST_ENTRY SamplesListHead) -{ - CHAR Buffer[256]; - PLIST_ENTRY current = NULL; - PLIST_ENTRY Largest; - - KdbProfilerWriteString("\r\n\r\n"); - KdbProfilerWriteString("Count Symbol\r\n"); - KdbProfilerWriteString("--------------------------------------------------\r\n"); - - current = SamplesListHead->Flink; - while (current != SamplesListHead) - { - Largest = KdbProfilerLargestSampleGroup(SamplesListHead); - if (Largest != NULL) - { - PSAMPLE_GROUP_INFO sgi = CONTAINING_RECORD( - Largest, SAMPLE_GROUP_INFO, ListEntry); - - //DbgPrint("%.08lu %s\n", sgi->Count, sgi->Description); - - sprintf(Buffer, "%.08lu %s\r\n", sgi->Count, sgi->Description); - KdbProfilerWriteString(Buffer); - - RemoveEntryList(Largest); - ExFreePool(sgi); - } - else - { - break; - } - - current = SamplesListHead->Flink; - } - - return STATUS_SUCCESS; -} - -LONG STDCALL -KdbProfilerKeyCompare(IN PVOID Key1, - IN PVOID Key2) -{ - int value = strcmp(Key1, Key2); - - if (value == 0) - return 0; - - return (value < 0) ? -1 : 1; -} - - -NTSTATUS -KdbProfilerAnalyzeSamples() -{ - CHAR NameBuffer[512]; - ULONG KeyLength; - PLIST_ENTRY current = NULL; - HASH_TABLE Hashtable; - LIST_ENTRY SamplesListHead; - ULONG Index; - ULONG_PTR Address; - - if (!ExInitializeHashTable(&Hashtable, 12, KdbProfilerKeyCompare, TRUE)) - { - DPRINT1("ExInitializeHashTable() failed."); - KEBUGCHECK(0); - } - - InitializeListHead(&SamplesListHead); - - current = RemoveHeadList(&KdbProfileDatabase->ListHead); - while (current != &KdbProfileDatabase->ListHead) - { - PPROFILE_DATABASE_BLOCK block; - - block = CONTAINING_RECORD(current, PROFILE_DATABASE_BLOCK, ListEntry); - - for (Index = 0; Index < block->UsedEntries; Index++) - { - PSAMPLE_GROUP_INFO sgi; - Address = block->Entries[Index].Address; - if (KdbProfilerGetSymbolInfo((PVOID) Address, (PCH) &NameBuffer)) - { - } - else - { - sprintf(NameBuffer, "(0x%.08lx)", (ULONG) Address); - } - - KeyLength = strlen(NameBuffer); - if (!ExSearchHashTable(&Hashtable, (PVOID) NameBuffer, KeyLength, (PVOID *) &sgi)) - { - sgi = ExAllocatePool(NonPagedPool, sizeof(SAMPLE_GROUP_INFO)); - ASSERT(sgi); - sgi->Address = Address; - sgi->Count = 1; - strcpy(sgi->Description, NameBuffer); - InsertTailList(&SamplesListHead, &sgi->ListEntry); - ExInsertHashTable(&Hashtable, sgi->Description, KeyLength, (PVOID) sgi); - } - else - { - sgi->Count++; - } - } - - ExFreePool(block); - - current = RemoveHeadList(&KdbProfileDatabase->ListHead); - } - - KdbProfilerWriteSampleGroups(&SamplesListHead); - - ExDeleteHashTable(&Hashtable); - - KdbDeleteProfileDatabase(KdbProfileDatabase); - - return STATUS_SUCCESS; -} - -VOID STDCALL -KdbProfilerThreadMain(PVOID Context) -{ - for (;;) - { - KeWaitForSingleObject(&KdbProfilerTimer, Executive, KernelMode, TRUE, NULL); - - KeWaitForSingleObject(&KdbProfilerLock, Executive, KernelMode, FALSE, NULL); - - KdbSuspendProfiling(); - - KdbProfilerAnalyzeSamples(); - - KdbResumeProfiling(); - - KeReleaseMutex(&KdbProfilerLock, FALSE); - } -} - -VOID -KdbDisableProfiling() -{ - if (KdbProfilingEnabled == TRUE) - { - /* FIXME: Implement */ -#if 0 - KdbProfilingEnabled = FALSE; - /* Stop timer */ - /* Close file */ - if (KdbProfileDatabase != NULL) - { - KdbDeleteProfileDatabase(KdbProfileDatabase); - ExFreePool(KdbProfileDatabase); - KdbProfileDatabase = NULL; - } -#endif - } -} - -/* - * SystemArgument1 = EIP - */ -static VOID STDCALL -KdbProfilerCollectorDpcRoutine(PKDPC Dpc, PVOID DeferredContext, - PVOID SystemArgument1, PVOID SystemArgument2) -{ - ULONG_PTR address = (ULONG_PTR) SystemArgument1; - - KdbAddEntryToProfileDatabase(KdbProfileDatabase, address); -} - -VOID INIT_FUNCTION -KdbEnableProfiling() -{ - if (KdbProfilingEnabled == FALSE) - { - NTSTATUS Status; - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING FileName; - IO_STATUS_BLOCK Iosb; - LARGE_INTEGER DueTime; - - RtlInitUnicodeString(&FileName, L"\\SystemRoot\\profiler.log"); - InitializeObjectAttributes(&ObjectAttributes, - &FileName, - 0, - NULL, - NULL); - - Status = NtCreateFile(&KdbProfilerLogFile, - FILE_ALL_ACCESS, - &ObjectAttributes, - &Iosb, - NULL, - FILE_ATTRIBUTE_NORMAL, - 0, - FILE_SUPERSEDE, - FILE_WRITE_THROUGH | FILE_SYNCHRONOUS_IO_NONALERT, - NULL, - 0); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to create profiler log file\n"); - return; - } - KeInitializeMutex(&KdbProfilerLock, 0); - - KdbProfileDatabase = ExAllocatePool(NonPagedPool, sizeof(PROFILE_DATABASE)); - ASSERT(KdbProfileDatabase); - InitializeListHead(&KdbProfileDatabase->ListHead); - KeInitializeDpc(&KdbProfilerCollectorDpc, KdbProfilerCollectorDpcRoutine, NULL); - - /* Initialize our periodic timer and its associated DPC object. When the timer - expires, the KdbProfilerSessionEndDpc deferred procedure call (DPC) is queued */ - KeInitializeTimerEx(&KdbProfilerTimer, SynchronizationTimer); - - Status = PsCreateSystemThread(&KdbProfilerThreadHandle, - THREAD_ALL_ACCESS, - NULL, - NULL, - &KdbProfilerThreadCid, - KdbProfilerThreadMain, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to create profiler thread\n"); - return; - } - - /* Start the periodic timer with an initial and periodic - relative expiration time of PROFILE_SESSION_LENGTH seconds */ - DueTime.QuadPart = -(LONGLONG) PROFILE_SESSION_LENGTH * 1000 * 10000; - KeSetTimerEx(&KdbProfilerTimer, DueTime, PROFILE_SESSION_LENGTH * 1000, NULL); - - KdbProfilingEnabled = TRUE; - } -} - -VOID -KdbProfileInterrupt(ULONG_PTR Address) -{ - ASSERT(KeGetCurrentIrql() == PROFILE_LEVEL); - - if (KdbProfilingInitialized != TRUE) - { - return; - } - - if ((KdbProfilingEnabled) && (!KdbProfilingSuspended)) - { - (BOOLEAN) KeInsertQueueDpc(&KdbProfilerCollectorDpc, (PVOID) Address, NULL); - } -} diff --git a/reactos/ntoskrnl/ex/btree.c b/reactos/ntoskrnl/ex/btree.c deleted file mode 100644 index 6ced8855417..00000000000 --- a/reactos/ntoskrnl/ex/btree.c +++ /dev/null @@ -1,644 +0,0 @@ -/* $Id:$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ex/btree.c - * PURPOSE: Binary tree support - * - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - */ - -#include -#define NDEBUG -#include - -/* DATA **********************************************************************/ - -typedef struct _BINARY_TREE_NODE -{ - struct _BINARY_TREE_NODE * Parent; - struct _BINARY_TREE_NODE * LeftChild; - struct _BINARY_TREE_NODE * RightChild; - PVOID Key; - PVOID Value; -} BINARY_TREE_NODE, *PBINARY_TREE_NODE; - -typedef struct _TRAVERSE_CONTEXT { - PTRAVERSE_ROUTINE Routine; - PVOID Context; -} TRAVERSE_CONTEXT, *PTRAVERSE_CONTEXT; - -/* FUNCTIONS ****************************************************************/ - -#define ExpBinaryTreeRootNode(Tree)(((PBINARY_TREE) (Tree))->RootNode) -#define ExpBinaryTreeIsExternalNode(Node)(((Node)->LeftChild == NULL) && ((Node)->RightChild == NULL)) -#define ExpBinaryTreeIsInternalNode(Node)(!ExpBinaryTreeIsExternalNode(Node)) -#define ExpBinaryTreeNodeKey(Node)((Node)->Key) -#define ExpBinaryTreeNodeValue(Node)((Node)->Value) -#define ExpBinaryTreeParentNode(Node)((Node)->Parent) -#define ExpBinaryTreeLeftChildNode(Node)((Node)->LeftChild) -#define ExpBinaryTreeRightChildNode(Node)((Node)->RightChild) -#define ExpBinaryTreeNodeEqual(Equality)((Equality) == 0) -#define ExpBinaryTreeNodeLess(Equality)((Equality) < 0) -#define ExpBinaryTreeNodeMore(Equality)((Equality) > 0) - - -/* - * Lock the binary tree - */ -inline VOID -ExpLockBinaryTree(PBINARY_TREE Tree, - PKIRQL OldIrql) -{ - if (Tree->UseNonPagedPool) - { - KeAcquireSpinLock(&Tree->Lock.NonPaged, OldIrql); - } - else - { - ExAcquireFastMutex(&Tree->Lock.Paged); - } -} - - -/* - * Unlock the binary tree - */ -inline VOID -ExpUnlockBinaryTree(PBINARY_TREE Tree, - PKIRQL OldIrql) -{ - if (Tree->UseNonPagedPool) - { - KeReleaseSpinLock(&Tree->Lock.NonPaged, *OldIrql); - } - else - { - ExReleaseFastMutex(&Tree->Lock.Paged); - } -} - - -/* - * Allocate resources for a new node and initialize it. - */ -inline PBINARY_TREE_NODE -ExpCreateBinaryTreeNode(PBINARY_TREE Tree, - PBINARY_TREE_NODE Parent, - PVOID Value) -{ - PBINARY_TREE_NODE Node; - - if (Tree->UseNonPagedPool) - { - Node = (PBINARY_TREE_NODE) ExAllocateFromNPagedLookasideList(&Tree->List.NonPaged); - } - else - { - Node = (PBINARY_TREE_NODE) ExAllocateFromPagedLookasideList(&Tree->List.Paged); - } - - if (Node) - { - ExpBinaryTreeParentNode(Node) = Parent; - ExpBinaryTreeLeftChildNode(Node) = NULL; - ExpBinaryTreeRightChildNode(Node) = NULL; - ExpBinaryTreeNodeValue(Node) = Value; - } - - return Node; -} - - -/* - * Release resources for the node. - */ -inline VOID -ExpDestroyBinaryTreeNode(PBINARY_TREE Tree, - PBINARY_TREE_NODE Node) -{ - if (Tree->UseNonPagedPool) - { - ExFreeToNPagedLookasideList(&Tree->List.NonPaged, Node); - } - else - { - ExFreeToPagedLookasideList(&Tree->List.Paged, Node); - } -} - - -/* - * Replaces a child node of a node with a new node. - * The lock for the tree must be acquired when this routine is called. - */ -inline VOID -ExpBinaryTreeReplaceChildNode(PBINARY_TREE_NODE Child, - PBINARY_TREE_NODE NewChild) -{ - if (ExpBinaryTreeLeftChildNode(ExpBinaryTreeParentNode(Child)) == Child) - { - ExpBinaryTreeLeftChildNode(ExpBinaryTreeParentNode(Child)) = NewChild; - } - else - { - ExpBinaryTreeRightChildNode(ExpBinaryTreeParentNode(Child)) = NewChild; - } -} - - -/* - * Returns the sibling node of a node. - * The lock for the tree must be acquired when this routine is called. - */ -inline PBINARY_TREE_NODE -ExpSiblingBinaryTreeNode(PBINARY_TREE Tree, - PBINARY_TREE_NODE Node) -{ - if (Node == ExpBinaryTreeRootNode(Tree)) - { - return NULL; - } - else - { - if (ExpBinaryTreeLeftChildNode(ExpBinaryTreeParentNode(Node)) == Node) - { - return ExpBinaryTreeRightChildNode(ExpBinaryTreeParentNode(Node)); - } - else - { - return ExpBinaryTreeLeftChildNode(ExpBinaryTreeParentNode(Node)); - } - } -} - - -/* - * Expands an external node to an internal node. - * The lock for the tree must be acquired when this routine is called. - */ -VOID -ExpExpandExternalBinaryTreeNode(PBINARY_TREE Tree, - PBINARY_TREE_NODE Node) -{ - ExpBinaryTreeLeftChildNode(Node) = ExpCreateBinaryTreeNode(Tree, Node, NULL); - - if (!ExpBinaryTreeLeftChildNode(Node)) - { - /* FIXME: Throw exception */ - DbgPrint("ExpCreateBinaryTreeNode() failed\n"); - } - - ExpBinaryTreeRightChildNode(Node) = ExpCreateBinaryTreeNode(Tree, Node, NULL); - - if (!ExpBinaryTreeRightChildNode(Node)) - { - ExpDestroyBinaryTreeNode(Tree, ExpBinaryTreeLeftChildNode(Node)); - /* FIXME: Throw exception */ - DbgPrint("ExpCreateBinaryTreeNode() failed\n"); - } -} - - -/* - * Searches a tree for a node with the specified key. If a node with the - * specified key is not found, the external node where it should be is - * returned. - * The lock for the tree must be acquired when this routine is called. - */ -inline PBINARY_TREE_NODE -ExpSearchBinaryTree(PBINARY_TREE Tree, - PVOID Key, - PBINARY_TREE_NODE Node) -{ - LONG Equality; - - /* FIXME: Possibly do this iteratively due to the small kernel-mode stack */ - - if (ExpBinaryTreeIsExternalNode(Node)) - { - return Node; - } - - Equality = (*Tree->Compare)(Key, ExpBinaryTreeNodeKey(Node)); - - if (ExpBinaryTreeNodeEqual(Equality)) - { - return Node; - } - - if (ExpBinaryTreeNodeLess(Equality)) - { - return ExpSearchBinaryTree(Tree, Key, ExpBinaryTreeLeftChildNode(Node)); - } - -/* if (ExpBinaryTreeNodeMore(Equality)) */ - { - return ExpSearchBinaryTree(Tree, Key, ExpBinaryTreeRightChildNode(Node)); - } -} - - -/* - * Removes an external node and it's parent node from the tree. - * The lock for the tree must be acquired when this routine is called. - */ -VOID -ExpRemoveAboveExternalBinaryTreeNode(PBINARY_TREE Tree, - PBINARY_TREE_NODE Node) -{ - ASSERTMSG(ExpBinaryTreeIsExternalNode(Node), ("Node is not external")); - - if (Node == ExpBinaryTreeRootNode(Tree)) - { - return; - } - else - { - PBINARY_TREE_NODE GrandParent; - PBINARY_TREE_NODE NewChild; - - GrandParent = ExpBinaryTreeParentNode(ExpBinaryTreeParentNode(Node)); - NewChild = ExpSiblingBinaryTreeNode(Tree, Node); - - if (GrandParent != NULL) - { - ExpBinaryTreeReplaceChildNode(ExpBinaryTreeParentNode(Node), NewChild); - } - - ExpDestroyBinaryTreeNode(Tree, ExpBinaryTreeParentNode(Node)); - ExpDestroyBinaryTreeNode(Tree, Node); - } -} - - -/* - * Release resources used by nodes of a binary (sub)tree. - */ -VOID -ExpDeleteBinaryTree(PBINARY_TREE Tree, - PBINARY_TREE_NODE Node) -{ - /* FIXME: Possibly do this iteratively due to the small kernel-mode stack */ - - if (ExpBinaryTreeIsInternalNode(Node)) - { - ExpDeleteBinaryTree(Tree, ExpBinaryTreeLeftChildNode(Node)); - ExpDeleteBinaryTree(Tree, ExpBinaryTreeRightChildNode(Node)); - } - - ExpDestroyBinaryTreeNode(Tree, Node); -} - - -/* - * Traverse a binary tree using preorder traversal method. - * Returns FALSE, if the traversal was terminated prematurely or - * TRUE if the callback routine did not request that the traversal - * be terminated prematurely. - * The lock for the tree must be acquired when this routine is called. - */ -BOOLEAN -ExpTraverseBinaryTreePreorder(PTRAVERSE_CONTEXT Context, - PBINARY_TREE_NODE Node) -{ - if (ExpBinaryTreeIsInternalNode(Node)) - { - /* Call the traversal routine */ - if (!(*Context->Routine)(Context->Context, - ExpBinaryTreeNodeKey(Node), - ExpBinaryTreeNodeValue(Node))) - { - return FALSE; - } - - /* Traverse left subtree */ - ExpTraverseBinaryTreePreorder(Context, ExpBinaryTreeLeftChildNode(Node)); - - /* Traverse right subtree */ - ExpTraverseBinaryTreePreorder(Context, ExpBinaryTreeRightChildNode(Node)); - } - - return TRUE; -} - - -/* - * Traverse a binary tree using inorder traversal method. - * Returns FALSE, if the traversal was terminated prematurely or - * TRUE if the callback routine did not request that the traversal - * be terminated prematurely. - * The lock for the tree must be acquired when this routine is called. - */ -BOOLEAN -ExpTraverseBinaryTreeInorder(PTRAVERSE_CONTEXT Context, - PBINARY_TREE_NODE Node) -{ - if (ExpBinaryTreeIsInternalNode(Node)) - { - /* Traverse left subtree */ - ExpTraverseBinaryTreeInorder(Context, ExpBinaryTreeLeftChildNode(Node)); - - /* Call the traversal routine */ - if (!(*Context->Routine)(Context->Context, - ExpBinaryTreeNodeKey(Node), - ExpBinaryTreeNodeValue(Node))) - { - return FALSE; - } - - /* Traverse right subtree */ - ExpTraverseBinaryTreeInorder(Context, ExpBinaryTreeRightChildNode(Node)); - } - - return TRUE; -} - - -/* - * Traverse a binary tree using postorder traversal method. - * Returns FALSE, if the traversal was terminated prematurely or - * TRUE if the callback routine did not request that the traversal - * be terminated prematurely. - * The lock for the tree must be acquired when this routine is called. - */ -BOOLEAN -ExpTraverseBinaryTreePostorder(PTRAVERSE_CONTEXT Context, - PBINARY_TREE_NODE Node) -{ - if (ExpBinaryTreeIsInternalNode(Node)) - { - /* Traverse left subtree */ - ExpTraverseBinaryTreePostorder(Context, ExpBinaryTreeLeftChildNode(Node)); - - /* Traverse right subtree */ - ExpTraverseBinaryTreePostorder(Context, ExpBinaryTreeRightChildNode(Node)); - - /* Call the traversal routine */ - return (*Context->Routine)(Context->Context, - ExpBinaryTreeNodeKey(Node), - ExpBinaryTreeNodeValue(Node)); - } - - return TRUE; -} - - -/* - * Default key compare function. Compares the integer values of the two keys. - */ -LONG STDCALL -ExpBinaryTreeDefaultCompare(PVOID Key1, - PVOID Key2) -{ - if (Key1 == Key2) - return 0; - - return (((LONG_PTR) Key1 < (LONG_PTR) Key2) ? -1 : 1); -} - - -/* - * Initializes a binary tree. - */ -BOOLEAN STDCALL -ExInitializeBinaryTree(IN PBINARY_TREE Tree, - IN PKEY_COMPARATOR Compare, - IN BOOLEAN UseNonPagedPool) -{ - RtlZeroMemory(Tree, sizeof(BINARY_TREE)); - - Tree->Compare = (Compare == NULL) - ? ExpBinaryTreeDefaultCompare : Compare; - - Tree->UseNonPagedPool = UseNonPagedPool; - - if (UseNonPagedPool) - { - ExInitializeNPagedLookasideList( - &Tree->List.NonPaged, /* Lookaside list */ - NULL, /* Allocate routine */ - NULL, /* Free routine */ - 0, /* Flags */ - sizeof(BINARY_TREE_NODE), /* Size of each entry */ - TAG('E','X','B','T'), /* Tag */ - 0); /* Depth */ - - KeInitializeSpinLock(&Tree->Lock.NonPaged); - } - else - { - ExInitializePagedLookasideList( - &Tree->List.Paged, /* Lookaside list */ - NULL, /* Allocate routine */ - NULL, /* Free routine */ - 0, /* Flags */ - sizeof(BINARY_TREE_NODE), /* Size of each entry */ - TAG('E','X','B','T'), /* Tag */ - 0); /* Depth */ - - ExInitializeFastMutex(&Tree->Lock.Paged); - } - - ExpBinaryTreeRootNode(Tree) = ExpCreateBinaryTreeNode(Tree, NULL, NULL); - - if (ExpBinaryTreeRootNode(Tree) == NULL) - { - if (UseNonPagedPool) - { - ExDeleteNPagedLookasideList(&Tree->List.NonPaged); - } - else - { - ExDeletePagedLookasideList(&Tree->List.Paged); - } - return FALSE; - } - else - { - return TRUE; - } -} - - -/* - * Release resources used by a binary tree. - */ -VOID STDCALL -ExDeleteBinaryTree(IN PBINARY_TREE Tree) -{ - /* Remove all nodes */ - ExpDeleteBinaryTree(Tree, ExpBinaryTreeRootNode(Tree)); - - if (Tree->UseNonPagedPool) - { - ExDeleteNPagedLookasideList(&Tree->List.NonPaged); - } - else - { - ExDeletePagedLookasideList(&Tree->List.Paged); - } -} - - -/* - * Insert a value in a binary tree. - */ -VOID STDCALL -ExInsertBinaryTree(IN PBINARY_TREE Tree, - IN PVOID Key, - IN PVOID Value) -{ - PBINARY_TREE_NODE Node; - KIRQL OldIrql; - - /* FIXME: Use SEH for error reporting */ - - ExpLockBinaryTree(Tree, &OldIrql); - Node = ExpBinaryTreeRootNode(Tree); - do - { - Node = ExpSearchBinaryTree(Tree, Key, Node); - - if (ExpBinaryTreeIsExternalNode(Node)) - { - break; - } - else - { - Node = ExpBinaryTreeRightChildNode(Node); - } - } while (TRUE); - ExpExpandExternalBinaryTreeNode(Tree, Node); - ExpBinaryTreeNodeKey(Node) = Key; - ExpBinaryTreeNodeValue(Node) = Value; - ExpUnlockBinaryTree(Tree, &OldIrql); -} - - -/* - * Search for a value associated with a given key in a binary tree. - */ -BOOLEAN STDCALL -ExSearchBinaryTree(IN PBINARY_TREE Tree, - IN PVOID Key, - OUT PVOID * Value) -{ - PBINARY_TREE_NODE Node; - KIRQL OldIrql; - - ExpLockBinaryTree(Tree, &OldIrql); - Node = ExpSearchBinaryTree(Tree, Key, ExpBinaryTreeRootNode(Tree)); - - if (ExpBinaryTreeIsInternalNode(Node)) - { - *Value = ExpBinaryTreeNodeValue(Node); - ExpUnlockBinaryTree(Tree, &OldIrql); - return TRUE; - } - else - { - ExpUnlockBinaryTree(Tree, &OldIrql); - return FALSE; - } -} - - -/* - * Remove a value associated with a given key from a binary tree. - */ -BOOLEAN STDCALL -ExRemoveBinaryTree(IN PBINARY_TREE Tree, - IN PVOID Key, - IN PVOID * Value) -{ - PBINARY_TREE_NODE Node; - KIRQL OldIrql; - - ExpLockBinaryTree(Tree, &OldIrql); - - Node = ExpSearchBinaryTree(Tree, Key, ExpBinaryTreeRootNode(Tree)); - - if (ExpBinaryTreeIsExternalNode(Node)) - { - ExpUnlockBinaryTree(Tree, &OldIrql); - return FALSE; - } - else - { - *Value = ExpBinaryTreeNodeValue(Node); - if (ExpBinaryTreeIsExternalNode(ExpBinaryTreeLeftChildNode(Node))) - { - Node = ExpBinaryTreeLeftChildNode(Node); - } - else if (ExpBinaryTreeIsExternalNode(ExpBinaryTreeRightChildNode(Node))) - { - Node = ExpBinaryTreeRightChildNode(Node); - } - else - { - // Node has internal children - PBINARY_TREE_NODE SwapNode; - - SwapNode = Node; - Node = ExpBinaryTreeRightChildNode(SwapNode); - do - { - Node = ExpBinaryTreeLeftChildNode(Node); - } while (ExpBinaryTreeIsInternalNode(Node)); - } - - ExpRemoveAboveExternalBinaryTreeNode(Tree, Node); - ExpUnlockBinaryTree(Tree, &OldIrql); - return TRUE; - } -} - - -/* - * Traverse a binary tree using either preorder, inorder or postorder - * traversal method. - * Returns FALSE, if the traversal was terminated prematurely or - * TRUE if the callback routine did not request that the traversal - * be terminated prematurely. - */ -BOOLEAN STDCALL -ExTraverseBinaryTree(IN PBINARY_TREE Tree, - IN TRAVERSE_METHOD Method, - IN PTRAVERSE_ROUTINE Routine, - IN PVOID Context) -{ - TRAVERSE_CONTEXT tc; - BOOLEAN Status; - KIRQL OldIrql; - - tc.Routine = Routine; - tc.Context = Context; - - ExpLockBinaryTree(Tree, &OldIrql); - - switch (Method) - { - case TraverseMethodPreorder: - Status = ExpTraverseBinaryTreePreorder(&tc, ExpBinaryTreeRootNode(Tree)); - break; - - case TraverseMethodInorder: - Status = ExpTraverseBinaryTreeInorder(&tc, ExpBinaryTreeRootNode(Tree)); - break; - - case TraverseMethodPostorder: - Status = ExpTraverseBinaryTreePostorder(&tc, ExpBinaryTreeRootNode(Tree)); - break; - - default: - Status = FALSE; - break; - } - - ExpUnlockBinaryTree(Tree, &OldIrql); - - return Status; -} - -/* EOF */ diff --git a/reactos/ntoskrnl/ex/hashtab.c b/reactos/ntoskrnl/ex/hashtab.c deleted file mode 100644 index 011aec6eb02..00000000000 --- a/reactos/ntoskrnl/ex/hashtab.c +++ /dev/null @@ -1,306 +0,0 @@ -/* $Id:$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ex/hashtab.c - * PURPOSE: Hash table support - * - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - */ - -/* - * NOTES: The hash function is from: - * Bob Jenkins - * http://burtleburtle.net/bob/hash/doobs.html - */ - -#include - -#define NDEBUG -#include - -/* FUNCTIONS ****************************************************************/ - -#define ExpHashTableSize(n) ((ULONG)1 << (n)) -#define ExpHashTableMask(n) (ExpHashTableSize(n) - 1) - -#define ExpHashMix(a, b, c) \ -{ \ - a -= b; a -= c; a ^= (c >> 13); \ - b -= c; b -= a; b ^= (a << 8); \ - c -= a; c -= b; c ^= (b >> 13); \ - a -= b; a -= c; a ^= (c >> 12); \ - b -= c; b -= a; b ^= (a << 16); \ - c -= a; c -= b; c ^= (b >> 5); \ - a -= b; a -= c; a ^= (c >> 3); \ - b -= c; b -= a; b ^= (a << 10); \ - c -= a; c -= b; c ^= (b >> 15); \ -} - - -ULONG -ExpHash(PUCHAR Key, - ULONG KeyLength) -{ - register ULONG a, b, c, len; - - /* Set up the internal state */ - len = KeyLength; - a = b = 0x9e3779b9; /* The golden ratio; an arbitrary value */ - c = 0; - - /* Handle most of the key */ - while (len >= 12) - { - a += (Key[0] + ((ULONG)Key[1]<<8) + ((ULONG)Key[2]<<16) + ((ULONG)Key[3]<<24)); - b += (Key[4] + ((ULONG)Key[5]<<8) + ((ULONG)Key[6]<<16) + ((ULONG)Key[7]<<24)); - c += (Key[8] + ((ULONG)Key[9]<<8) + ((ULONG)Key[10]<<16)+ ((ULONG)Key[11]<<24)); - ExpHashMix(a, b, c); - Key += 12; len -= 12; - } - - /* Handle the last 11 bytes */ - c += KeyLength; - switch(len) /* All the case statements fall through */ - { - case 11: c += ((ULONG)Key[10] << 24); - case 10: c += ((ULONG)Key[9] << 16); - case 9 : c += ((ULONG)Key[8] << 8); - /* The first byte of c is reserved for the length */ - case 8 : b += ((ULONG)Key[7] << 24); - case 7 : b += ((ULONG)Key[6] << 16); - case 6 : b += ((ULONG)Key[5] << 8); - case 5 : b += Key[4]; - case 4 : a += ((ULONG)Key[3] << 24); - case 3 : a += ((ULONG)Key[2] << 16); - case 2 : a += ((ULONG)Key[1] << 8); - case 1 : a += Key[0]; - /* case 0: nothing left to add */ - } - - ExpHashMix(a, b, c); - - return c; -} - - -/* - * Lock the hash table - */ -inline VOID -ExpLockHashTable(PHASH_TABLE HashTable, - PKIRQL OldIrql) -{ - if (HashTable->UseNonPagedPool) - { - KeAcquireSpinLock(&HashTable->Lock.NonPaged, OldIrql); - } - else - { - ExAcquireFastMutex(&HashTable->Lock.Paged); - } -} - - -/* - * Unlock the hash table - */ -inline VOID -ExpUnlockHashTable(PHASH_TABLE HashTable, - PKIRQL OldIrql) -{ - if (HashTable->UseNonPagedPool) - { - KeReleaseSpinLock(&HashTable->Lock.NonPaged, *OldIrql); - } - else - { - ExReleaseFastMutex(&HashTable->Lock.Paged); - } -} - - -/* - * Insert a value in a hash table. - */ -inline VOID STDCALL -ExpInsertHashTable(IN PHASH_TABLE HashTable, - IN PVOID Key, - IN ULONG KeyLength, - IN PVOID Value) -{ - ULONG Index; - - Index = (ExpHash(Key, KeyLength) & ExpHashTableMask(HashTable->HashTableSize)); - - ExInsertSplayTree(&HashTable->HashTrees[Index], Key, Value); -} - - -/* - * Search for a value associated with a given key in a hash table. - */ -inline BOOLEAN STDCALL -ExpSearchHashTable(IN PHASH_TABLE HashTable, - IN PVOID Key, - IN ULONG KeyLength, - OUT PVOID * Value) -{ - ULONG Index; - - Index = (ExpHash(Key, KeyLength) & ExpHashTableMask(HashTable->HashTableSize)); - - return ExSearchSplayTree(&HashTable->HashTrees[Index], Key, Value); -} - - -/* - * Remove a value associated with a given key from a hash table. - */ -BOOLEAN STDCALL -ExpRemoveHashTable(IN PHASH_TABLE HashTable, - IN PVOID Key, - IN ULONG KeyLength, - IN PVOID * Value) -{ - ULONG Index; - - Index = (ExpHash(Key, KeyLength) & ExpHashTableMask(HashTable->HashTableSize)); - - return ExRemoveSplayTree(&HashTable->HashTrees[Index], Key, Value); -} - - -/* - * Initializes a hash table. - */ -BOOLEAN STDCALL -ExInitializeHashTable(IN PHASH_TABLE HashTable, - IN ULONG HashTableSize, - IN PKEY_COMPARATOR Compare OPTIONAL, - IN BOOLEAN UseNonPagedPool) -{ - BOOLEAN Status; - ULONG Index; - - RtlZeroMemory(HashTable, sizeof(HASH_TABLE)); - - HashTable->HashTableSize = HashTableSize; - - HashTable->UseNonPagedPool = UseNonPagedPool; - - if (UseNonPagedPool) - { - KeInitializeSpinLock(&HashTable->Lock.NonPaged); - HashTable->HashTrees = ExAllocatePool(NonPagedPool, ExpHashTableSize(HashTableSize) * sizeof(SPLAY_TREE)); - } - else - { - ExInitializeFastMutex(&HashTable->Lock.Paged); - HashTable->HashTrees = ExAllocatePool(PagedPool, ExpHashTableSize(HashTableSize) * sizeof(SPLAY_TREE)); - } - - if (HashTable->HashTrees == NULL) - { - return FALSE; - } - - for (Index = 0; Index < ExpHashTableSize(HashTableSize); Index++) - { - Status = ExInitializeSplayTree(&HashTable->HashTrees[Index], Compare, FALSE, UseNonPagedPool); - - if (!Status) - { - LONG i; - - for (i = Index - 1; i >= 0; i--) - { - ExDeleteSplayTree(&HashTable->HashTrees[i]); - } - - ExFreePool(HashTable->HashTrees); - - return FALSE; - } - } - - return TRUE; -} - - -/* - * Release resources used by a hash table. - */ -VOID STDCALL -ExDeleteHashTable(IN PHASH_TABLE HashTable) -{ - ULONG Index; - - for (Index = 0; Index < ExpHashTableSize(HashTable->HashTableSize); Index++) - { - ExDeleteSplayTree(&HashTable->HashTrees[Index]); - } - - ExFreePool(HashTable->HashTrees); -} - - -/* - * Insert a value in a hash table. - */ -VOID STDCALL -ExInsertHashTable(IN PHASH_TABLE HashTable, - IN PVOID Key, - IN ULONG KeyLength, - IN PVOID Value) -{ - KIRQL OldIrql; - - /* FIXME: Use SEH for error reporting */ - - ExpLockHashTable(HashTable, &OldIrql); - ExpInsertHashTable(HashTable, Key, KeyLength, Value); - ExpUnlockHashTable(HashTable, &OldIrql); -} - - -/* - * Search for a value associated with a given key in a hash table. - */ -BOOLEAN STDCALL -ExSearchHashTable(IN PHASH_TABLE HashTable, - IN PVOID Key, - IN ULONG KeyLength, - OUT PVOID * Value) -{ - BOOLEAN Status; - KIRQL OldIrql; - - ExpLockHashTable(HashTable, &OldIrql); - Status = ExpSearchHashTable(HashTable, Key, KeyLength, Value); - ExpUnlockHashTable(HashTable, &OldIrql); - - return Status; -} - - -/* - * Remove a value associated with a given key from a hash table. - */ -BOOLEAN STDCALL -ExRemoveHashTable(IN PHASH_TABLE HashTable, - IN PVOID Key, - IN ULONG KeyLength, - IN PVOID * Value) -{ - BOOLEAN Status; - KIRQL OldIrql; - - ExpLockHashTable(HashTable, &OldIrql); - Status = ExpRemoveHashTable(HashTable, Key, KeyLength, Value); - ExpUnlockHashTable(HashTable, &OldIrql); - - return Status; -} - -/* EOF */ diff --git a/reactos/ntoskrnl/ex/profile.c b/reactos/ntoskrnl/ex/profile.c index 863add88d9e..cb9c86b532d 100644 --- a/reactos/ntoskrnl/ex/profile.c +++ b/reactos/ntoskrnl/ex/profile.c @@ -1,11 +1,10 @@ -/* $Id:$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * FILE: ntoskrnl/nt/profile.c - * PURPOSE: Support for profiling + * FILE: ntoskrnl/ex/profile.c + * PURPOSE: Support for Executive Profile Objects * - * PROGRAMMERS: No programmer listed. + * PROGRAMMERS: Alex Ionescu */ /* INCLUDES *****************************************************************/ @@ -13,369 +12,448 @@ #include #include -/* TYPES ********************************************************************/ +/* This structure is a *GUESS* -- Alex */ +typedef struct _EPROFILE { + PEPROCESS Process; + PVOID ImageBase; + ULONG ImageSize; + ULONG BucketSize; + PVOID Buffer; + ULONG BufferSize; + PKPROFILE KeProfile; + KPROFILE_SOURCE ProfileSource; + KAFFINITY Affinity; + PMDL Mdl; + PVOID LockedBuffer; +} EPROFILE, *PEPROFILE; /* GLOBALS *******************************************************************/ POBJECT_TYPE EXPORTED ExProfileObjectType = NULL; +static KMUTEX ExpProfileMutex; + +#define PROFILE_CONTROL 1 + static GENERIC_MAPPING ExpProfileMapping = { - STANDARD_RIGHTS_READ, - STANDARD_RIGHTS_WRITE, - STANDARD_RIGHTS_EXECUTE, - STANDARD_RIGHTS_ALL}; + STANDARD_RIGHTS_READ | PROFILE_CONTROL, + STANDARD_RIGHTS_WRITE | PROFILE_CONTROL, + STANDARD_RIGHTS_EXECUTE | PROFILE_CONTROL, + STANDARD_RIGHTS_ALL}; -/* - * Size of the profile hash table. - */ -#define PROFILE_HASH_TABLE_SIZE (32) +VOID +STDCALL +ExpDeleteProfile(PVOID ObjectBody) +{ + PEPROFILE Profile; -/* - * Table of lists of per-process profiling data structures hashed by PID. - */ -LIST_ENTRY ProcessProfileListHashTable[PROFILE_HASH_TABLE_SIZE]; + /* Typecast the Object */ + Profile = (PEPROFILE)ObjectBody; + + /* Check if there if the Profile was started */ + if (Profile->LockedBuffer) { + + /* Stop the Profile */ + KeStopProfile(Profile->KeProfile); + + /* Unmap the Locked Buffer */ + MmUnmapLockedPages(Profile->LockedBuffer, Profile->Mdl); + MmUnlockPages(Profile->Mdl); + ExFreePool(Profile->Mdl); + } + + /* Check if a Process is associated */ + if (Profile->Process != NULL) { + + /* Dereference it */ + ObDereferenceObject(Profile->Process); + Profile->Process = NULL; + } +} -/* - * Head of the list of profile data structures for the kernel. - */ -LIST_ENTRY SystemProfileList; - -/* - * Lock that protects the profiling data structures. - */ -KSPIN_LOCK ProfileListLock; - -/* - * Timer interrupts happen before we have initialized the profiling - * data structures so just ignore them before that. - */ -BOOLEAN ProfileInitDone = FALSE; - -VOID INIT_FUNCTION +VOID +INIT_FUNCTION ExpInitializeProfileImplementation(VOID) { - ULONG i; - - InitializeListHead(&SystemProfileList); - - for (i = 0; i < PROFILE_HASH_TABLE_SIZE; i++) - { - InitializeListHead(&ProcessProfileListHashTable[i]); - } - - KeInitializeSpinLock(&ProfileListLock); - ProfileInitDone = TRUE; - - ExProfileObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); - - RtlpCreateUnicodeString(&ExProfileObjectType->TypeName, L"Profile", NonPagedPool); - - ExProfileObjectType->Tag = TAG('P', 'R', 'O', 'F'); - ExProfileObjectType->PeakObjects = 0; - ExProfileObjectType->PeakHandles = 0; - ExProfileObjectType->TotalObjects = 0; - ExProfileObjectType->TotalHandles = 0; - ExProfileObjectType->PagedPoolCharge = 0; - ExProfileObjectType->NonpagedPoolCharge = sizeof(KPROFILE); - ExProfileObjectType->Mapping = &ExpProfileMapping; - ExProfileObjectType->Dump = NULL; - ExProfileObjectType->Open = NULL; - ExProfileObjectType->Close = NULL; - ExProfileObjectType->Delete = KiDeleteProfile; - ExProfileObjectType->Parse = NULL; - ExProfileObjectType->Security = NULL; - ExProfileObjectType->QueryName = NULL; - ExProfileObjectType->OkayToClose = NULL; - ExProfileObjectType->Create = NULL; - - ObpCreateTypeObject(ExProfileObjectType); + /* Initialize the Mutex to lock the States */ + KeInitializeMutex(&ExpProfileMutex, 0x40); + + /* Create the Object Type */ + ExProfileObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); + RtlInitUnicodeString(&ExProfileObjectType->TypeName, L"Profile"); + ExProfileObjectType->Tag = TAG('P', 'R', 'O', 'F'); + ExProfileObjectType->PeakObjects = 0; + ExProfileObjectType->PeakHandles = 0; + ExProfileObjectType->TotalObjects = 0; + ExProfileObjectType->TotalHandles = 0; + ExProfileObjectType->PagedPoolCharge = 0; + ExProfileObjectType->NonpagedPoolCharge = sizeof(EPROFILE); + ExProfileObjectType->Mapping = &ExpProfileMapping; + ExProfileObjectType->Dump = NULL; + ExProfileObjectType->Open = NULL; + ExProfileObjectType->Close = NULL; + ExProfileObjectType->Delete = ExpDeleteProfile; + ExProfileObjectType->Parse = NULL; + ExProfileObjectType->Security = NULL; + ExProfileObjectType->QueryName = NULL; + ExProfileObjectType->OkayToClose = NULL; + ExProfileObjectType->Create = NULL; + ObpCreateTypeObject(ExProfileObjectType); } -NTSTATUS STDCALL +NTSTATUS +STDCALL NtCreateProfile(OUT PHANDLE ProfileHandle, - IN HANDLE Process OPTIONAL, - IN PVOID ImageBase, - IN ULONG ImageSize, - IN ULONG BucketSize, - IN PVOID Buffer, - IN ULONG BufferSize, - IN KPROFILE_SOURCE ProfileSource, - IN KAFFINITY Affinity) + IN HANDLE Process OPTIONAL, + IN PVOID ImageBase, + IN ULONG ImageSize, + IN ULONG BucketSize, + IN PVOID Buffer, + IN ULONG BufferSize, + IN KPROFILE_SOURCE ProfileSource, + IN KAFFINITY Affinity) { - HANDLE hProfile; - PKPROFILE Profile; - PEPROCESS pProcess; - KPROCESSOR_MODE PreviousMode; - OBJECT_ATTRIBUTES ObjectAttributes; - NTSTATUS Status = STATUS_SUCCESS; + HANDLE hProfile; + PEPROFILE Profile; + PEPROCESS pProcess; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status = STATUS_SUCCESS; - PAGED_CODE(); - - PreviousMode = ExGetPreviousMode(); - - if(BufferSize == 0) - { - return STATUS_INVALID_PARAMETER_7; - } - - if(PreviousMode != KernelMode) - { - _SEH_TRY - { - ProbeForWrite(ProfileHandle, - sizeof(HANDLE), - sizeof(ULONG)); - ProbeForWrite(Buffer, - BufferSize, - sizeof(ULONG)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; + PAGED_CODE(); + + /* Easy way out */ + if(BufferSize == 0) return STATUS_INVALID_PARAMETER_7; + + /* Check the Parameters for validity */ + if(PreviousMode != KernelMode) { + + _SEH_TRY { + + ProbeForWrite(ProfileHandle, + sizeof(HANDLE), + sizeof(ULONG)); + + ProbeForWrite(Buffer, + BufferSize, + sizeof(ULONG)); + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + } _SEH_END; - if(!NT_SUCCESS(Status)) - { - return Status; - } - } - - /* - * Reference the associated process - */ - if (Process != NULL) - { - Status = ObReferenceObjectByHandle(Process, - PROCESS_QUERY_INFORMATION, - PsProcessType, - PreviousMode, - (PVOID*)&pProcess, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - } - else - { - pProcess = NULL; - if(!SeSinglePrivilegeCheck(SeSystemProfilePrivilege, - PreviousMode)) - { - DPRINT1("NtCreateProfile: Caller requires the SeSystemProfilePrivilege privilege!\n"); - return STATUS_PRIVILEGE_NOT_HELD; - } + if(!NT_SUCCESS(Status)) return Status; } - /* - * Check the parameters - */ - if ((pProcess == NULL && ImageBase < (PVOID)KERNEL_BASE) || - (pProcess != NULL && ImageBase >= (PVOID)KERNEL_BASE)) - { - return(STATUS_INVALID_PARAMETER_3); - } - if (((ImageSize >> BucketSize) * 4) >= BufferSize) - { - return(STATUS_BUFFER_TOO_SMALL); - } - if (ProfileSource != ProfileTime) - { - return(STATUS_INVALID_PARAMETER_9); - } - if (Affinity != 0) - { - return(STATUS_INVALID_PARAMETER_10); + /* Check if a process was specified */ + if (Process) { + + /* Reference it */ + Status = ObReferenceObjectByHandle(Process, + PROCESS_QUERY_INFORMATION, + PsProcessType, + PreviousMode, + (PVOID*)&pProcess, + NULL); + if (!NT_SUCCESS(Status)) return(Status); + + } else { + + /* No process was specified, which means a System-Wide Profile */ + pProcess = NULL; + + /* For this, we need to check the Privilege */ + if(!SeSinglePrivilegeCheck(SeSystemProfilePrivilege, PreviousMode)) { + + DPRINT1("NtCreateProfile: Caller requires the SeSystemProfilePrivilege privilege!\n"); + return STATUS_PRIVILEGE_NOT_HELD; + } } - /* - * Create the object - */ - InitializeObjectAttributes(&ObjectAttributes, + /* Create the object */ + InitializeObjectAttributes(&ObjectAttributes, + NULL, + 0, + NULL, + NULL); + Status = ObCreateObject(KernelMode, + ExProfileObjectType, + &ObjectAttributes, + PreviousMode, + NULL, + sizeof(EPROFILE), + 0, + 0, + (PVOID*)&Profile); + if (!NT_SUCCESS(Status)) return(Status); + + /* Initialize it */ + Profile->ImageBase = ImageBase; + Profile->ImageSize = ImageSize; + Profile->Buffer = Buffer; + Profile->BufferSize = BufferSize; + Profile->BucketSize = BucketSize; + Profile->LockedBuffer = NULL; + Profile->Affinity = Affinity; + Profile->Process = pProcess; + + /* Insert into the Object Tree */ + Status = ObInsertObject ((PVOID)Profile, NULL, + PROFILE_CONTROL, 0, NULL, - NULL); - - Status = ObCreateObject(KernelMode, - ExProfileObjectType, - &ObjectAttributes, - PreviousMode, - NULL, - sizeof(KPROFILE), - 0, - 0, - (PVOID*)&Profile); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - /* - * Initialize it - */ - Profile->Base = ImageBase; - Profile->Size = ImageSize; - Profile->BucketShift = BucketSize; - Profile->BufferMdl = MmCreateMdl(NULL, Buffer, BufferSize); - if(Profile->BufferMdl == NULL) { - DPRINT("MmCreateMdl: Out of memory!"); - ObDereferenceObject (Profile); - return(STATUS_NO_MEMORY); - } - MmProbeAndLockPages(Profile->BufferMdl, UserMode, IoWriteAccess); - Profile->Buffer = MmGetSystemAddressForMdl(Profile->BufferMdl); - Profile->BufferSize = BufferSize; - Profile->ProcessorMask = Affinity; - Profile->Started = FALSE; - Profile->Process = pProcess; - - /* - * Insert the profile into the profile list data structures - */ - KiInsertProfile(Profile); - - Status = ObInsertObject ((PVOID)Profile, - NULL, - STANDARD_RIGHTS_ALL, - 0, - NULL, - &hProfile); - if (!NT_SUCCESS(Status)) - { - ObDereferenceObject (Profile); - return Status; - } - - /* - * Copy the created handle back to the caller - */ - _SEH_TRY - { - *ProfileHandle = hProfile; - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - ObDereferenceObject(Profile); - - return Status; -} - -NTSTATUS STDCALL -NtQueryIntervalProfile(IN KPROFILE_SOURCE ProfileSource, - OUT PULONG Interval) -{ - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; - - PAGED_CODE(); - - PreviousMode = ExGetPreviousMode(); - - if(PreviousMode != KernelMode) - { - _SEH_TRY - { - ProbeForWrite(Interval, - sizeof(ULONG), - sizeof(ULONG)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; + &hProfile); + ObDereferenceObject(Profile); - if(!NT_SUCCESS(Status)) - { - return Status; + /* Check for Success */ + if (!NT_SUCCESS(Status)) { + + /* Dereference Process on failure */ + if (pProcess) ObDereferenceObject(pProcess); + return Status; } - } - - if (ProfileSource == ProfileTime) - { - ULONG ReturnInterval; - - /* FIXME: What units does this use, for now nanoseconds */ - ReturnInterval = 100; - - _SEH_TRY - { - *Interval = ReturnInterval; - } - _SEH_HANDLE - { + + /* Copy the created handle back to the caller*/ + _SEH_TRY { + + *ProfileHandle = hProfile; + + } _SEH_HANDLE { + Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - return Status; - } - return STATUS_INVALID_PARAMETER_2; + } _SEH_END; + + /* Return Status */ + return Status; } -NTSTATUS STDCALL -NtSetIntervalProfile(IN ULONG Interval, - IN KPROFILE_SOURCE Source) +NTSTATUS +STDCALL +NtQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceCounter, + OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL) { - return(STATUS_NOT_IMPLEMENTED); + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + LARGE_INTEGER PerfFrequency; + NTSTATUS Status = STATUS_SUCCESS; + + /* Check the Parameters for validity */ + if(PreviousMode != KernelMode) { + + _SEH_TRY { + + ProbeForWrite(PerformanceCounter, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + + ProbeForWrite(PerformanceFrequency, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + } _SEH_END; + + if(!NT_SUCCESS(Status)) return Status; + } + + _SEH_TRY { + + /* Query the Kernel */ + *PerformanceCounter = KeQueryPerformanceCounter(&PerfFrequency); + + /* Return Frequency if requested */ + if(PerformanceFrequency) { + + *PerformanceFrequency = PerfFrequency; + } + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + + } _SEH_END; + + return Status; } -NTSTATUS STDCALL +NTSTATUS +STDCALL NtStartProfile(IN HANDLE ProfileHandle) { - PKPROFILE Profile; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status; + PEPROFILE Profile; + PKPROFILE KeProfile; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + PVOID TempLockedBuffer; + NTSTATUS Status; - PAGED_CODE(); - - PreviousMode = ExGetPreviousMode(); + PAGED_CODE(); - Status = ObReferenceObjectByHandle(ProfileHandle, - STANDARD_RIGHTS_ALL, - ExProfileObjectType, - PreviousMode, - (PVOID*)&Profile, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); + /* Get the Object */ + Status = ObReferenceObjectByHandle(ProfileHandle, + PROFILE_CONTROL, + ExProfileObjectType, + PreviousMode, + (PVOID*)&Profile, + NULL); + if (!NT_SUCCESS(Status)) return(Status); + + /* To avoid a Race, wait on the Mutex */ + KeWaitForSingleObject(&ExpProfileMutex, + Executive, + KernelMode, + FALSE, + NULL); + + /* The Profile can still be enabled though, so handle that */ + if (Profile->LockedBuffer) { + + /* Release our lock, dereference and return */ + KeReleaseMutex(&ExpProfileMutex, FALSE); + ObDereferenceObject(Profile); + return STATUS_PROFILING_NOT_STOPPED; } - Profile->Started = TRUE; - ObDereferenceObject(Profile); - return(STATUS_SUCCESS); + + /* Allocate a Kernel Profile Object. */ + KeProfile = ExAllocatePoolWithTag(NonPagedPool, + sizeof(EPROFILE), + TAG('P', 'r', 'o', 'f')); + + /* Allocate the Mdl Structure */ + Profile->Mdl = MmCreateMdl(NULL, Profile->Buffer, Profile->BufferSize); + + /* Probe and Lock for Write Access */ + MmProbeAndLockPages(Profile->Mdl, PreviousMode, IoWriteAccess); + + /* Map the pages */ + TempLockedBuffer = MmMapLockedPages(Profile->Mdl, KernelMode); + + /* Initialize the Kernel Profile Object */ + Profile->KeProfile = KeProfile; + KeInitializeProfile(KeProfile, + (PKPROCESS)Profile->Process, + Profile->ImageBase, + Profile->ImageSize, + Profile->BucketSize, + Profile->ProfileSource, + Profile->Affinity); + + /* Start the Profiling */ + KeStartProfile(KeProfile, TempLockedBuffer); + + /* Now it's safe to save this */ + Profile->LockedBuffer = TempLockedBuffer; + + /* Release mutex, dereference and return */ + KeReleaseMutex(&ExpProfileMutex, FALSE); + ObDereferenceObject(Profile); + return STATUS_SUCCESS; } -NTSTATUS STDCALL +NTSTATUS +STDCALL NtStopProfile(IN HANDLE ProfileHandle) { - PKPROFILE Profile; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status; + PEPROFILE Profile; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status; - PAGED_CODE(); - - PreviousMode = ExGetPreviousMode(); + PAGED_CODE(); - Status = ObReferenceObjectByHandle(ProfileHandle, - STANDARD_RIGHTS_ALL, - ExProfileObjectType, - PreviousMode, - (PVOID*)&Profile, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); + /* Get the Object */ + Status = ObReferenceObjectByHandle(ProfileHandle, + PROFILE_CONTROL, + ExProfileObjectType, + PreviousMode, + (PVOID*)&Profile, + NULL); + if (!NT_SUCCESS(Status)) return(Status); + + /* Get the Mutex */ + KeWaitForSingleObject(&ExpProfileMutex, + Executive, + KernelMode, + FALSE, + NULL); + + /* Make sure the Profile Object is really Started */ + if (!Profile->LockedBuffer) { + + Status = STATUS_PROFILING_NOT_STARTED; + goto Exit; } - Profile->Started = FALSE; - ObDereferenceObject(Profile); - return(STATUS_SUCCESS); + + /* Stop the Profile */ + KeStopProfile(Profile->KeProfile); + + /* Unlock the Buffer */ + MmUnmapLockedPages(Profile->LockedBuffer, Profile->Mdl); + MmUnlockPages(Profile->Mdl); + ExFreePool(Profile->KeProfile); + + /* Clear the Locked Buffer pointer, meaning the Object is Stopped */ + Profile->LockedBuffer = NULL; + +Exit: + /* Release Mutex, Dereference and Return */ + KeReleaseMutex(&ExpProfileMutex, FALSE); + ObDereferenceObject(Profile); + return Status; } +NTSTATUS +STDCALL +NtQueryIntervalProfile(IN KPROFILE_SOURCE ProfileSource, + OUT PULONG Interval) +{ + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + ULONG ReturnInterval; + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); + + /* Check the Parameters for validity */ + if(PreviousMode != KernelMode) { + + _SEH_TRY { + + ProbeForWrite(Interval, + sizeof(ULONG), + sizeof(ULONG)); + + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + } _SEH_END; + + if(!NT_SUCCESS(Status)) return Status; + } + + /* Query the Interval */ + ReturnInterval = KeQueryIntervalProfile(ProfileSource); + /* Return the data */ + _SEH_TRY { + + *Interval = ReturnInterval; + + } _SEH_HANDLE { + + Status = _SEH_GetExceptionCode(); + + } _SEH_END; + + /* Return Success */ + return STATUS_SUCCESS; +} + +NTSTATUS +STDCALL +NtSetIntervalProfile(IN ULONG Interval, + IN KPROFILE_SOURCE Source) +{ + /* Let the Kernel do the job */ + KeSetIntervalProfile(Interval, Source); + + /* Nothing can go wrong */ + return STATUS_SUCCESS; +} diff --git a/reactos/ntoskrnl/ex/stree.c b/reactos/ntoskrnl/ex/stree.c deleted file mode 100644 index 14c740dfbcd..00000000000 --- a/reactos/ntoskrnl/ex/stree.c +++ /dev/null @@ -1,1339 +0,0 @@ -/* $Id:$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ex/stree.c - * PURPOSE: Splay tree support - * - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - * - * NOTES: Based on a splay tree implementation by - * Daniel Stenberg - * http://www.contactor.se/~dast/stuff/dsplay-1.2.tar.gz - */ - -#include -#define NDEBUG -#include - -/* DATA **********************************************************************/ - -#define WEIGHT 1 -#undef UNIQUE_KEYS - -typedef struct _SPLAY_TREE_NODE -{ - /* Children on this branch that has smaller keys than this node */ - struct _SPLAY_TREE_NODE * SmallerChild; - - /* Children on this branch that has larger keys than this node */ - struct _SPLAY_TREE_NODE * LargerChild; - - /* Points to a node with identical key */ - struct _SPLAY_TREE_NODE * Same; - - /* Key of this node */ - PVOID Key; - - /* Value of this node */ - PVOID Value; - - /* The number of nodes rooted here */ - LONG Weight; -} SPLAY_TREE_NODE, *PSPLAY_TREE_NODE; - -typedef struct _TRAVERSE_CONTEXT { - PTRAVERSE_ROUTINE Routine; - PVOID Context; -} TRAVERSE_CONTEXT, *PTRAVERSE_CONTEXT; - -#define SPLAY_INDEX 0 -#define SEARCH_INDEX 1 -#define INSERT_INDEX 2 -#define REMOVE_INDEX 3 - -typedef PSPLAY_TREE_NODE (*PSPLAY_TREE_SPLAY)(PSPLAY_TREE Tree, - PVOID Key, - PSPLAY_TREE_NODE Node); - -typedef BOOLEAN (*PSPLAY_TREE_SEARCH)(PSPLAY_TREE Tree, - PVOID Key, - PSPLAY_TREE_NODE Node, - PSPLAY_TREE_NODE * ReturnNode); - -typedef PSPLAY_TREE_NODE (*PSPLAY_TREE_INSERT)(PSPLAY_TREE Tree, - PVOID Key, - PSPLAY_TREE_NODE Node, - PSPLAY_TREE_NODE New); - -typedef PSPLAY_TREE_NODE (*PSPLAY_TREE_REMOVE)(PSPLAY_TREE Tree, - PVOID Key, - PSPLAY_TREE_NODE Node, - PSPLAY_TREE_NODE * RemovedNode); - -/* FUNCTIONS ****************************************************************/ - -#define ExpSplayTreeRootNode(Tree)(((PSPLAY_TREE) (Tree))->RootNode) -#define ExpSplayTreeNodeKey(Node)((Node)->Key) -#define ExpSplayTreeNodeValue(Node)((Node)->Value) -#define ExpSplayTreeSmallerChildNode(Node)((Node)->SmallerChild) -#define ExpSplayTreeLargerChildNode(Node)((Node)->LargerChild) -#define ExpSplayTreeNodeEqual(Equality)((Equality) == 0) -#define ExpSplayTreeNodeLess(Equality)((Equality) < 0) -#define ExpSplayTreeNodeMore(Equality)((Equality) > 0) -#define ExpSplayTreeNodeSame(Node)((Node)->Same) -#define ExpSplayTreeNodeWeight(Node)((Node)->Weight) -#define ExpSplayTreeNodeGetWeight(Node)(((Node) == NULL) ? 0 : ((Node)->Weight)) -#define ExpSplayTreeNodeSetWeight(Node, _Weight)((Node)->Weight = (_Weight)) - -#define KEY_NOTUSED (PVOID)-1 - - -/* - * Lock the splay tree - */ -inline VOID -ExpLockSplayTree(PSPLAY_TREE Tree, - PKIRQL OldIrql) -{ - if (Tree->UseNonPagedPool) - { - KeAcquireSpinLock(&Tree->Lock.NonPaged, OldIrql); - } - else - { - ExAcquireFastMutex(&Tree->Lock.Paged); - } -} - - -/* - * Unlock the splay tree - */ -inline VOID -ExpUnlockSplayTree(PSPLAY_TREE Tree, - PKIRQL OldIrql) -{ - if (Tree->UseNonPagedPool) - { - KeReleaseSpinLock(&Tree->Lock.NonPaged, *OldIrql); - } - else - { - ExReleaseFastMutex(&Tree->Lock.Paged); - } -} - - -/* - * Allocate resources for a new node and initialize it. - */ -inline PSPLAY_TREE_NODE -ExpCreateSplayTreeNode(PSPLAY_TREE Tree, - PVOID Value) -{ - PSPLAY_TREE_NODE Node; - - if (Tree->UseNonPagedPool) - { - Node = (PSPLAY_TREE_NODE) ExAllocateFromNPagedLookasideList(&Tree->List.NonPaged); - } - else - { - Node = (PSPLAY_TREE_NODE) ExAllocateFromPagedLookasideList(&Tree->List.Paged); - } - - if (Node) - { - ExpSplayTreeSmallerChildNode(Node) = NULL; - ExpSplayTreeLargerChildNode(Node) = NULL; - ExpSplayTreeNodeValue(Node) = Value; - } - - return Node; -} - -/* - * Release resources for the node. - */ -inline VOID -ExpDestroySplayTreeNode(PSPLAY_TREE Tree, - PSPLAY_TREE_NODE Node) -{ - if (Tree->UseNonPagedPool) - { - ExFreeToNPagedLookasideList(&Tree->List.NonPaged, Node); - } - else - { - ExFreeToPagedLookasideList(&Tree->List.Paged, Node); - } -} - - -/* - * Splay using the key 'Key' (which may or may not be in the tree). The starting - * root is Node. - * The lock for the tree must be acquired when this routine is called. - * This routine does not maintain weight information. - */ -PSPLAY_TREE_NODE -ExpSplayTreeNoWeight(PSPLAY_TREE Tree, - PVOID Key, - PSPLAY_TREE_NODE Node) -{ - PSPLAY_TREE_NODE l; - PSPLAY_TREE_NODE r; - PSPLAY_TREE_NODE y; - LONG ChildEquality; - SPLAY_TREE_NODE N; - LONG Equality; - - if (Node == NULL) - return Node; - - ExpSplayTreeSmallerChildNode(&N) = NULL; - ExpSplayTreeLargerChildNode(&N) = NULL; - l = &N; - r = &N; - - for (;;) - { - Equality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)); - - if (ExpSplayTreeNodeLess(Equality)) - { - if (ExpSplayTreeSmallerChildNode(Node) == NULL) - break; - - ChildEquality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(ExpSplayTreeSmallerChildNode(Node))); - if (ExpSplayTreeNodeLess(ChildEquality)) - { - y = ExpSplayTreeSmallerChildNode(Node); /* Rotate smaller */ - ExpSplayTreeSmallerChildNode(Node) = ExpSplayTreeLargerChildNode(y); - ExpSplayTreeLargerChildNode(y) = Node; - - Node = y; - if (ExpSplayTreeSmallerChildNode(Node) == NULL) - break; - } - - ExpSplayTreeSmallerChildNode(r) = Node; /* Link smaller */ - r = Node; - Node = ExpSplayTreeSmallerChildNode(Node); - } - else if (ExpSplayTreeNodeMore(Equality)) - { - if (ExpSplayTreeLargerChildNode(Node) == NULL) - break; - - ChildEquality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(ExpSplayTreeLargerChildNode(Node))); - if (ExpSplayTreeNodeMore(ChildEquality)) - { - y = ExpSplayTreeLargerChildNode(Node); /* Rotate larger */ - ExpSplayTreeLargerChildNode(Node) = ExpSplayTreeSmallerChildNode(y); - ExpSplayTreeSmallerChildNode(y) = Node; - - Node = y; - if (ExpSplayTreeLargerChildNode(Node) == NULL) - break; - } - - ExpSplayTreeLargerChildNode(l) = Node; /* Link larger */ - l = Node; - Node = ExpSplayTreeLargerChildNode(Node); - } - else - { - break; - } - } - - ExpSplayTreeLargerChildNode(l) = NULL; - ExpSplayTreeSmallerChildNode(r) = NULL; - - ExpSplayTreeLargerChildNode(l) = ExpSplayTreeSmallerChildNode(Node); /* Assemble */ - ExpSplayTreeSmallerChildNode(r) = ExpSplayTreeLargerChildNode(Node); - ExpSplayTreeSmallerChildNode(Node) = ExpSplayTreeLargerChildNode(&N); - ExpSplayTreeLargerChildNode(Node) = ExpSplayTreeSmallerChildNode(&N); - - return Node; -} - - -/* - * Splay using the key 'Key' (which may or may not be in the tree). The starting - * root is Node. - * The lock for the tree must be acquired when this routine is called. - * This routine maintains weight information. - */ -PSPLAY_TREE_NODE -ExpSplayTreeWeight(PSPLAY_TREE Tree, - PVOID Key, - PSPLAY_TREE_NODE Node) -{ - PSPLAY_TREE_NODE l; - PSPLAY_TREE_NODE r; - PSPLAY_TREE_NODE y; - LONG ChildEquality; - SPLAY_TREE_NODE N; - LONG Equality; -#ifdef WEIGHT - LONG RootWeight; - LONG Weight1; - LONG Weight2; -#endif - - if (Node == NULL) - return Node; - - ExpSplayTreeSmallerChildNode(&N) = NULL; - ExpSplayTreeLargerChildNode(&N) = NULL; - l = &N; - r = &N; - -#ifdef WEIGHT - RootWeight = ExpSplayTreeNodeGetWeight(Node); - Weight1 = 0; - Weight2 = 0; -#endif - - for (;;) - { - Equality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)); - - if (ExpSplayTreeNodeLess(Equality)) - { - if (ExpSplayTreeSmallerChildNode(Node) == NULL) - break; - - ChildEquality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(ExpSplayTreeSmallerChildNode(Node))); - if (ExpSplayTreeNodeLess(ChildEquality)) - { - y = ExpSplayTreeSmallerChildNode(Node); /* Rotate smaller */ - ExpSplayTreeSmallerChildNode(Node) = ExpSplayTreeLargerChildNode(y); - ExpSplayTreeLargerChildNode(y) = Node; - -#ifdef WEIGHT - ExpSplayTreeNodeSetWeight(Node, ExpSplayTreeNodeGetWeight(ExpSplayTreeSmallerChildNode(Node)) - + ExpSplayTreeNodeGetWeight(ExpSplayTreeLargerChildNode(Node)) + 1); -#endif - - Node = y; - if (ExpSplayTreeSmallerChildNode(Node) == NULL) - break; - } - - ExpSplayTreeSmallerChildNode(r) = Node; /* Link smaller */ - r = Node; - Node = ExpSplayTreeSmallerChildNode(Node); - -#ifdef WEIGHT - Weight2 += 1 + ExpSplayTreeNodeGetWeight(ExpSplayTreeLargerChildNode(r)); -#endif - } - else if (ExpSplayTreeNodeMore(Equality)) - { - if (ExpSplayTreeLargerChildNode(Node) == NULL) - break; - - ChildEquality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(ExpSplayTreeLargerChildNode(Node))); - if (ExpSplayTreeNodeMore(ChildEquality)) - { - y = ExpSplayTreeLargerChildNode(Node); /* Rotate larger */ - ExpSplayTreeLargerChildNode(Node) = ExpSplayTreeSmallerChildNode(y); - ExpSplayTreeSmallerChildNode(y) = Node; - -#ifdef WEIGHT - ExpSplayTreeNodeSetWeight(Node, ExpSplayTreeNodeGetWeight(ExpSplayTreeSmallerChildNode(Node)) - + ExpSplayTreeNodeGetWeight(ExpSplayTreeLargerChildNode(Node)) + 1); -#endif - - Node = y; - if (ExpSplayTreeLargerChildNode(Node) == NULL) - break; - } - - ExpSplayTreeLargerChildNode(l) = Node; /* Link larger */ - l = Node; - Node = ExpSplayTreeLargerChildNode(Node); - -#ifdef WEIGHT - Weight1 += 1 + ExpSplayTreeNodeGetWeight(ExpSplayTreeSmallerChildNode(l)); -#endif - - } - else - { - break; - } - } - -#ifdef WEIGHT - Weight1 += ExpSplayTreeNodeGetWeight(ExpSplayTreeSmallerChildNode(Node)); /* Now Weight1 and Weight2 are the weights of */ - Weight2 += ExpSplayTreeNodeGetWeight(ExpSplayTreeLargerChildNode(Node)); /* The 'smaller' and 'larger' trees we just built. */ - ExpSplayTreeNodeSetWeight(Node, Weight1 + Weight2 + 1); -#endif - - ExpSplayTreeLargerChildNode(l) = NULL; - ExpSplayTreeSmallerChildNode(r) = NULL; - -#ifdef WEIGHT - /* The following two loops correct the weight fields of the right path from - * the left child of the root and the right path from the left child of the - * root. - */ - for (y = ExpSplayTreeLargerChildNode(&N); y != NULL; y = ExpSplayTreeLargerChildNode(y)) { - ExpSplayTreeNodeSetWeight(y, Weight1); - Weight1 -= 1 + ExpSplayTreeNodeGetWeight(ExpSplayTreeSmallerChildNode(y)); - } - for (y = ExpSplayTreeSmallerChildNode(&N); y != NULL; y = ExpSplayTreeSmallerChildNode(y)) { - ExpSplayTreeNodeSetWeight(y, Weight2); - Weight2 -= 1 + ExpSplayTreeNodeGetWeight(ExpSplayTreeLargerChildNode(y)); - } -#endif - - ExpSplayTreeLargerChildNode(l) = ExpSplayTreeSmallerChildNode(Node); /* Assemble */ - ExpSplayTreeSmallerChildNode(r) = ExpSplayTreeLargerChildNode(Node); - ExpSplayTreeSmallerChildNode(Node) = ExpSplayTreeLargerChildNode(&N); - ExpSplayTreeLargerChildNode(Node) = ExpSplayTreeSmallerChildNode(&N); - - return Node; -} - - -inline PSPLAY_TREE_NODE -ExpSplayTree(PSPLAY_TREE Tree, - PVOID Key, - PSPLAY_TREE_NODE Node) -{ - return (*((PSPLAY_TREE_SPLAY)Tree->Reserved[SPLAY_INDEX]))(Tree, Key, Node); -} - - -/* - * The lock for the tree must be acquired when this routine is called. - * This routine does not maintain weight information. - */ -BOOLEAN -ExpSearchSplayTreeNoWeight(PSPLAY_TREE Tree, - PVOID Key, - PSPLAY_TREE_NODE Node, - PSPLAY_TREE_NODE * ReturnNode) -{ - LONG Equality; - - if (Node == NULL) - return FALSE; - - Node = ExpSplayTree(Tree, Key, Node); - - Equality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)); - if (ExpSplayTreeNodeEqual(Equality)) - { - /* Found the key */ - - *ReturnNode = Node; - return TRUE; - } - else - { - *ReturnNode = NULL; /* No match */ - return FALSE; /* It wasn't there */ - } -} - - -/* - * The lock for the tree must be acquired when this routine is called. - * This routine maintains weight information. - */ -BOOLEAN -ExpSearchSplayTreeWeight(PSPLAY_TREE Tree, - PVOID Key, - PSPLAY_TREE_NODE Node, - PSPLAY_TREE_NODE * ReturnNode) -{ - PSPLAY_TREE_NODE x = NULL; - LONG Equality; -#ifdef WEIGHT - LONG tweight; -#endif - - if (Node == NULL) - return FALSE; - -#ifdef WEIGHT - tweight = ExpSplayTreeNodeGetWeight(Node); -#endif - - Node = ExpSplayTree(Tree, Key, Node); - - Equality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)); - if (ExpSplayTreeNodeEqual(Equality)) - { - /* Found the key */ - -#ifdef WEIGHT - if (x != NULL) - { - ExpSplayTreeNodeSetWeight(x, tweight - 1); - } -#endif - - *ReturnNode = Node; - return TRUE; - } - else - { - *ReturnNode = NULL; /* No match */ - return FALSE; /* It wasn't there */ - } -} - - -inline BOOLEAN -ExpSearchSplayTree(PSPLAY_TREE Tree, - PVOID Key, - PSPLAY_TREE_NODE Node, - PSPLAY_TREE_NODE * ReturnNode) -{ - return (*((PSPLAY_TREE_SEARCH)Tree->Reserved[SEARCH_INDEX]))(Tree, Key, Node, ReturnNode); -} - - -/* - * The lock for the tree must be acquired when this routine is called. - * This routine does not maintain weight information. - */ -PSPLAY_TREE_NODE -ExpInsertSplayTreeNoWeight(PSPLAY_TREE Tree, - PVOID Key, - PSPLAY_TREE_NODE Node, - PSPLAY_TREE_NODE New) -{ - if (New == NULL) - return Node; - - if (Node != NULL) - { - LONG Equality; - - Node = ExpSplayTree(Tree, Key, Node); - - Equality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)); - if (ExpSplayTreeNodeEqual(Equality)) - { - -#ifdef UNIQUE_KEYS - - /* This is how to prevent the same node key getting added twice */ - return NULL; - -#else - - /* It already exists one of this size */ - - ExpSplayTreeNodeSame(New) = Node; - ExpSplayTreeNodeKey(New) = Key; - ExpSplayTreeSmallerChildNode(New) = ExpSplayTreeSmallerChildNode(Node); - ExpSplayTreeLargerChildNode(New) = ExpSplayTreeLargerChildNode(Node); - - ExpSplayTreeSmallerChildNode(Node) = New; - ExpSplayTreeNodeKey(Node) = KEY_NOTUSED; - - /* New root node */ - return New; - -#endif - - } - } - - if (Node == NULL) - { - ExpSplayTreeSmallerChildNode(New) = NULL; - ExpSplayTreeLargerChildNode(New) = NULL; - } - else if (ExpSplayTreeNodeLess((*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)))) - { - ExpSplayTreeSmallerChildNode(New) = ExpSplayTreeSmallerChildNode(Node); - ExpSplayTreeLargerChildNode(New) = Node; - ExpSplayTreeSmallerChildNode(Node) = NULL; - } - else - { - ExpSplayTreeLargerChildNode(New) = ExpSplayTreeLargerChildNode(Node); - ExpSplayTreeSmallerChildNode(New) = Node; - ExpSplayTreeLargerChildNode(Node) = NULL; - } - - ExpSplayTreeNodeKey(New) = Key; - -#ifndef UNIQUE_KEYS - /* No identical nodes (yet) */ - ExpSplayTreeNodeSame(New) = NULL; -#endif - - return New; -} - - -/* - * The lock for the tree must be acquired when this routine is called. - * This routine maintains weight information. - */ -PSPLAY_TREE_NODE -ExpInsertSplayTreeWeight(PSPLAY_TREE Tree, - PVOID Key, - PSPLAY_TREE_NODE Node, - PSPLAY_TREE_NODE New) -{ - if (New == NULL) - return Node; - - if (Node != NULL) - { - LONG Equality; - - Node = ExpSplayTree(Tree, Key, Node); - - Equality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)); - if (ExpSplayTreeNodeEqual(Equality)) - { - -#ifdef UNIQUE_KEYS - - /* This is how to prevent the same node key getting added twice */ - return NULL; - -#else - - /* It already exists one of this size */ - - ExpSplayTreeNodeSame(New) = Node; - ExpSplayTreeNodeKey(New) = Key; - ExpSplayTreeSmallerChildNode(New) = ExpSplayTreeSmallerChildNode(Node); - ExpSplayTreeLargerChildNode(New) = ExpSplayTreeLargerChildNode(Node); - -#ifdef WEIGHT - ExpSplayTreeNodeSetWeight(New, ExpSplayTreeNodeGetWeight(Node)); -#endif - - ExpSplayTreeSmallerChildNode(Node) = New; - ExpSplayTreeNodeKey(Node) = KEY_NOTUSED; - - /* New root node */ - return New; - -#endif - - } - } - - if (Node == NULL) - { - ExpSplayTreeSmallerChildNode(New) = NULL; - ExpSplayTreeLargerChildNode(New) = NULL; - } - else if (ExpSplayTreeNodeLess((*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)))) - { - ExpSplayTreeSmallerChildNode(New) = ExpSplayTreeSmallerChildNode(Node); - ExpSplayTreeLargerChildNode(New) = Node; - ExpSplayTreeSmallerChildNode(Node) = NULL; - -#ifdef WEIGHT - ExpSplayTreeNodeSetWeight(Node, 1 + ExpSplayTreeNodeGetWeight(ExpSplayTreeLargerChildNode(Node))); -#endif - - } - else - { - ExpSplayTreeLargerChildNode(New) = ExpSplayTreeLargerChildNode(Node); - ExpSplayTreeSmallerChildNode(New) = Node; - ExpSplayTreeLargerChildNode(Node) = NULL; - -#ifdef WEIGHT - ExpSplayTreeNodeSetWeight(Node, 1 + ExpSplayTreeNodeGetWeight(ExpSplayTreeSmallerChildNode(Node))); -#endif - - } - - ExpSplayTreeNodeKey(New) = Key; - -#ifdef WEIGHT - ExpSplayTreeNodeSetWeight(New, 1 + ExpSplayTreeNodeGetWeight(ExpSplayTreeSmallerChildNode(New)) - + ExpSplayTreeNodeGetWeight(ExpSplayTreeLargerChildNode(New))); -#endif - -#ifndef UNIQUE_KEYS - /* No identical nodes (yet) */ - ExpSplayTreeNodeSame(New) = NULL; -#endif - - return New; -} - - -inline PSPLAY_TREE_NODE -ExpInsertSplayTree(PSPLAY_TREE Tree, - PVOID Key, - PSPLAY_TREE_NODE Node, - PSPLAY_TREE_NODE New) -{ - return (*((PSPLAY_TREE_INSERT)Tree->Reserved[INSERT_INDEX]))(Tree, Key, Node, New); -} - - -/* - * Deletes the node with key 'Key' from the tree if it's there. - * Return a pointer to the resulting tree. - * The lock for the tree must be acquired when this routine is called. - * This routine does not maintain weight information. - */ -PSPLAY_TREE_NODE -ExpRemoveSplayTreeNoWeight(PSPLAY_TREE Tree, - PVOID Key, - PSPLAY_TREE_NODE Node, - PSPLAY_TREE_NODE * RemovedNode) -{ - PSPLAY_TREE_NODE x; - LONG Equality; - - if (Node == NULL) - return NULL; - - Node = ExpSplayTree(Tree, Key, Node); - - Equality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)); - if (ExpSplayTreeNodeEqual(Equality)) - { - /* Found the key */ - -#ifndef UNIQUE_KEYS - /* FIRST! Check if there is a list with identical sizes */ - x = ExpSplayTreeNodeSame(Node); - if (x) - { - /* There is several, pick one from the list */ - - /* 'x' is the new root node */ - - ExpSplayTreeNodeKey(x) = ExpSplayTreeNodeKey(Node); - ExpSplayTreeLargerChildNode(x) = ExpSplayTreeLargerChildNode(Node); - ExpSplayTreeSmallerChildNode(x) = ExpSplayTreeSmallerChildNode(Node); - - *RemovedNode = Node; - return x; - } -#endif - - if (ExpSplayTreeSmallerChildNode(Node) == NULL) - { - x = ExpSplayTreeLargerChildNode(Node); - } - else - { - x = ExpSplayTree(Tree, Key, ExpSplayTreeSmallerChildNode(Node)); - ExpSplayTreeLargerChildNode(x) = ExpSplayTreeLargerChildNode(Node); - } - *RemovedNode = Node; - - return x; - } - else - { - *RemovedNode = NULL; /* No match */ - return Node; /* It wasn't there */ - } -} - - -/* - * Deletes the node with key 'Key' from the tree if it's there. - * Return a pointer to the resulting tree. - * The lock for the tree must be acquired when this routine is called. - * This routine maintains weight information. - */ -PSPLAY_TREE_NODE -ExpRemoveSplayTreeWeight(PSPLAY_TREE Tree, - PVOID Key, - PSPLAY_TREE_NODE Node, - PSPLAY_TREE_NODE * RemovedNode) -{ - PSPLAY_TREE_NODE x; - LONG Equality; - -#ifdef WEIGHT - LONG tweight; -#endif - - if (Node == NULL) - return NULL; - -#ifdef WEIGHT - tweight = ExpSplayTreeNodeGetWeight(Node); -#endif - - Node = ExpSplayTree(Tree, Key, Node); - - Equality = (*Tree->Compare)(Key, ExpSplayTreeNodeKey(Node)); - if (ExpSplayTreeNodeEqual(Equality)) - { - /* Found the key */ - -#ifndef UNIQUE_KEYS - /* FIRST! Check if there is a list with identical sizes */ - x = ExpSplayTreeNodeSame(Node); - if (x) - { - /* There is several, pick one from the list */ - - /* 'x' is the new root node */ - - ExpSplayTreeNodeKey(x) = ExpSplayTreeNodeKey(Node); - ExpSplayTreeLargerChildNode(x) = ExpSplayTreeLargerChildNode(Node); - ExpSplayTreeSmallerChildNode(x) = ExpSplayTreeSmallerChildNode(Node); - -#ifdef WEIGHT - ExpSplayTreeNodeSetWeight(x, ExpSplayTreeNodeGetWeight(Node)); -#endif - - *RemovedNode = Node; - return x; - } -#endif - - if (ExpSplayTreeSmallerChildNode(Node) == NULL) - { - x = ExpSplayTreeLargerChildNode(Node); - } - else - { - x = ExpSplayTree(Tree, Key, ExpSplayTreeSmallerChildNode(Node)); - ExpSplayTreeLargerChildNode(x) = ExpSplayTreeLargerChildNode(Node); - } - *RemovedNode = Node; - -#ifdef WEIGHT - if (x != NULL) - { - ExpSplayTreeNodeSetWeight(x, tweight - 1); - } -#endif - - return x; - } - else - { - *RemovedNode = NULL; /* No match */ - return Node; /* It wasn't there */ - } -} - - -inline PSPLAY_TREE_NODE -ExpRemoveSplayTree(PSPLAY_TREE Tree, - PVOID Key, - PSPLAY_TREE_NODE Node, - PSPLAY_TREE_NODE * RemovedNode) -{ - return (*((PSPLAY_TREE_REMOVE)Tree->Reserved[REMOVE_INDEX]))(Tree, Key, Node, RemovedNode); -} - - -/* - * The lock for the tree must be acquired when this routine is called. - */ -ULONG -ExpPrintSplayTree(PSPLAY_TREE Tree, - PSPLAY_TREE_NODE Node, - ULONG Distance) -{ - PSPLAY_TREE_NODE n; - ULONG d = 0; - ULONG i; - - if (Node == NULL) - return 0; - - Distance += ExpPrintSplayTree(Tree, ExpSplayTreeLargerChildNode(Node), Distance + 1); - - for (i = 0; i < Distance; i++) - { - DbgPrint(" "); - } - - if (Tree->Weighted) - { - DbgPrint("%d(%d)[%d]", ExpSplayTreeNodeKey(Node), ExpSplayTreeNodeGetWeight(Node), i); - } - else - { - DbgPrint("%d[%d]", ExpSplayTreeNodeKey(Node), i); - } - - for (n = ExpSplayTreeNodeSame(Node); n; n = ExpSplayTreeNodeSame(n)) - { - d += i; - - DbgPrint(" [+]"); - } - - d += i; - - d += ExpPrintSplayTree(Tree, ExpSplayTreeSmallerChildNode(Node), Distance + 1); - - return d; -} - - -#define MAX_DIFF 4 - -#ifdef WEIGHT - -/* - * The lock for the tree must be acquired when this routine is called. - * Returns the new root of the tree. - * Use of this routine could improve performance, or it might not. - * FIXME: Do some performance tests - */ -PSPLAY_TREE_NODE -ExpSplayTreeMaxTreeWeight(PSPLAY_TREE Tree, - PSPLAY_TREE_NODE Node) -{ - PSPLAY_TREE_NODE First = Node; - LONG Diff; - - do - { - Diff = ExpSplayTreeNodeGetWeight(ExpSplayTreeSmallerChildNode(Node)) - - ExpSplayTreeNodeGetWeight(ExpSplayTreeLargerChildNode(Node)); - - if (Diff >= MAX_DIFF) - { - Node = ExpSplayTreeSmallerChildNode(Node); - } - else if (Diff <= -MAX_DIFF) - { - Node = ExpSplayTreeLargerChildNode(Node); - } - else - break; - } while (abs(Diff) >= MAX_DIFF); - - if (Node != First) - return ExpSplayTree(Tree, ExpSplayTreeNodeKey(Node), First); - else - return First; -} - -#endif - - -/* - * Traverse a splay tree using preorder traversal method. - * Returns FALSE, if the traversal was terminated prematurely or - * TRUE if the callback routine did not request that the traversal - * be terminated prematurely. - * The lock for the tree must be acquired when this routine is called. - */ -BOOLEAN -ExpTraverseSplayTreePreorder(PTRAVERSE_CONTEXT Context, - PSPLAY_TREE_NODE Node) -{ - PSPLAY_TREE_NODE n; - - if (Node == NULL) - return TRUE; - - /* Call the traversal routine */ - if (!(*Context->Routine)(Context->Context, - ExpSplayTreeNodeKey(Node), - ExpSplayTreeNodeValue(Node))) - { - return FALSE; - } - - for (n = ExpSplayTreeNodeSame(Node); n; n = ExpSplayTreeNodeSame(n)) - { - /* Call the traversal routine */ - if (!(*Context->Routine)(Context->Context, - ExpSplayTreeNodeKey(n), - ExpSplayTreeNodeValue(n))) - { - return FALSE; - } - } - - /* Traverse 'smaller' subtree */ - ExpTraverseSplayTreePreorder(Context, ExpSplayTreeSmallerChildNode(Node)); - - /* Traverse 'larger' subtree */ - ExpTraverseSplayTreePreorder(Context, ExpSplayTreeLargerChildNode(Node)); - - return TRUE; -} - - -/* - * Traverse a splay tree using inorder traversal method. - * Returns FALSE, if the traversal was terminated prematurely or - * TRUE if the callback routine did not request that the traversal - * be terminated prematurely. - * The lock for the tree must be acquired when this routine is called. - */ -BOOLEAN -ExpTraverseSplayTreeInorder(PTRAVERSE_CONTEXT Context, - PSPLAY_TREE_NODE Node) -{ - PSPLAY_TREE_NODE n; - - if (Node == NULL) - return TRUE; - - /* Traverse 'smaller' subtree */ - ExpTraverseSplayTreeInorder(Context, ExpSplayTreeSmallerChildNode(Node)); - - /* Call the traversal routine */ - if (!(*Context->Routine)(Context->Context, - ExpSplayTreeNodeKey(Node), - ExpSplayTreeNodeValue(Node))) - { - return FALSE; - } - - for (n = ExpSplayTreeNodeSame(Node); n; n = ExpSplayTreeNodeSame(n)) - { - /* Call the traversal routine */ - if (!(*Context->Routine)(Context->Context, - ExpSplayTreeNodeKey(n), - ExpSplayTreeNodeValue(n))) - { - return FALSE; - } - } - - /* Traverse right subtree */ - ExpTraverseSplayTreeInorder(Context, ExpSplayTreeLargerChildNode(Node)); - - return TRUE; -} - - -/* - * Traverse a splay tree using postorder traversal method. - * Returns FALSE, if the traversal was terminated prematurely or - * TRUE if the callback routine did not request that the traversal - * be terminated prematurely. - * The lock for the tree must be acquired when this routine is called. - */ -BOOLEAN -ExpTraverseSplayTreePostorder(PTRAVERSE_CONTEXT Context, - PSPLAY_TREE_NODE Node) -{ - PSPLAY_TREE_NODE n; - - if (Node == NULL) - return TRUE; - - /* Traverse 'smaller' subtree */ - ExpTraverseSplayTreePostorder(Context, ExpSplayTreeSmallerChildNode(Node)); - - /* Traverse 'larger' subtree */ - ExpTraverseSplayTreePostorder(Context, ExpSplayTreeLargerChildNode(Node)); - - /* Call the traversal routine */ - if (!(*Context->Routine)(Context->Context, - ExpSplayTreeNodeKey(Node), - ExpSplayTreeNodeValue(Node))) - { - return FALSE; - } - - for (n = ExpSplayTreeNodeSame(Node); n; n = ExpSplayTreeNodeSame(n)) - { - /* Call the traversal routine */ - if (!(*Context->Routine)(Context->Context, - ExpSplayTreeNodeKey(n), - ExpSplayTreeNodeValue(n))) - { - return FALSE; - } - } - - return TRUE; -} - - -/* - * Default key compare function. Compares the integer values of the two keys. - */ -LONG STDCALL -ExpSplayTreeDefaultCompare(IN PVOID Key1, - IN PVOID Key2) -{ - if (Key1 == Key2) - return 0; - - return (((LONG_PTR) Key1 < (LONG_PTR) Key2) ? -1 : 1); -} - - -/* - * Initializes a splay tree. - */ -BOOLEAN STDCALL -ExInitializeSplayTree(IN PSPLAY_TREE Tree, - IN PKEY_COMPARATOR Compare, - IN BOOLEAN Weighted, - IN BOOLEAN UseNonPagedPool) -{ - RtlZeroMemory(Tree, sizeof(SPLAY_TREE)); - - Tree->Compare = (Compare == NULL) - ? ExpSplayTreeDefaultCompare : Compare; - - Tree->Weighted = Weighted; - - if (Weighted) - { - Tree->Reserved[SPLAY_INDEX] = (PVOID) ExpSplayTreeWeight; - Tree->Reserved[SEARCH_INDEX] = (PVOID) ExpSearchSplayTreeWeight; - Tree->Reserved[INSERT_INDEX] = (PVOID) ExpInsertSplayTreeWeight; - Tree->Reserved[REMOVE_INDEX] = (PVOID) ExpRemoveSplayTreeWeight; - } - else - { - Tree->Reserved[SPLAY_INDEX] = (PVOID) ExpSplayTreeNoWeight; - Tree->Reserved[SEARCH_INDEX] = (PVOID) ExpSearchSplayTreeNoWeight; - Tree->Reserved[INSERT_INDEX] = (PVOID) ExpInsertSplayTreeNoWeight; - Tree->Reserved[REMOVE_INDEX] = (PVOID) ExpRemoveSplayTreeNoWeight; - } - - Tree->UseNonPagedPool = UseNonPagedPool; - - if (UseNonPagedPool) - { - ExInitializeNPagedLookasideList( - &Tree->List.NonPaged, /* Lookaside list */ - NULL, /* Allocate routine */ - NULL, /* Free routine */ - 0, /* Flags */ - sizeof(SPLAY_TREE_NODE), /* Size of each entry */ - TAG('E','X','S','T'), /* Tag */ - 0); /* Depth */ - - KeInitializeSpinLock(&Tree->Lock.NonPaged); - } - else - { - ExInitializePagedLookasideList( - &Tree->List.Paged, /* Lookaside list */ - NULL, /* Allocate routine */ - NULL, /* Free routine */ - 0, /* Flags */ - sizeof(SPLAY_TREE_NODE), /* Size of each entry */ - TAG('E','X','S','T'), /* Tag */ - 0); /* Depth */ - - ExInitializeFastMutex(&Tree->Lock.Paged); - } - - return TRUE; -} - - -/* - * Release resources used by a splay tree. - */ -VOID STDCALL -ExDeleteSplayTree(IN PSPLAY_TREE Tree) -{ - PSPLAY_TREE_NODE RemovedNode; - PSPLAY_TREE_NODE Node; - - /* Remove all nodes */ - Node = ExpSplayTreeRootNode(Tree); - while (Node != NULL) - { - Node = ExpRemoveSplayTree(Tree, Node->Key, Node, &RemovedNode); - - if (RemovedNode != NULL) - { - ExpDestroySplayTreeNode(Tree, RemovedNode); - } - } - - if (Tree->UseNonPagedPool) - { - ExDeleteNPagedLookasideList(&Tree->List.NonPaged); - } - else - { - ExDeletePagedLookasideList(&Tree->List.Paged); - } -} - - -/* - * Insert a value in a splay tree. - */ -VOID STDCALL -ExInsertSplayTree(IN PSPLAY_TREE Tree, - IN PVOID Key, - IN PVOID Value) -{ - PSPLAY_TREE_NODE Node; - PSPLAY_TREE_NODE NewNode; - KIRQL OldIrql; - - /* FIXME: Use SEH for error reporting */ - - NewNode = ExpCreateSplayTreeNode(Tree, Value); - - ExpLockSplayTree(Tree, &OldIrql); - Node = ExpInsertSplayTree(Tree, Key, ExpSplayTreeRootNode(Tree), NewNode); - ExpSplayTreeRootNode(Tree) = Node; - ExpUnlockSplayTree(Tree, &OldIrql); -} - - -/* - * Search for a value associated with a given key in a splay tree. - */ -BOOLEAN STDCALL -ExSearchSplayTree(IN PSPLAY_TREE Tree, - IN PVOID Key, - OUT PVOID * Value) -{ - PSPLAY_TREE_NODE Node; - BOOLEAN Status; - KIRQL OldIrql; - - ExpLockSplayTree(Tree, &OldIrql); - Status = ExpSearchSplayTree(Tree, Key, ExpSplayTreeRootNode(Tree), &Node); - - if (Status) - { - ExpSplayTreeRootNode(Tree) = Node; - *Value = ExpSplayTreeNodeValue(Node); - ExpUnlockSplayTree(Tree, &OldIrql); - return TRUE; - } - else - { - ExpUnlockSplayTree(Tree, &OldIrql); - return FALSE; - } -} - - -/* - * Remove a value associated with a given key from a splay tree. - */ -BOOLEAN STDCALL -ExRemoveSplayTree(IN PSPLAY_TREE Tree, - IN PVOID Key, - IN PVOID * Value) -{ - PSPLAY_TREE_NODE RemovedNode; - PSPLAY_TREE_NODE Node; - KIRQL OldIrql; - - ExpLockSplayTree(Tree, &OldIrql); - Node = ExpRemoveSplayTree(Tree, Key, ExpSplayTreeRootNode(Tree), &RemovedNode); - ExpSplayTreeRootNode(Tree) = Node; - ExpUnlockSplayTree(Tree, &OldIrql); - - if (RemovedNode != NULL) - { - *Value = ExpSplayTreeNodeValue(RemovedNode); - ExpDestroySplayTreeNode(Tree, RemovedNode); - return TRUE; - } - else - { - return FALSE; - } -} - - -/* - * Return the weight of the root node in the splay tree. - * The returned value is the number of nodes in the tree. - */ -BOOLEAN STDCALL -ExWeightOfSplayTree(IN PSPLAY_TREE Tree, - OUT PULONG Weight) -{ - KIRQL OldIrql; - - ExpLockSplayTree(Tree, &OldIrql); - - if (!Tree->Weighted) - { - ExpUnlockSplayTree(Tree, &OldIrql); - return FALSE; - } - - *Weight = ExpSplayTreeNodeWeight(ExpSplayTreeRootNode(Tree)); - ExpUnlockSplayTree(Tree, &OldIrql); - - return TRUE; -} - - -/* - * Traverse a splay tree using either preorder, inorder or postorder - * traversal method. - * Returns FALSE, if the traversal was terminated prematurely or - * TRUE if the callback routine did not request that the traversal - * be terminated prematurely. - */ -BOOLEAN STDCALL -ExTraverseSplayTree(IN PSPLAY_TREE Tree, - IN TRAVERSE_METHOD Method, - IN PTRAVERSE_ROUTINE Routine, - IN PVOID Context) -{ - TRAVERSE_CONTEXT tc; - BOOLEAN Status; - KIRQL OldIrql; - - tc.Routine = Routine; - tc.Context = Context; - - ExpLockSplayTree(Tree, &OldIrql); - - if (ExpSplayTreeRootNode(Tree) == NULL) - { - ExpUnlockSplayTree(Tree, &OldIrql); - return TRUE; - } - - switch (Method) - { - case TraverseMethodPreorder: - Status = ExpTraverseSplayTreePreorder(&tc, ExpSplayTreeRootNode(Tree)); - break; - - case TraverseMethodInorder: - Status = ExpTraverseSplayTreeInorder(&tc, ExpSplayTreeRootNode(Tree)); - break; - - case TraverseMethodPostorder: - Status = ExpTraverseSplayTreePostorder(&tc, ExpSplayTreeRootNode(Tree)); - break; - - default: - Status = FALSE; - break; - } - - ExpUnlockSplayTree(Tree, &OldIrql); - - return Status; -} - -/* EOF */ diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index a25b2f8a7d6..a89cd9784ea 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -65,56 +65,23 @@ KeIpiGenericCall(VOID (STDCALL *WorkerRoutine)(PVOID), /* next file ***************************************************************/ -typedef struct _KPROCESS_PROFILE -/* - * List of the profile data structures associated with a process. - */ -{ - LIST_ENTRY ProfileListHead; - LIST_ENTRY ListEntry; - HANDLE Pid; -} KPROCESS_PROFILE, *PKPROCESS_PROFILE; +typedef struct _KPROFILE_SOURCE_OBJECT { + KPROFILE_SOURCE Source; + LIST_ENTRY ListEntry; +} KPROFILE_SOURCE_OBJECT, *PKPROFILE_SOURCE_OBJECT; -typedef struct _KPROFILE -/* - * Describes a contiguous region of process memory that is being profiled. - */ -{ - CSHORT Type; - CSHORT Name; - - /* Entry in the list of profile data structures for this process. */ - LIST_ENTRY ListEntry; - - /* Base of the region being profiled. */ - PVOID Base; - - /* Size of the region being profiled. */ - ULONG Size; - - /* Shift of offsets from the region to buckets in the profiling buffer. */ - ULONG BucketShift; - - /* MDL which described the buffer that receives profiling data. */ - struct _MDL *BufferMdl; - - /* System alias for the profiling buffer. */ - PULONG Buffer; - - /* Size of the buffer for profiling data. */ - ULONG BufferSize; - - /* - * Mask of processors for which profiling data should be collected. - * Currently unused. - */ - ULONG ProcessorMask; - - /* TRUE if profiling has been started for this region. */ - BOOLEAN Started; - - /* Pointer (and reference) to the process which is being profiled. */ - struct _EPROCESS *Process; +typedef struct _KPROFILE { + CSHORT Type; + CSHORT Size; + LIST_ENTRY ListEntry; + PVOID RegionStart; + PVOID RegionEnd; + ULONG BucketShift; + PVOID Buffer; + CSHORT Source; + ULONG Affinity; + BOOLEAN Active; + struct _KPROCESS *Process; } KPROFILE, *PKPROFILE; /* Cached modules from the loader block */ @@ -131,6 +98,34 @@ extern PLOADER_MODULE CachedModules[MaximumCachedModuleType]; VOID STDCALL DbgBreakPointNoBugCheck(VOID); +STDCALL +VOID +KeInitializeProfile(struct _KPROFILE* Profile, + struct _KPROCESS* Process, + PVOID ImageBase, + ULONG ImageSize, + ULONG BucketSize, + KPROFILE_SOURCE ProfileSource, + KAFFINITY Affinity); + +STDCALL +VOID +KeStartProfile(struct _KPROFILE* Profile, + PVOID Buffer); + +STDCALL +VOID +KeStopProfile(struct _KPROFILE* Profile); + +STDCALL +ULONG +KeQueryIntervalProfile(KPROFILE_SOURCE ProfileSource); + +STDCALL +VOID +KeSetIntervalProfile(KPROFILE_SOURCE ProfileSource, + ULONG Interval); + VOID STDCALL KeProfileInterrupt( @@ -144,8 +139,6 @@ KeProfileInterruptWithSource( IN KPROFILE_SOURCE Source ); -VOID KiAddProfileEventToProcess(PLIST_ENTRY ListHead, PVOID Eip); -VOID KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Eip); VOID KiInsertProfileIntoProcess(PLIST_ENTRY ListHead, PKPROFILE Profile); VOID KiInsertProfile(PKPROFILE Profile); VOID KiRemoveProfile(PKPROFILE Profile); diff --git a/reactos/ntoskrnl/io/irp.c b/reactos/ntoskrnl/io/irp.c index ed98e86d973..7f3a7701689 100644 --- a/reactos/ntoskrnl/io/irp.c +++ b/reactos/ntoskrnl/io/irp.c @@ -410,7 +410,16 @@ IofCompleteRequest(PIRP Irp, if (Irp->UserIosb) { - *Irp->UserIosb = Irp->IoStatus; + _SEH_TRY + { + *Irp->UserIosb = Irp->IoStatus; + } + _SEH_HANDLE + { + DPRINT1("Unable to set UserIosb (at 0x%x) to 0x%x, Error: 0x%x\n", + Irp->UserIosb, Irp->IoStatus, _SEH_GetExceptionCode()); + } + _SEH_END; } if (Irp->UserEvent) diff --git a/reactos/ntoskrnl/kd/kdebug.c b/reactos/ntoskrnl/kd/kdebug.c index bc403f3cab0..8c6e357fad0 100644 --- a/reactos/ntoskrnl/kd/kdebug.c +++ b/reactos/ntoskrnl/kd/kdebug.c @@ -243,12 +243,6 @@ KdInitSystem(ULONG BootPhase, } } } -#if defined(KDBG) || defined(DBG) - else if (!_strnicmp(p2, "PROFILE", 7) && BootPhase > 0) - { - KdbInitProfiling(); - } -#endif /* KDBG */ p1 = p2; } diff --git a/reactos/ntoskrnl/ke/i386/irq.c b/reactos/ntoskrnl/ke/i386/irq.c index 865dd302fcb..22d269b69ac 100644 --- a/reactos/ntoskrnl/ke/i386/irq.c +++ b/reactos/ntoskrnl/ke/i386/irq.c @@ -340,9 +340,6 @@ KiInterruptDispatch (ULONG vector, PKIRQ_TRAPFRAME Trapframe) { KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame); KeUpdateSystemTime(&KernelTrapFrame, old_level); -#if defined(KDBG) || defined(DBG) - KdbProfileInterrupt(Trapframe->Eip); -#endif /* KDBG */ } else #endif diff --git a/reactos/ntoskrnl/ke/profile.c b/reactos/ntoskrnl/ke/profile.c index 454e15c3afc..cb2279bf878 100644 --- a/reactos/ntoskrnl/ke/profile.c +++ b/reactos/ntoskrnl/ke/profile.c @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/profile.c @@ -8,335 +7,294 @@ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) */ +/* INCLUDES *****************************************************************/ #include #define NDEBUG #include -extern LIST_ENTRY ProcessProfileListHashTable[PROFILE_HASH_TABLE_SIZE]; -extern LIST_ENTRY SystemProfileList; -extern KSPIN_LOCK ProfileListLock; -extern BOOLEAN ProfileInitDone; +/* GLOBALS *******************************************************************/ + +KIRQL KiProfileIrql = PROFILE_LEVEL; +LIST_ENTRY KiProfileListHead; +LIST_ENTRY KiProfileSourceListHead; +KSPIN_LOCK KiProfileLock; +ULONG KiProfileTimeInterval = 78125; /* Default resolution 7.8ms (sysinternals) */ /* FUNCTIONS *****************************************************************/ +STDCALL VOID -KiAddProfileEventToProcess(PLIST_ENTRY ListHead, PVOID Eip) - /* - * Add a profile event to the profile objects for a particular process - * or the system - */ +KeInitializeProfile(PKPROFILE Profile, + PKPROCESS Process, + PVOID ImageBase, + ULONG ImageSize, + ULONG BucketSize, + KPROFILE_SOURCE ProfileSource, + KAFFINITY Affinity) { - PKPROFILE current; - PLIST_ENTRY current_entry; - - current_entry = ListHead->Flink; - while (current_entry != ListHead) - { - current = CONTAINING_RECORD(current_entry, KPROFILE, ListEntry); - - if (current->Base > Eip) - { - return; - } - - if (current->Base <= Eip && ((char*)current->Base + current->Size) > (char*)Eip && - current->Started) - { - ULONG Bucket; - - Bucket = ((ULONG)((char*)Eip - (char*)current->Base)) >> current->BucketShift; - - if ((Bucket*4) < current->BufferSize) - { - current->Buffer[Bucket]++; - } - } - - current_entry = current_entry->Flink; - } -} - -VOID -KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Eip) - /* - * Add a profile event - */ -{ - HANDLE Pid; - PKPROCESS_PROFILE current; - PLIST_ENTRY current_entry; - PLIST_ENTRY ListHead; - - if (!ProfileInitDone) - { - return; - } - - Pid = PsGetCurrentProcessId(); - ListHead = - ProcessProfileListHashTable[(ULONG)Pid % PROFILE_HASH_TABLE_SIZE].Flink; - - KeAcquireSpinLockAtDpcLevel(&ProfileListLock); - - current_entry = ListHead; - while (current_entry != ListHead) - { - current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE, ListEntry); - - if (current->Pid == Pid) - { - KiAddProfileEventToProcess(¤t->ProfileListHead, (PVOID)Eip); - break; - } - - current_entry = current_entry->Flink; - } - - KiAddProfileEventToProcess(&SystemProfileList, (PVOID)Eip); - - KeReleaseSpinLockFromDpcLevel(&ProfileListLock); -} - -VOID -KiInsertProfileIntoProcess(PLIST_ENTRY ListHead, PKPROFILE Profile) - /* - * Insert a profile object into the list for a process or the system - */ -{ - PKPROFILE current; - PLIST_ENTRY current_entry; - - current_entry = ListHead; - while (current_entry != ListHead) - { - current = CONTAINING_RECORD(current_entry, KPROFILE, ListEntry); - - if (current->Base > Profile->Base) - { - Profile->ListEntry.Flink = current_entry; - Profile->ListEntry.Blink = current_entry->Blink; - current_entry->Blink->Flink = &Profile->ListEntry; - current_entry->Blink = &Profile->ListEntry; - return; - } - - current_entry = current_entry->Flink; - } - InsertTailList(ListHead, &Profile->ListEntry); -} - -VOID -KiInsertProfile(PKPROFILE Profile) - /* - * Insert a profile into the relevant data structures - */ -{ - KIRQL oldIrql; - - KeAcquireSpinLock(&ProfileListLock, &oldIrql); - - if (Profile->Process == NULL) - { - KiInsertProfileIntoProcess(&SystemProfileList, Profile); - } - else - { - HANDLE Pid; - PKPROCESS_PROFILE current; - PLIST_ENTRY current_entry; - PLIST_ENTRY ListHead; - - Pid = Profile->Process->UniqueProcessId; - ListHead = &ProcessProfileListHashTable[(ULONG_PTR)Pid % PROFILE_HASH_TABLE_SIZE]; - - current_entry = ListHead; - while(current_entry != ListHead) - { - current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE, - ListEntry); - - if (current->Pid == Pid) - { - KiInsertProfileIntoProcess(¤t->ProfileListHead, Profile); - KeReleaseSpinLock(&ProfileListLock, oldIrql); - return; - } - - current_entry = current_entry->Flink; - } - - current = ExAllocatePool(NonPagedPool, sizeof(KPROCESS_PROFILE)); - - current->Pid = Pid; - InitializeListHead(¤t->ProfileListHead); - InsertTailList(ListHead, ¤t->ListEntry); - - KiInsertProfileIntoProcess(¤t->ProfileListHead, Profile); - } - - KeReleaseSpinLock(&ProfileListLock, oldIrql); -} - -VOID KiRemoveProfile(PKPROFILE Profile) -{ - KIRQL oldIrql; - - KeAcquireSpinLock(&ProfileListLock, &oldIrql); - - if (Profile->Process == NULL) - { - RemoveEntryList(&Profile->ListEntry); - } - else - { - HANDLE Pid; - PLIST_ENTRY ListHead; - PKPROCESS_PROFILE current; - PLIST_ENTRY current_entry; - - RemoveEntryList(&Profile->ListEntry); - - Pid = Profile->Process->UniqueProcessId; - ListHead = &ProcessProfileListHashTable[(ULONG_PTR)Pid % PROFILE_HASH_TABLE_SIZE]; - - current_entry = ListHead; - while(current_entry != ListHead) - { - current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE, - ListEntry); - - if (current->Pid == Pid) - { - if (IsListEmpty(¤t->ProfileListHead)) - { - RemoveEntryList(¤t->ListEntry); - ExFreePool(current); - } - KeReleaseSpinLock(&ProfileListLock, oldIrql); - return; - } - - current_entry = current_entry->Flink; - } - KEBUGCHECK(0); - } - - KeReleaseSpinLock(&ProfileListLock, oldIrql); -} - -VOID STDCALL -KiDeleteProfile(PVOID ObjectBody) -{ - PKPROFILE Profile; - - Profile = (PKPROFILE)ObjectBody; - - KiRemoveProfile(Profile); - if (Profile->Process != NULL) - { - ObDereferenceObject(Profile->Process); - Profile->Process = NULL; - } - - if (Profile->BufferMdl->MappedSystemVa != NULL) - { - MmUnmapLockedPages(Profile->BufferMdl->MappedSystemVa, - Profile->BufferMdl); - } - MmUnlockPages(Profile->BufferMdl); - ExFreePool(Profile->BufferMdl); - Profile->BufferMdl = NULL; -} - -/* - * @unimplemented - */ -STDCALL -VOID -KeProfileInterrupt( - PKTRAP_FRAME TrapFrame -) -{ - UNIMPLEMENTED; -} - -/* - * @unimplemented - */ -STDCALL -VOID -KeProfileInterruptWithSource( - IN PKTRAP_FRAME TrapFrame, - IN KPROFILE_SOURCE Source -) -{ - UNIMPLEMENTED; -} - -/* - * @unimplemented - */ -STDCALL -VOID -KeSetProfileIrql( - IN KIRQL ProfileIrql -) -{ - UNIMPLEMENTED; -} - -NTSTATUS STDCALL -NtQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceCounter, - OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL) -{ - LARGE_INTEGER PerfCounter; - LARGE_INTEGER PerfFrequency; - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; - - PreviousMode = ExGetPreviousMode(); - - if(PreviousMode != KernelMode) - { - _SEH_TRY - { - ProbeForWrite(PerformanceCounter, - sizeof(LARGE_INTEGER), - sizeof(ULONG)); - if(PerformanceFrequency != NULL) - { - ProbeForWrite(PerformanceFrequency, - sizeof(LARGE_INTEGER), - sizeof(ULONG)); - } - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; + /* Initialize the Header */ + Profile->Type = ProfileObject; + Profile->Size = sizeof(KPROFILE); - if(!NT_SUCCESS(Status)) - { - return Status; - } - } - - PerfCounter = KeQueryPerformanceCounter(&PerfFrequency); - - _SEH_TRY - { - *PerformanceCounter = PerfCounter; - if(PerformanceFrequency != NULL) - { - *PerformanceFrequency = PerfFrequency; - } - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - return Status; + /* Copy all the settings we were given */ + Profile->Process = Process; + Profile->RegionStart = ImageBase; + Profile->BucketShift = BucketSize - 2; /* See ntinternals.net -- Alex */ + Profile->RegionEnd = (PVOID)(ULONG_PTR)ImageBase + ImageSize; + Profile->Active = FALSE; + Profile->Source = ProfileSource; + Profile->Affinity = Affinity; +} + +STDCALL +VOID +KeStartProfile(PKPROFILE Profile, + PVOID Buffer) +{ + KIRQL OldIrql; + PKPROFILE_SOURCE_OBJECT SourceBuffer; + PKPROFILE_SOURCE_OBJECT Source = NULL; + PKPROFILE_SOURCE_OBJECT CurrentSource; + BOOLEAN FreeBuffer = TRUE; + PKPROCESS ProfileProcess; + PLIST_ENTRY ListEntry; + + /* Allocate a buffer first, before we raise IRQL */ + SourceBuffer = ExAllocatePoolWithTag(NonPagedPool, + sizeof(KPROFILE_SOURCE_OBJECT), + TAG('P', 'r', 'o', 'f')); + RtlZeroMemory(Source, sizeof(KPROFILE_SOURCE_OBJECT)); + + /* Raise to PROFILE_LEVEL */ + KeRaiseIrql(PROFILE_LEVEL, &OldIrql); + KeAcquireSpinLockAtDpcLevel(&KiProfileLock); + + /* Make sure it's not running */ + if (!Profile->Active) { + + /* Set it as active */ + Profile->Buffer = Buffer; + Profile->Active = TRUE; + + /* Get the process, if any */ + ProfileProcess = Profile->Process; + + /* Insert it into the Process List or Global List */ + if (ProfileProcess) { + + InsertTailList(&ProfileProcess->ProfileListHead, &Profile->ListEntry); + + } else { + + InsertTailList(&KiProfileListHead, &Profile->ListEntry); + } + + /* Check if this type of profile (source) is already running */ + for (ListEntry = KiProfileSourceListHead.Flink; + ListEntry != &KiProfileSourceListHead; + ListEntry = ListEntry->Flink) { + + /* Get the Source Object */ + CurrentSource = CONTAINING_RECORD(ListEntry, + KPROFILE_SOURCE_OBJECT, + ListEntry); + + /* Check if it's the same as the one being requested now */ + if (CurrentSource->Source == Profile->Source) { + + Source = CurrentSource; + break; + } + } + + /* See if the loop found something */ + if (!Source) { + + /* Nothing found, use our allocated buffer */ + Source = SourceBuffer; + + /* Set up the Source Object */ + Source->Source = Profile->Source; + InsertHeadList(&KiProfileSourceListHead, &Source->ListEntry); + + /* Don't free the pool later on */ + FreeBuffer = FALSE; + } + } + + /* Lower the IRQL */ + KeReleaseSpinLockFromDpcLevel(&KiProfileLock); + KeLowerIrql(OldIrql); + + /* FIXME: Tell HAL to Start the Profile Interrupt */ + //HalStartProfileInterrupt(Profile->Source); + + /* Free the pool */ + if (!FreeBuffer) ExFreePool(SourceBuffer); +} + +STDCALL +VOID +KeStopProfile(PKPROFILE Profile) +{ + KIRQL OldIrql; + PLIST_ENTRY ListEntry; + PKPROFILE_SOURCE_OBJECT CurrentSource = NULL; + + /* Raise to PROFILE_LEVEL and acquire spinlock */ + KeRaiseIrql(PROFILE_LEVEL, &OldIrql); + KeAcquireSpinLockAtDpcLevel(&KiProfileLock); + + /* Make sure it's running */ + if (Profile->Active) { + + /* Remove it from the list and disable */ + RemoveEntryList(&Profile->ListEntry); + Profile->Active = FALSE; + + /* Find the Source Object */ + for (ListEntry = KiProfileSourceListHead.Flink; + CurrentSource->Source != Profile->Source; + ListEntry = ListEntry->Flink) { + + /* Get the Source Object */ + CurrentSource = CONTAINING_RECORD(ListEntry, + KPROFILE_SOURCE_OBJECT, + ListEntry); + } + + /* Remove it */ + RemoveEntryList(&CurrentSource->ListEntry); + } + + /* Lower IRQL */ + KeReleaseSpinLockFromDpcLevel(&KiProfileLock); + KeLowerIrql(OldIrql); + + /* Stop Profiling. FIXME: Implement in HAL */ + //HalStopProfileInterrupt(Profile->Source); + + /* Free the Source Object */ + if (CurrentSource) ExFreePool(CurrentSource); +} + +STDCALL +ULONG +KeQueryIntervalProfile(KPROFILE_SOURCE ProfileSource) +{ + /* Check if this is the timer profile */ + if (ProfileSource == ProfileTime) { + + /* Return the good old 100ns sampling interval */ + return KiProfileTimeInterval; + + } else { + + /* Request it from HAL. FIXME: What structure is used? */ + HalQuerySystemInformation(HalProfileSourceInformation, + sizeof(NULL), + NULL, + NULL); + + return 0; + } +} + +STDCALL +VOID +KeSetIntervalProfile(KPROFILE_SOURCE ProfileSource, + ULONG Interval) +{ + /* Check if this is the timer profile */ + if (ProfileSource == ProfileTime) { + + /* Set the good old 100ns sampling interval */ + KiProfileTimeInterval = Interval; + + } else { + + /* Set it with HAL. FIXME: What structure is used? */ + HalSetSystemInformation(HalProfileSourceInformation, + sizeof(NULL), + NULL); + + } +} + +/* + * @implemented + */ +STDCALL +VOID +KeProfileInterrupt(PKTRAP_FRAME TrapFrame) +{ + /* Called from HAL for Timer Profiling */ + KeProfileInterruptWithSource(TrapFrame, ProfileTime); +} + +VOID +STDCALL +KiParseProfileList(IN PKTRAP_FRAME TrapFrame, + IN KPROFILE_SOURCE Source, + IN PLIST_ENTRY ListHead) +{ + PULONG BucketValue; + PKPROFILE Profile; + PLIST_ENTRY NextEntry; + + /* Loop the List */ + for (NextEntry = ListHead->Flink; NextEntry != ListHead; NextEntry = NextEntry->Flink) { + + /* Get the Current Profile in the List */ + Profile = CONTAINING_RECORD(NextEntry, KPROFILE, ListEntry); + + /* Check if the source is good, and if it's within the range */ + if ((Profile->Source != Source) || + (TrapFrame->Eip < (ULONG_PTR)Profile->RegionStart) || + (TrapFrame->Eip > (ULONG_PTR)Profile->RegionEnd)) { + + continue; + } + + /* Get the Pointer to the Bucket Value representing this EIP */ + BucketValue = (PULONG)(((ULONG_PTR)(Profile->Buffer + + (TrapFrame->Eip - (ULONG_PTR)Profile->RegionStart)) + >> Profile->BucketShift) &~ 0x3); + + /* Increment the value */ + ++BucketValue; + } +} + +/* + * @implemented + * + * Remarks: + * Called from HAL, this function looks up the process + * entries, finds the proper source object, verifies the + * ranges with the trapframe data, and inserts the information + * from the trap frame into the buffer, while using buckets and + * shifting like we specified. -- Alex + */ +STDCALL +VOID +KeProfileInterruptWithSource(IN PKTRAP_FRAME TrapFrame, + IN KPROFILE_SOURCE Source) +{ + PKPROCESS Process = KeGetCurrentThread()->ApcState.Process; + + /* We have to parse 2 lists. Per-Process and System-Wide */ + KiParseProfileList(TrapFrame, Source, &Process->ProfileListHead); + KiParseProfileList(TrapFrame, Source, &KiProfileListHead); +} + +/* + * @implemented + */ +STDCALL +VOID +KeSetProfileIrql(IN KIRQL ProfileIrql) +{ + /* Set the IRQL at which Profiling will run */ + KiProfileIrql = ProfileIrql; } diff --git a/reactos/ntoskrnl/ke/timer.c b/reactos/ntoskrnl/ke/timer.c index c46db9ddcff..44f7b19b34a 100644 --- a/reactos/ntoskrnl/ke/timer.c +++ b/reactos/ntoskrnl/ke/timer.c @@ -219,7 +219,6 @@ KiExpireTimers(PKDPC Dpc, PVOID SystemArgument1, PVOID SystemArgument2) { - ULONG Eip = (ULONG)SystemArgument1; PKTIMER Timer; ULONGLONG InterruptTime; LIST_ENTRY ExpiredTimerList; @@ -267,8 +266,6 @@ KiExpireTimers(PKDPC Dpc, } DPRINT("Timers expired\n"); - /* Add a Profile Event */ - KiAddProfileEvent(ProfileTime, Eip); /* Release Dispatcher Lock */ KeReleaseDispatcherDatabaseLock(OldIrql); diff --git a/reactos/ntoskrnl/ntoskrnl.def b/reactos/ntoskrnl/ntoskrnl.def index 9444fe08006..956d20c43ae 100644 --- a/reactos/ntoskrnl/ntoskrnl.def +++ b/reactos/ntoskrnl/ntoskrnl.def @@ -152,24 +152,6 @@ ExUuidCreate@4 ExVerifySuite@4 @ExWaitForRundownProtectionRelease@4 ExWindowStationObjectType DATA -ExInitializeBinaryTree@12 -ExDeleteBinaryTree@4 -ExInsertBinaryTree@12 -ExSearchBinaryTree@12 -ExRemoveBinaryTree@12 -ExTraverseBinaryTree@16 -ExInitializeSplayTree@16 -ExDeleteSplayTree@4 -ExInsertSplayTree@12 -ExSearchSplayTree@12 -ExRemoveSplayTree@12 -ExWeightOfSplayTree@8 -ExTraverseSplayTree@16 -ExInitializeHashTable@16 -ExDeleteHashTable@4 -ExInsertHashTable@16 -ExSearchHashTable@16 -ExRemoveHashTable@16 @ExfAcquirePushLockExclusive@4 @ExfAcquirePushLockShared@4 @ExfReleasePushLock@4