3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/nt/profile.c
6 * PURPOSE: Support for profiling
8 * PROGRAMMERS: No programmer listed.
11 /* INCLUDES *****************************************************************/
14 #include <internal/debug.h>
16 /* TYPES ********************************************************************/
18 /* GLOBALS *******************************************************************/
20 POBJECT_TYPE EXPORTED ExProfileObjectType
= NULL
;
22 static GENERIC_MAPPING ExpProfileMapping
= {
24 STANDARD_RIGHTS_WRITE
,
25 STANDARD_RIGHTS_EXECUTE
,
29 * Size of the profile hash table.
31 #define PROFILE_HASH_TABLE_SIZE (32)
34 * Table of lists of per-process profiling data structures hashed by PID.
36 LIST_ENTRY ProcessProfileListHashTable
[PROFILE_HASH_TABLE_SIZE
];
39 * Head of the list of profile data structures for the kernel.
41 LIST_ENTRY SystemProfileList
;
44 * Lock that protects the profiling data structures.
46 KSPIN_LOCK ProfileListLock
;
49 * Timer interrupts happen before we have initialized the profiling
50 * data structures so just ignore them before that.
52 BOOLEAN ProfileInitDone
= FALSE
;
55 ExpInitializeProfileImplementation(VOID
)
59 InitializeListHead(&SystemProfileList
);
61 for (i
= 0; i
< PROFILE_HASH_TABLE_SIZE
; i
++)
63 InitializeListHead(&ProcessProfileListHashTable
[i
]);
66 KeInitializeSpinLock(&ProfileListLock
);
67 ProfileInitDone
= TRUE
;
69 ExProfileObjectType
= ExAllocatePool(NonPagedPool
,sizeof(OBJECT_TYPE
));
71 RtlCreateUnicodeString(&ExProfileObjectType
->TypeName
, L
"Profile");
73 ExProfileObjectType
->Tag
= TAG('P', 'R', 'O', 'F');
74 ExProfileObjectType
->PeakObjects
= 0;
75 ExProfileObjectType
->PeakHandles
= 0;
76 ExProfileObjectType
->TotalObjects
= 0;
77 ExProfileObjectType
->TotalHandles
= 0;
78 ExProfileObjectType
->PagedPoolCharge
= 0;
79 ExProfileObjectType
->NonpagedPoolCharge
= sizeof(KPROFILE
);
80 ExProfileObjectType
->Mapping
= &ExpProfileMapping
;
81 ExProfileObjectType
->Dump
= NULL
;
82 ExProfileObjectType
->Open
= NULL
;
83 ExProfileObjectType
->Close
= NULL
;
84 ExProfileObjectType
->Delete
= KiDeleteProfile
;
85 ExProfileObjectType
->Parse
= NULL
;
86 ExProfileObjectType
->Security
= NULL
;
87 ExProfileObjectType
->QueryName
= NULL
;
88 ExProfileObjectType
->OkayToClose
= NULL
;
89 ExProfileObjectType
->Create
= NULL
;
91 ObpCreateTypeObject(ExProfileObjectType
);
95 NtCreateProfile(OUT PHANDLE ProfileHandle
,
96 IN HANDLE Process OPTIONAL
,
102 IN KPROFILE_SOURCE ProfileSource
,
103 IN KAFFINITY Affinity
)
108 KPROCESSOR_MODE PreviousMode
;
109 OBJECT_ATTRIBUTES ObjectAttributes
;
110 NTSTATUS Status
= STATUS_SUCCESS
;
112 PreviousMode
= ExGetPreviousMode();
116 return STATUS_INVALID_PARAMETER_7
;
119 if(PreviousMode
!= KernelMode
)
123 ProbeForWrite(ProfileHandle
,
126 ProbeForWrite(Buffer
,
132 Status
= _SEH_GetExceptionCode();
136 if(!NT_SUCCESS(Status
))
143 * Reference the associated process
147 Status
= ObReferenceObjectByHandle(Process
,
148 PROCESS_QUERY_INFORMATION
,
153 if (!NT_SUCCESS(Status
))
161 if(!SeSinglePrivilegeCheck(SeSystemProfilePrivilege
,
164 DPRINT1("NtCreateProfile: Caller requires the SeSystemProfilePrivilege privilege!\n");
165 return STATUS_PRIVILEGE_NOT_HELD
;
170 * Check the parameters
172 if ((pProcess
== NULL
&& ImageBase
< (PVOID
)KERNEL_BASE
) ||
173 (pProcess
!= NULL
&& ImageBase
>= (PVOID
)KERNEL_BASE
))
175 return(STATUS_INVALID_PARAMETER_3
);
177 if (((ImageSize
>> BucketSize
) * 4) >= BufferSize
)
179 return(STATUS_BUFFER_TOO_SMALL
);
181 if (ProfileSource
!= ProfileTime
)
183 return(STATUS_INVALID_PARAMETER_9
);
187 return(STATUS_INVALID_PARAMETER_10
);
193 InitializeObjectAttributes(&ObjectAttributes
,
199 Status
= ObCreateObject(KernelMode
,
208 if (!NT_SUCCESS(Status
))
216 Profile
->Base
= ImageBase
;
217 Profile
->Size
= ImageSize
;
218 Profile
->BucketShift
= BucketSize
;
219 Profile
->BufferMdl
= MmCreateMdl(NULL
, Buffer
, BufferSize
);
220 if(Profile
->BufferMdl
== NULL
) {
221 DPRINT("MmCreateMdl: Out of memory!");
222 ObDereferenceObject (Profile
);
223 return(STATUS_NO_MEMORY
);
225 MmProbeAndLockPages(Profile
->BufferMdl
, UserMode
, IoWriteAccess
);
226 Profile
->Buffer
= MmGetSystemAddressForMdl(Profile
->BufferMdl
);
227 Profile
->BufferSize
= BufferSize
;
228 Profile
->ProcessorMask
= Affinity
;
229 Profile
->Started
= FALSE
;
230 Profile
->Process
= pProcess
;
233 * Insert the profile into the profile list data structures
235 KiInsertProfile(Profile
);
237 Status
= ObInsertObject ((PVOID
)Profile
,
243 if (!NT_SUCCESS(Status
))
245 ObDereferenceObject (Profile
);
250 * Copy the created handle back to the caller
254 *ProfileHandle
= hProfile
;
258 Status
= _SEH_GetExceptionCode();
262 ObDereferenceObject(Profile
);
268 NtQueryIntervalProfile(IN KPROFILE_SOURCE ProfileSource
,
271 KPROCESSOR_MODE PreviousMode
;
272 NTSTATUS Status
= STATUS_SUCCESS
;
274 PreviousMode
= ExGetPreviousMode();
276 if(PreviousMode
!= KernelMode
)
280 ProbeForWrite(Interval
,
286 Status
= _SEH_GetExceptionCode();
290 if(!NT_SUCCESS(Status
))
296 if (ProfileSource
== ProfileTime
)
298 ULONG ReturnInterval
;
300 /* FIXME: What units does this use, for now nanoseconds */
301 ReturnInterval
= 100;
305 *Interval
= ReturnInterval
;
309 Status
= _SEH_GetExceptionCode();
315 return STATUS_INVALID_PARAMETER_2
;
319 NtSetIntervalProfile(IN ULONG Interval
,
320 IN KPROFILE_SOURCE Source
)
322 return(STATUS_NOT_IMPLEMENTED
);
326 NtStartProfile(IN HANDLE ProfileHandle
)
329 KPROCESSOR_MODE PreviousMode
;
332 PreviousMode
= ExGetPreviousMode();
334 Status
= ObReferenceObjectByHandle(ProfileHandle
,
340 if (!NT_SUCCESS(Status
))
344 Profile
->Started
= TRUE
;
345 ObDereferenceObject(Profile
);
346 return(STATUS_SUCCESS
);
350 NtStopProfile(IN HANDLE ProfileHandle
)
353 KPROCESSOR_MODE PreviousMode
;
356 PreviousMode
= ExGetPreviousMode();
358 Status
= ObReferenceObjectByHandle(ProfileHandle
,
364 if (!NT_SUCCESS(Status
))
368 Profile
->Started
= FALSE
;
369 ObDereferenceObject(Profile
);
370 return(STATUS_SUCCESS
);