* 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:
David Welch 2001-03-16 16:05:34 +00:00
parent 18f3b6c58b
commit 18015b2244
12 changed files with 594 additions and 57 deletions

View file

@ -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.

View file

@ -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,
IN ULONG ImageSize,
IN ULONG Granularity,
OUT PVOID Buffer,
IN ULONG ProfilingSize,
IN ULONG ClockSource,
IN ULONG ProcessorMask
);
NtCreateProfile(OUT PHANDLE ProfileHandle,
IN HANDLE ProcessHandle,
IN PVOID ImageBase,
IN ULONG ImageSize,
IN ULONG Granularity,
OUT PULONG Buffer,
IN ULONG ProfilingSize,
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
);

View file

@ -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 )

View file

@ -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

View file

@ -4,3 +4,4 @@ VOID NtInitializeSemaphoreImplementation(VOID);
VOID NtInitializeMutantImplementation(VOID);
VOID NtInitializeTimerImplementation(VOID);
NTSTATUS NiInitPort(VOID);
VOID NtInitializeProfileImplementation(VOID);

View file

@ -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,11 +74,10 @@ IoBuildPartialMdl(PMDL SourceMdl,
}
}
VOID
STDCALL
VOID STDCALL
IoFreeMdl(PMDL Mdl)
{
MmUnmapLockedPages(MmGetSystemAddressForMdl(Mdl),Mdl);
MmUnmapLockedPages(MmGetSystemAddressForMdl(Mdl), Mdl);
MmUnlockPages(Mdl);
ExFreePool(Mdl);
}

View file

@ -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
{

View file

@ -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");
@ -421,13 +422,15 @@ KeExpireTimers(PKDPC Dpc,
HandleExpiredTimer(current);
}
}
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);
}

View file

@ -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
@ -1346,6 +1346,13 @@ NtReadVirtualMemory(IN HANDLE ProcessHandle,
memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
KeDetachProcess();
if (Mdl->MappedSystemVa != NULL)
{
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
}
MmUnlockPages(Mdl);
ExFreePool(Mdl);
ObDereferenceObject(Process);
@ -1410,6 +1417,13 @@ NtWriteVirtualMemory(IN HANDLE ProcessHandle,
KeDetachProcess();
ObDereferenceObject(Process);
if (Mdl->MappedSystemVa != NULL)
{
MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
}
MmUnlockPages(Mdl);
ExFreePool(Mdl);
*NumberOfBytesWritten = NumberOfBytesToWrite;

View file

@ -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 */

View file

@ -132,18 +132,27 @@ NtCreateEvent(OUT PHANDLE UnsafeEventHandle,
PKEVENT Event;
HANDLE EventHandle;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
Status = MmCopyFromCaller(&ObjectAttributes, UnsafeObjectAttributes,
sizeof(OBJECT_ATTRIBUTES));
if (!NT_SUCCESS(Status))
OBJECT_ATTRIBUTES SafeObjectAttributes;
POBJECT_ATTRIBUTES ObjectAttributes;
if (UnsafeObjectAttributes != NULL)
{
return(Status);
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,

View file

@ -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,
IN ULONG ImageSize,
IN ULONG Granularity,
OUT PVOID Buffer,
IN ULONG ProfilingSize,
IN ULONG ClockSource,
IN ULONG ProcessorMask)
VOID STATIC
KiAddProfileEventToProcess(PLIST_ENTRY ListHead, PVOID Eip)
/*
* Add a profile event to the profile objects for a particular process
* or the system
*/
{
UNIMPLEMENTED;
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;
}
}
NTSTATUS STDCALL NtQueryIntervalProfile(OUT PULONG Interval,
OUT PULONG ClockSource)
VOID
KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Eip)
/*
* Add a profile event
*/
{
UNIMPLEMENTED;
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(&current->ProfileListHead, (PVOID)Eip);
break;
}
current_entry = current_entry->Flink;
}
KiAddProfileEventToProcess(&SystemProfileList, (PVOID)Eip);
KeReleaseSpinLockFromDpcLevel(&ProfileListLock);
}
NTSTATUS STDCALL NtSetIntervalProfile(IN ULONG Interval,
IN ULONG ClockSource)
VOID
KiInsertProfileIntoProcess(PLIST_ENTRY ListHead, PKPROFILE Profile)
/*
* Insert a profile object into the list for a process or the system
*/
{
UNIMPLEMENTED;
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);
}
NTSTATUS STDCALL NtStartProfile(IN HANDLE ProfileHandle)
VOID
KiInsertProfile(PKPROFILE Profile)
/*
* Insert a profile into the relevant data structures
*/
{
UNIMPLEMENTED;
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(&current->ProfileListHead, Profile);
KeReleaseSpinLock(&ProfileListLock, oldIrql);
return;
}
current_entry = current_entry->Flink;
}
current = ExAllocatePool(NonPagedPool, sizeof(KPROCESS_PROFILE));
current->Pid = (HANDLE)Pid;
InitializeListHead(&current->ProfileListHead);
InsertTailList(ListHead, &current->ListEntry);
KiInsertProfileIntoProcess(&current->ProfileListHead, Profile);
}
KeReleaseSpinLock(&ProfileListLock, oldIrql);
}
NTSTATUS STDCALL NtStopProfile(IN HANDLE ProfileHandle)
VOID KiRemoveProfile(PKPROFILE Profile)
{
UNIMPLEMENTED;
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(&current->ProfileListHead))
{
RemoveEntryList(&current->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 PULONG Buffer,
IN ULONG BufferSize,
IN KPROFILE_SOURCE Source,
IN ULONG ProcessorMask)
{
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;
}
/*
* Check the parameters
*/
if ((Process == NULL && ImageBase < (PVOID)KERNEL_BASE) ||
(Process != NULL && ImageBase >= (PVOID)KERNEL_BASE))
{
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);
}
/*
* 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))
{
ObDereferenceObject(Profile);
ZwClose(ProfileHandle);
return(Status);
}
ObDereferenceObject(Profile);
return(STATUS_SUCCESS);
}
NTSTATUS STDCALL
NtQueryIntervalProfile(OUT PULONG UnsafeInterval,
OUT KPROFILE_SOURCE Source)
{
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);
}