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 RtlpCreateUnicodeString(&ExProfileObjectType
->TypeName
, L
"Profile", NonPagedPool
);
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
;
114 PreviousMode
= ExGetPreviousMode();
118 return STATUS_INVALID_PARAMETER_7
;
121 if(PreviousMode
!= KernelMode
)
125 ProbeForWrite(ProfileHandle
,
128 ProbeForWrite(Buffer
,
134 Status
= _SEH_GetExceptionCode();
138 if(!NT_SUCCESS(Status
))
145 * Reference the associated process
149 Status
= ObReferenceObjectByHandle(Process
,
150 PROCESS_QUERY_INFORMATION
,
155 if (!NT_SUCCESS(Status
))
163 if(!SeSinglePrivilegeCheck(SeSystemProfilePrivilege
,
166 DPRINT1("NtCreateProfile: Caller requires the SeSystemProfilePrivilege privilege!\n");
167 return STATUS_PRIVILEGE_NOT_HELD
;
172 * Check the parameters
174 if ((pProcess
== NULL
&& ImageBase
< (PVOID
)KERNEL_BASE
) ||
175 (pProcess
!= NULL
&& ImageBase
>= (PVOID
)KERNEL_BASE
))
177 return(STATUS_INVALID_PARAMETER_3
);
179 if (((ImageSize
>> BucketSize
) * 4) >= BufferSize
)
181 return(STATUS_BUFFER_TOO_SMALL
);
183 if (ProfileSource
!= ProfileTime
)
185 return(STATUS_INVALID_PARAMETER_9
);
189 return(STATUS_INVALID_PARAMETER_10
);
195 InitializeObjectAttributes(&ObjectAttributes
,
201 Status
= ObCreateObject(KernelMode
,
210 if (!NT_SUCCESS(Status
))
218 Profile
->Base
= ImageBase
;
219 Profile
->Size
= ImageSize
;
220 Profile
->BucketShift
= BucketSize
;
221 Profile
->BufferMdl
= MmCreateMdl(NULL
, Buffer
, BufferSize
);
222 if(Profile
->BufferMdl
== NULL
) {
223 DPRINT("MmCreateMdl: Out of memory!");
224 ObDereferenceObject (Profile
);
225 return(STATUS_NO_MEMORY
);
227 MmProbeAndLockPages(Profile
->BufferMdl
, UserMode
, IoWriteAccess
);
228 Profile
->Buffer
= MmGetSystemAddressForMdl(Profile
->BufferMdl
);
229 Profile
->BufferSize
= BufferSize
;
230 Profile
->ProcessorMask
= Affinity
;
231 Profile
->Started
= FALSE
;
232 Profile
->Process
= pProcess
;
235 * Insert the profile into the profile list data structures
237 KiInsertProfile(Profile
);
239 Status
= ObInsertObject ((PVOID
)Profile
,
245 if (!NT_SUCCESS(Status
))
247 ObDereferenceObject (Profile
);
252 * Copy the created handle back to the caller
256 *ProfileHandle
= hProfile
;
260 Status
= _SEH_GetExceptionCode();
264 ObDereferenceObject(Profile
);
270 NtQueryIntervalProfile(IN KPROFILE_SOURCE ProfileSource
,
273 KPROCESSOR_MODE PreviousMode
;
274 NTSTATUS Status
= STATUS_SUCCESS
;
278 PreviousMode
= ExGetPreviousMode();
280 if(PreviousMode
!= KernelMode
)
284 ProbeForWrite(Interval
,
290 Status
= _SEH_GetExceptionCode();
294 if(!NT_SUCCESS(Status
))
300 if (ProfileSource
== ProfileTime
)
302 ULONG ReturnInterval
;
304 /* FIXME: What units does this use, for now nanoseconds */
305 ReturnInterval
= 100;
309 *Interval
= ReturnInterval
;
313 Status
= _SEH_GetExceptionCode();
319 return STATUS_INVALID_PARAMETER_2
;
323 NtSetIntervalProfile(IN ULONG Interval
,
324 IN KPROFILE_SOURCE Source
)
326 return(STATUS_NOT_IMPLEMENTED
);
330 NtStartProfile(IN HANDLE ProfileHandle
)
333 KPROCESSOR_MODE PreviousMode
;
338 PreviousMode
= ExGetPreviousMode();
340 Status
= ObReferenceObjectByHandle(ProfileHandle
,
346 if (!NT_SUCCESS(Status
))
350 Profile
->Started
= TRUE
;
351 ObDereferenceObject(Profile
);
352 return(STATUS_SUCCESS
);
356 NtStopProfile(IN HANDLE ProfileHandle
)
359 KPROCESSOR_MODE PreviousMode
;
364 PreviousMode
= ExGetPreviousMode();
366 Status
= ObReferenceObjectByHandle(ProfileHandle
,
372 if (!NT_SUCCESS(Status
))
376 Profile
->Started
= FALSE
;
377 ObDereferenceObject(Profile
);
378 return(STATUS_SUCCESS
);