mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
* include/ddk/zw.h: Corrected declarations of NtCreateProfile,
NtQueryIntervalProfile, NtSetIntervalProfile. * include/ddk/zwtypes.h: Added definitions of KPROFILE_SOURCE. * ntoskrnl/include/internal/ke.h: Added the interrupted EIP as a parameter to KiUpdateSystemTime for profiling purposes. * ntoskrnl/include/internal/nt: Added declaration for profiling support initialization. * ntoskrnl/ke/timer.c (KiUpdateSystemTime, KeExpireTimers): Call the profiling code on a timer interrupt with the interrupt EIP. * ntoskrnl/ke/i386/irq.c (KiDispatchInterrupt): Pass the interrupted EIP to KiUpdateSystemTime. * ntoskrnl/mm/virtual.c (NtReadVirtualMemory, NtWriteVirtualMemory): Release the MDLs used properly. * ntoskrnl/nt/nt.c: Call the profiling support initialization. * ntoskrnl/nt/ntevent.c (NtCreateEvent): Don't try copying the ObjectAttributes parameter if it is NULL. * ntoskrnl/nt/profile.c: Implemented profiling. svn path=/trunk/; revision=1701
This commit is contained in:
parent
18f3b6c58b
commit
18015b2244
12 changed files with 594 additions and 57 deletions
|
@ -1,3 +1,23 @@
|
|||
2001-03-16 David Welch <welch@cwcom.net>
|
||||
|
||||
* include/ddk/zw.h: Corrected declarations of NtCreateProfile,
|
||||
NtQueryIntervalProfile, NtSetIntervalProfile.
|
||||
* include/ddk/zwtypes.h: Added definitions of KPROFILE_SOURCE.
|
||||
* ntoskrnl/include/internal/ke.h: Added the interrupted EIP as a
|
||||
parameter to KiUpdateSystemTime for profiling purposes.
|
||||
* ntoskrnl/include/internal/nt: Added declaration for profiling
|
||||
support initialization.
|
||||
* ntoskrnl/ke/timer.c (KiUpdateSystemTime, KeExpireTimers): Call
|
||||
the profiling code on a timer interrupt with the interrupt EIP.
|
||||
* ntoskrnl/ke/i386/irq.c (KiDispatchInterrupt): Pass the interrupted
|
||||
EIP to KiUpdateSystemTime.
|
||||
* ntoskrnl/mm/virtual.c (NtReadVirtualMemory, NtWriteVirtualMemory):
|
||||
Release the MDLs used properly.
|
||||
* ntoskrnl/nt/nt.c: Call the profiling support initialization.
|
||||
* ntoskrnl/nt/ntevent.c (NtCreateEvent): Don't try copying the
|
||||
ObjectAttributes parameter if it is NULL.
|
||||
* ntoskrnl/nt/profile.c: Implemented profiling.
|
||||
|
||||
2001-03-16 David Welch <welch@cwcom.net>
|
||||
|
||||
* ntoskrnl/include/internal/safe.h: Corrected typo.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
/* $Id: zw.h,v 1.40 2001/01/02 00:46:10 ekohl Exp $
|
||||
/* $Id: zw.h,v 1.41 2001/03/16 16:05:32 dwelch Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -816,17 +816,15 @@ ZwCreateProcess(
|
|||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtCreateProfile(
|
||||
OUT PHANDLE ProfileHandle,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
IN ULONG ImageBase,
|
||||
NtCreateProfile(OUT PHANDLE ProfileHandle,
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PVOID ImageBase,
|
||||
IN ULONG ImageSize,
|
||||
IN ULONG Granularity,
|
||||
OUT PVOID Buffer,
|
||||
OUT PULONG Buffer,
|
||||
IN ULONG ProfilingSize,
|
||||
IN ULONG ClockSource,
|
||||
IN ULONG ProcessorMask
|
||||
);
|
||||
IN KPROFILE_SOURCE Source,
|
||||
IN ULONG ProcessorMask);
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
|
@ -3031,14 +3029,14 @@ NTSTATUS
|
|||
STDCALL
|
||||
NtQueryIntervalProfile(
|
||||
OUT PULONG Interval,
|
||||
OUT PULONG ClockSource
|
||||
OUT KPROFILE_SOURCE ClockSource
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
ZwQueryIntervalProfile(
|
||||
OUT PULONG Interval,
|
||||
OUT PULONG ClockSource
|
||||
OUT KPROFILE_SOURCE ClockSource
|
||||
);
|
||||
|
||||
|
||||
|
@ -4396,14 +4394,14 @@ NTSTATUS
|
|||
STDCALL
|
||||
NtSetIntervalProfile(
|
||||
ULONG Interval,
|
||||
ULONG ClockSource
|
||||
KPROFILE_SOURCE ClockSource
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
ZwSetIntervalProfile(
|
||||
ULONG Interval,
|
||||
ULONG ClockSource
|
||||
KPROFILE_SOURCE ClockSource
|
||||
);
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
#ifndef __INCLUDE_DDK_ZWTYPES_H
|
||||
#define __INCLUDE_DDK_ZWTYPES_H
|
||||
|
||||
typedef enum _KPROFILE_SOURCE
|
||||
{
|
||||
ProfileTime
|
||||
} KPROFILE_SOURCE;
|
||||
|
||||
#define NtCurrentProcess() ( (HANDLE) 0xFFFFFFFF )
|
||||
#define NtCurrentThread() ( (HANDLE) 0xFFFFFFFE )
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ typedef struct _KTRAP_FRAME
|
|||
USHORT Reserved9;
|
||||
} KTRAP_FRAME, *PKTRAP_FRAME;
|
||||
|
||||
VOID KiUpdateSystemTime (KIRQL oldIrql);
|
||||
VOID KiUpdateSystemTime (KIRQL oldIrql, ULONG Eip);
|
||||
|
||||
VOID KeAcquireDispatcherDatabaseLock(BOOLEAN Wait);
|
||||
VOID KeReleaseDispatcherDatabaseLock(BOOLEAN Wait);
|
||||
|
@ -127,5 +127,7 @@ VOID KeInit2(VOID);
|
|||
BOOLEAN KiDeliverUserApc(PKTRAP_FRAME TrapFrame);
|
||||
VOID
|
||||
NtEarlyInitVdm(VOID);
|
||||
VOID
|
||||
KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Eip);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,3 +4,4 @@ VOID NtInitializeSemaphoreImplementation(VOID);
|
|||
VOID NtInitializeMutantImplementation(VOID);
|
||||
VOID NtInitializeTimerImplementation(VOID);
|
||||
NTSTATUS NiInitPort(VOID);
|
||||
VOID NtInitializeProfileImplementation(VOID);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: mdl.c,v 1.6 2001/03/07 16:48:42 dwelch Exp $
|
||||
/* $Id: mdl.c,v 1.7 2001/03/16 16:05:33 dwelch Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -74,8 +74,7 @@ IoBuildPartialMdl(PMDL SourceMdl,
|
|||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
VOID STDCALL
|
||||
IoFreeMdl(PMDL Mdl)
|
||||
{
|
||||
MmUnmapLockedPages(MmGetSystemAddressForMdl(Mdl), Mdl);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: irq.c,v 1.7 2001/03/14 23:19:14 dwelch Exp $
|
||||
/* $Id: irq.c,v 1.8 2001/03/16 16:05:34 dwelch Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -154,7 +154,7 @@ KiInterruptDispatch (ULONG irq, PKIRQ_TRAPFRAME Trapframe)
|
|||
|
||||
if (irq==0)
|
||||
{
|
||||
KiUpdateSystemTime(old_level);
|
||||
KiUpdateSystemTime(old_level, Trapframe->Eip);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: timer.c,v 1.41 2001/03/14 23:19:14 dwelch Exp $
|
||||
/* $Id: timer.c,v 1.42 2001/03/16 16:05:33 dwelch Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -403,6 +403,7 @@ KeExpireTimers(PKDPC Dpc,
|
|||
{
|
||||
PLIST_ENTRY current_entry = NULL;
|
||||
PKTIMER current = NULL;
|
||||
ULONG Eip = (ULONG)Arg1;
|
||||
|
||||
DPRINT("KeExpireTimers()\n");
|
||||
|
||||
|
@ -422,12 +423,14 @@ KeExpireTimers(PKDPC Dpc,
|
|||
}
|
||||
}
|
||||
|
||||
KiAddProfileEvent(ProfileTime, Eip);
|
||||
|
||||
KeReleaseSpinLockFromDpcLevel(&TimerListLock);
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
KiUpdateSystemTime (KIRQL oldIrql)
|
||||
KiUpdateSystemTime (KIRQL oldIrql, ULONG Eip)
|
||||
/*
|
||||
* FUNCTION: Handles a timer interrupt
|
||||
*/
|
||||
|
@ -463,7 +466,7 @@ KiUpdateSystemTime (KIRQL oldIrql)
|
|||
/*
|
||||
* Queue a DPC that will expire timers
|
||||
*/
|
||||
KeInsertQueueDpc(&ExpireTimerDpc, 0, 0);
|
||||
KeInsertQueueDpc(&ExpireTimerDpc, (PVOID)Eip, 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: virtual.c,v 1.42 2001/03/13 16:25:54 dwelch Exp $
|
||||
/* $Id: virtual.c,v 1.43 2001/03/16 16:05:34 dwelch Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -1347,6 +1347,13 @@ NtReadVirtualMemory(IN HANDLE ProcessHandle,
|
|||
|
||||
KeDetachProcess();
|
||||
|
||||
if (Mdl->MappedSystemVa != NULL)
|
||||
{
|
||||
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
|
||||
}
|
||||
MmUnlockPages(Mdl);
|
||||
ExFreePool(Mdl);
|
||||
|
||||
ObDereferenceObject(Process);
|
||||
|
||||
*NumberOfBytesRead = NumberOfBytesToRead;
|
||||
|
@ -1411,6 +1418,13 @@ NtWriteVirtualMemory(IN HANDLE ProcessHandle,
|
|||
|
||||
ObDereferenceObject(Process);
|
||||
|
||||
if (Mdl->MappedSystemVa != NULL)
|
||||
{
|
||||
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
|
||||
}
|
||||
MmUnlockPages(Mdl);
|
||||
ExFreePool(Mdl);
|
||||
|
||||
*NumberOfBytesWritten = NumberOfBytesToWrite;
|
||||
|
||||
DPRINT("Finished NtWriteVirtualMemory()\n");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: nt.c,v 1.6 2001/02/04 17:28:13 ekohl Exp $
|
||||
/* $Id: nt.c,v 1.7 2001/03/16 16:05:34 dwelch Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -25,6 +25,7 @@ VOID NtInit(VOID)
|
|||
NtInitializeSemaphoreImplementation();
|
||||
NtInitializeTimerImplementation();
|
||||
NiInitPort();
|
||||
NtInitializeProfileImplementation();
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -132,18 +132,27 @@ NtCreateEvent(OUT PHANDLE UnsafeEventHandle,
|
|||
PKEVENT Event;
|
||||
HANDLE EventHandle;
|
||||
NTSTATUS Status;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
OBJECT_ATTRIBUTES SafeObjectAttributes;
|
||||
POBJECT_ATTRIBUTES ObjectAttributes;
|
||||
|
||||
Status = MmCopyFromCaller(&ObjectAttributes, UnsafeObjectAttributes,
|
||||
if (UnsafeObjectAttributes != NULL)
|
||||
{
|
||||
Status = MmCopyFromCaller(&SafeObjectAttributes, UnsafeObjectAttributes,
|
||||
sizeof(OBJECT_ATTRIBUTES));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
ObjectAttributes = &SafeObjectAttributes;
|
||||
}
|
||||
else
|
||||
{
|
||||
ObjectAttributes = NULL;
|
||||
}
|
||||
|
||||
Event = ObCreateObject(&EventHandle,
|
||||
DesiredAccess,
|
||||
&ObjectAttributes,
|
||||
ObjectAttributes,
|
||||
ExEventObjectType);
|
||||
KeInitializeEvent(Event,
|
||||
ManualReset ? NotificationEvent : SynchronizationEvent,
|
||||
|
|
|
@ -1,7 +1,24 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/nt/Profile.c
|
||||
* FILE: ntoskrnl/nt/profile.c
|
||||
* PURPOSE: Support for profiling
|
||||
* PROGRAMMER: Nobody
|
||||
* UPDATE HISTORY:
|
||||
|
@ -11,42 +28,510 @@
|
|||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <internal/mm.h>
|
||||
#include <internal/ps.h>
|
||||
#include <internal/pool.h>
|
||||
#include <limits.h>
|
||||
#include <internal/safe.h>
|
||||
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* TYPES ********************************************************************/
|
||||
|
||||
typedef struct _KPROCESS_PROFILE
|
||||
{
|
||||
LIST_ENTRY ProfileListHead;
|
||||
LIST_ENTRY ListEntry;
|
||||
HANDLE Pid;
|
||||
} KPROCESS_PROFILE, *PKPROCESS_PROFILE;
|
||||
|
||||
typedef struct _KPROFILE
|
||||
{
|
||||
CSHORT Type;
|
||||
CSHORT Name;
|
||||
LIST_ENTRY ListEntry;
|
||||
PVOID Base;
|
||||
ULONG Size;
|
||||
ULONG BucketShift;
|
||||
PMDL BufferMdl;
|
||||
PULONG Buffer;
|
||||
ULONG BufferSize;
|
||||
ULONG ProcessorMask;
|
||||
BOOLEAN Started;
|
||||
PEPROCESS Process;
|
||||
} KPROFILE, *PKPROFILE;
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
POBJECT_TYPE EXPORTED ExProfileObjectType = NULL;
|
||||
|
||||
static GENERIC_MAPPING ExpProfileMapping = {
|
||||
STANDARD_RIGHTS_READ,
|
||||
STANDARD_RIGHTS_WRITE,
|
||||
STANDARD_RIGHTS_EXECUTE,
|
||||
STANDARD_RIGHTS_ALL};
|
||||
|
||||
/*
|
||||
* Size of the profile hash table
|
||||
*/
|
||||
#define PROFILE_HASH_TABLE_SIZE (32)
|
||||
|
||||
/*
|
||||
* Table of lists of per-process profiling data structures hashed by PID.
|
||||
*/
|
||||
static LIST_ENTRY ProcessProfileListHashTable[PROFILE_HASH_TABLE_SIZE];
|
||||
|
||||
/*
|
||||
* Head of the list of profile data structures for the kernel
|
||||
*/
|
||||
static LIST_ENTRY SystemProfileList;
|
||||
|
||||
/*
|
||||
* Lock that protects the profiling data structures
|
||||
*/
|
||||
static KSPIN_LOCK ProfileListLock;
|
||||
|
||||
static BOOLEAN ProfileInitDone = FALSE;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS STDCALL NtCreateProfile(OUT PHANDLE ProfileHandle,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
IN ULONG ImageBase,
|
||||
VOID STATIC
|
||||
KiAddProfileEventToProcess(PLIST_ENTRY ListHead, PVOID Eip)
|
||||
/*
|
||||
* Add a profile event to the profile objects for a particular process
|
||||
* or the system
|
||||
*/
|
||||
{
|
||||
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 && (current->Base + current->Size) > Eip &&
|
||||
current->Started)
|
||||
{
|
||||
ULONG Bucket;
|
||||
|
||||
Bucket = ((ULONG)(Eip - 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
|
||||
{
|
||||
ULONG Pid;
|
||||
PKPROCESS_PROFILE current;
|
||||
PLIST_ENTRY current_entry;
|
||||
PLIST_ENTRY ListHead;
|
||||
|
||||
Pid = Profile->Process->UniqueProcessId;
|
||||
ListHead = &ProcessProfileListHashTable[Pid % PROFILE_HASH_TABLE_SIZE];
|
||||
|
||||
current_entry = ListHead;
|
||||
while(current_entry != ListHead)
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE,
|
||||
ListEntry);
|
||||
|
||||
if (current->Pid == (HANDLE)Pid)
|
||||
{
|
||||
KiInsertProfileIntoProcess(¤t->ProfileListHead, Profile);
|
||||
KeReleaseSpinLock(&ProfileListLock, oldIrql);
|
||||
return;
|
||||
}
|
||||
|
||||
current_entry = current_entry->Flink;
|
||||
}
|
||||
|
||||
current = ExAllocatePool(NonPagedPool, sizeof(KPROCESS_PROFILE));
|
||||
|
||||
current->Pid = (HANDLE)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
|
||||
{
|
||||
ULONG Pid;
|
||||
PLIST_ENTRY ListHead;
|
||||
PKPROCESS_PROFILE current;
|
||||
PLIST_ENTRY current_entry;
|
||||
|
||||
RemoveEntryList(&Profile->ListEntry);
|
||||
|
||||
Pid = Profile->Process->UniqueProcessId;
|
||||
ListHead = &ProcessProfileListHashTable[Pid % PROFILE_HASH_TABLE_SIZE];
|
||||
|
||||
current_entry = ListHead;
|
||||
while(current_entry != ListHead)
|
||||
{
|
||||
current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE,
|
||||
ListEntry);
|
||||
|
||||
if (current->Pid == (HANDLE)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
|
||||
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;
|
||||
}
|
||||
|
||||
VOID
|
||||
NtInitializeProfileImplementation(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));
|
||||
|
||||
RtlCreateUnicodeString(&ExProfileObjectType->TypeName, L"Profile");
|
||||
|
||||
ExProfileObjectType->Tag = TAG('P', 'R', 'O', 'F');
|
||||
ExProfileObjectType->MaxObjects = ULONG_MAX;
|
||||
ExProfileObjectType->MaxHandles = ULONG_MAX;
|
||||
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;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtCreateProfile(OUT PHANDLE UnsafeProfileHandle,
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PVOID ImageBase,
|
||||
IN ULONG ImageSize,
|
||||
IN ULONG Granularity,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG ProfilingSize,
|
||||
IN ULONG ClockSource,
|
||||
OUT PULONG Buffer,
|
||||
IN ULONG BufferSize,
|
||||
IN KPROFILE_SOURCE Source,
|
||||
IN ULONG ProcessorMask)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
HANDLE ProfileHandle;
|
||||
NTSTATUS Status;
|
||||
PKPROFILE Profile;
|
||||
PEPROCESS Process;
|
||||
|
||||
/*
|
||||
* Reference the associated process
|
||||
*/
|
||||
if (ProcessHandle != NULL)
|
||||
{
|
||||
Status = ObReferenceObjectByHandle(ProcessHandle,
|
||||
PROCESS_QUERY_INFORMATION,
|
||||
PsProcessType,
|
||||
UserMode,
|
||||
(PVOID*)&Process,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Process = NULL;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL NtQueryIntervalProfile(OUT PULONG Interval,
|
||||
OUT PULONG ClockSource)
|
||||
/*
|
||||
* Check the parameters
|
||||
*/
|
||||
if ((Process == NULL && ImageBase < (PVOID)KERNEL_BASE) ||
|
||||
(Process != NULL && ImageBase >= (PVOID)KERNEL_BASE))
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return(STATUS_INVALID_PARAMETER_3);
|
||||
}
|
||||
if (((ImageSize >> Granularity) * 4) >= BufferSize)
|
||||
{
|
||||
return(STATUS_BUFFER_TOO_SMALL);
|
||||
}
|
||||
if (Source != ProfileTime)
|
||||
{
|
||||
return(STATUS_INVALID_PARAMETER_9);
|
||||
}
|
||||
if (ProcessorMask != 0)
|
||||
{
|
||||
return(STATUS_INVALID_PARAMETER_10);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL NtSetIntervalProfile(IN ULONG Interval,
|
||||
IN ULONG ClockSource)
|
||||
/*
|
||||
* Create the object
|
||||
*/
|
||||
Profile = ObCreateObject(&ProfileHandle,
|
||||
STANDARD_RIGHTS_ALL,
|
||||
NULL,
|
||||
ExProfileObjectType);
|
||||
|
||||
/*
|
||||
* Initialize it
|
||||
*/
|
||||
Profile->Base = ImageBase;
|
||||
Profile->Size = ImageSize;
|
||||
Profile->BucketShift = Granularity;
|
||||
Profile->BufferMdl = MmCreateMdl(NULL, Buffer, BufferSize);
|
||||
MmProbeAndLockPages(Profile->BufferMdl, UserMode, IoWriteAccess);
|
||||
Profile->Buffer = MmGetSystemAddressForMdl(Profile->BufferMdl);
|
||||
Profile->BufferSize = BufferSize;
|
||||
Profile->ProcessorMask = ProcessorMask;
|
||||
Profile->Started = FALSE;
|
||||
Profile->Process = Process;
|
||||
|
||||
/*
|
||||
* Insert the profile into the profile list data structures
|
||||
*/
|
||||
KiInsertProfile(Profile);
|
||||
|
||||
/*
|
||||
* Copy the created handle back to the caller
|
||||
*/
|
||||
Status = MmCopyToCaller(UnsafeProfileHandle, &ProfileHandle, sizeof(HANDLE));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
ObDereferenceObject(Profile);
|
||||
ZwClose(ProfileHandle);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL NtStartProfile(IN HANDLE ProfileHandle)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
ObDereferenceObject(Profile);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL NtStopProfile(IN HANDLE ProfileHandle)
|
||||
NTSTATUS STDCALL
|
||||
NtQueryIntervalProfile(OUT PULONG UnsafeInterval,
|
||||
OUT KPROFILE_SOURCE Source)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
NTSTATUS Status;
|
||||
|
||||
if (Source == ProfileTime)
|
||||
{
|
||||
ULONG Interval;
|
||||
|
||||
/* FIXME: What units does this use, for now nanoseconds */
|
||||
Interval = 100;
|
||||
Status = MmCopyToCaller(UnsafeInterval, &Interval, sizeof(ULONG));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
return(STATUS_INVALID_PARAMETER_2);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtSetIntervalProfile(IN ULONG Interval,
|
||||
IN KPROFILE_SOURCE Source)
|
||||
{
|
||||
return(STATUS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtStartProfile(IN HANDLE ProfileHandle)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PKPROFILE Profile;
|
||||
|
||||
Status = ObReferenceObjectByHandle(ProfileHandle,
|
||||
STANDARD_RIGHTS_ALL,
|
||||
ExProfileObjectType,
|
||||
UserMode,
|
||||
(PVOID*)&Profile,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
Profile->Started = TRUE;
|
||||
ObDereferenceObject(Profile);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NtStopProfile(IN HANDLE ProfileHandle)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PKPROFILE Profile;
|
||||
|
||||
Status = ObReferenceObjectByHandle(ProfileHandle,
|
||||
STANDARD_RIGHTS_ALL,
|
||||
ExProfileObjectType,
|
||||
UserMode,
|
||||
(PVOID*)&Profile,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
Profile->Started = FALSE;
|
||||
ObDereferenceObject(Profile);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue