ReactOS 0.4.16-dev-106-g10b08aa
profobj.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/ke/profobj.c
5 * PURPOSE: Kernel Profiling
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 */
8
9/* INCLUDES *****************************************************************/
10
11#include <ntoskrnl.h>
12#define NDEBUG
13#include <debug.h>
14
15/* GLOBALS *******************************************************************/
16
21ULONG KiProfileTimeInterval = 78125; /* Default resolution 7.8ms (sysinternals) */
23
24/* FUNCTIONS *****************************************************************/
25
26VOID
30 PVOID ImageBase,
31 SIZE_T ImageSize,
32 ULONG BucketSize,
33 KPROFILE_SOURCE ProfileSource,
35{
36 /* Initialize the Header */
37 Profile->Type = ProfileObject;
38 Profile->Size = sizeof(KPROFILE);
39
40 /* Copy all the settings we were given */
41 Profile->Process = Process;
42 Profile->RangeBase = ImageBase;
43 Profile->BucketShift = BucketSize - 2; /* See ntinternals.net -- Alex */
44 Profile->RangeLimit = (PVOID)((ULONG_PTR)ImageBase + ImageSize);
45 Profile->Started = FALSE;
46 Profile->Source = ProfileSource;
47 Profile->Affinity = Affinity;
48}
49
54{
56 PKPROFILE_SOURCE_OBJECT SourceBuffer;
57 PKPROFILE_SOURCE_OBJECT CurrentSource;
58 BOOLEAN FreeBuffer = TRUE, SourceFound = FALSE, StartedProfile;
59 PKPROCESS ProfileProcess;
60 PLIST_ENTRY NextEntry;
61
62 /* Allocate a buffer first, before we raise IRQL */
65 'forP');
66 if (!SourceBuffer) return FALSE;
67 RtlZeroMemory(SourceBuffer, sizeof(KPROFILE_SOURCE_OBJECT));
68
69 /* Raise to profile IRQL and acquire the profile lock */
72
73 /* Make sure it's not running */
74 if (!Profile->Started)
75 {
76 /* Set it as Started */
77 Profile->Buffer = Buffer;
78 Profile->Started = TRUE;
79 StartedProfile = TRUE;
80
81 /* Get the process, if any */
82 ProfileProcess = Profile->Process;
83
84 /* Check where we should insert it */
85 if (ProfileProcess)
86 {
87 /* Insert it into the Process List */
88 InsertTailList(&ProfileProcess->ProfileListHead, &Profile->ProfileListEntry);
89 }
90 else
91 {
92 /* Insert it into the Global List */
93 InsertTailList(&KiProfileListHead, &Profile->ProfileListEntry);
94 }
95
96 /* Start looping */
97 for (NextEntry = KiProfileSourceListHead.Flink;
98 NextEntry != &KiProfileSourceListHead;
99 NextEntry = NextEntry->Flink)
100 {
101 /* Get the entry */
102 CurrentSource = CONTAINING_RECORD(NextEntry,
104 ListEntry);
105
106 /* Check if it's the same as the one being requested now */
107 if (CurrentSource->Source == Profile->Source)
108 {
109 /* It is, break out */
110 SourceFound = TRUE;
111 break;
112 }
113 }
114
115 /* See if the loop found something */
116 if (!SourceFound)
117 {
118 /* Nothing found, use our allocated buffer */
119 CurrentSource = SourceBuffer;
120
121 /* Set up the Source Object */
122 CurrentSource->Source = Profile->Source;
124
125 /* Don't free the pool later on */
126 FreeBuffer = FALSE;
127 }
128 }
129 else
130 {
131 /* Already running so nothing to start */
132 StartedProfile = FALSE;
133 }
134
135 /* Release the profile lock */
137
138 /* Tell HAL to start the profile interrupt */
139 HalStartProfileInterrupt(Profile->Source);
140
141 /* Lower back to original IRQL */
143
144 /* Free the pool */
145 if (FreeBuffer) ExFreePoolWithTag(SourceBuffer, 'forP');
146
147 /* Return whether we could start the profile */
148 return StartedProfile;
149}
150
152NTAPI
154{
156 PKPROFILE_SOURCE_OBJECT CurrentSource = NULL;
157 PLIST_ENTRY NextEntry;
158 BOOLEAN SourceFound = FALSE, StoppedProfile;
159
160 /* Raise to profile IRQL and acquire the profile lock */
163
164 /* Make sure it's running */
165 if (Profile->Started)
166 {
167 /* Remove it from the list and disable */
168 RemoveEntryList(&Profile->ProfileListEntry);
169 Profile->Started = FALSE;
170 StoppedProfile = TRUE;
171
172 /* Start looping */
173 for (NextEntry = KiProfileSourceListHead.Flink;
174 NextEntry != &KiProfileSourceListHead;
175 NextEntry = NextEntry->Flink)
176 {
177 /* Get the entry */
178 CurrentSource = CONTAINING_RECORD(NextEntry,
180 ListEntry);
181
182 /* Check if this is the Source Object */
183 if (CurrentSource->Source == Profile->Source)
184 {
185 /* Remember we found one */
186 SourceFound = TRUE;
187
188 /* Remove it and break out */
189 RemoveEntryList(&CurrentSource->ListEntry);
190 break;
191 }
192 }
193
194 }
195 else
196 {
197 /* It wasn't! */
198 StoppedProfile = FALSE;
199 }
200
201 /* Release the profile lock */
203
204 /* Stop the profile interrupt */
205 HalStopProfileInterrupt(Profile->Source);
206
207 /* Lower back to original IRQL */
209
210 /* Free the Source Object */
211 if (SourceFound) ExFreePool(CurrentSource);
212
213 /* Return whether we could stop the profile */
214 return StoppedProfile;
215}
216
217ULONG
218NTAPI
220{
221 HAL_PROFILE_SOURCE_INFORMATION ProfileSourceInformation;
224
225 /* Check what profile this is */
226 if (ProfileSource == ProfileTime)
227 {
228 /* Return the time interval */
230 }
231 else if (ProfileSource == ProfileAlignmentFixup)
232 {
233 /* Return the alignment interval */
235 }
236 else
237 {
238 /* Request it from HAL */
239 ProfileSourceInformation.Source = ProfileSource;
242 &ProfileSourceInformation,
243 &ReturnLength);
244
245 /* Check if HAL handled it and supports this profile */
246 if (NT_SUCCESS(Status) && (ProfileSourceInformation.Supported))
247 {
248 /* Get the interval */
249 Interval = ProfileSourceInformation.Interval;
250 }
251 else
252 {
253 /* Unsupported or invalid source, fail */
254 Interval = 0;
255 }
256 }
257
258 /* Return the interval we got */
259 return Interval;
260}
261
262VOID
263NTAPI
265 IN KPROFILE_SOURCE ProfileSource)
266{
267 HAL_PROFILE_SOURCE_INTERVAL ProfileSourceInterval;
268
269 /* Check what profile this is */
270 if (ProfileSource == ProfileTime)
271 {
272 /* Set the interval through HAL */
274 }
275 else if (ProfileSource == ProfileAlignmentFixup)
276 {
277 /* Set the alignment interval */
279 }
280 else
281 {
282 /* HAL handles any other interval */
283 ProfileSourceInterval.Source = ProfileSource;
284 ProfileSourceInterval.Interval = Interval;
287 &ProfileSourceInterval);
288 }
289}
290
291/*
292 * @implemented
293 */
294VOID
295NTAPI
297{
298 /* Called from HAL for Timer Profiling */
300}
301
302VOID
303NTAPI
306 IN PLIST_ENTRY ListHead)
307{
308 PULONG BucketValue;
309 PKPROFILE Profile;
310 PLIST_ENTRY NextEntry;
311 ULONG_PTR ProgramCounter;
312
313 /* Get the Program Counter */
314 ProgramCounter = KeGetTrapFramePc(TrapFrame);
315
316 /* Loop the List */
317 for (NextEntry = ListHead->Flink;
318 NextEntry != ListHead;
319 NextEntry = NextEntry->Flink)
320 {
321 /* Get the entry */
322 Profile = CONTAINING_RECORD(NextEntry, KPROFILE, ProfileListEntry);
323
324 /* Check if the source is good, and if it's within the range */
325 if ((Profile->Source != Source) ||
326 (ProgramCounter < (ULONG_PTR)Profile->RangeBase) ||
327 (ProgramCounter > (ULONG_PTR)Profile->RangeLimit))
328 {
329 continue;
330 }
331
332 /* Get the Pointer to the Bucket Value representing this Program Counter */
333 BucketValue = (PULONG)((ULONG_PTR)Profile->Buffer +
334 (((ProgramCounter - (ULONG_PTR)Profile->RangeBase)
335 >> Profile->BucketShift) &~ 0x3));
336
337 /* Increment the value */
338 (*BucketValue)++;
339 }
340}
341
342/*
343 * @implemented
344 *
345 * Remarks:
346 * Called from HAL, this function looks up the process
347 * entries, finds the proper source object, verifies the
348 * ranges with the trapframe data, and inserts the information
349 * from the trap frame into the buffer, while using buckets and
350 * shifting like we specified. -- Alex
351 */
352VOID
353NTAPI
356{
357 PKPROCESS Process = KeGetCurrentThread()->ApcState.Process;
358
359 /* We have to parse 2 lists. Per-Process and System-Wide */
360 KiParseProfileList(TrapFrame, Source, &Process->ProfileListHead);
362}
363
364/*
365 * @implemented
366 */
367VOID
368NTAPI
370{
371 /* Set the IRQL at which Profiling will run */
372 KiProfileIrql = ProfileIrql;
373}
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
ULONG_PTR KAFFINITY
Definition: compat.h:85
#define ULONG_PTR
Definition: config.h:101
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:43
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define PROFILE_LEVEL
Definition: env_spec_w32.h:698
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define NonPagedPool
Definition: env_spec_w32.h:307
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
Status
Definition: gdiplustypes.h:25
#define KeGetCurrentThread
Definition: hal.h:55
VOID NTAPI HalStartProfileInterrupt(IN KPROFILE_SOURCE ProfileSource)
Definition: profil.c:33
VOID NTAPI HalStopProfileInterrupt(IN KPROFILE_SOURCE ProfileSource)
Definition: profil.c:22
ULONG_PTR NTAPI HalSetProfileInterval(IN ULONG_PTR Interval)
Definition: profil.c:44
enum _KPROFILE_SOURCE KPROFILE_SOURCE
@ ProfileAlignmentFixup
Definition: winternl.h:2124
@ ProfileTime
Definition: winternl.h:2123
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3169
struct _KPROFILE KPROFILE
@ ProfileObject
Definition: ketypes.h:429
DWORD Interval
Definition: netstat.c:30
#define KeGetTrapFramePc(TrapFrame)
Definition: ke.h:37
BOOLEAN NTAPI KeStartProfile(IN PKPROFILE Profile, IN PVOID Buffer)
Definition: profobj.c:52
VOID NTAPI KeInitializeProfile(PKPROFILE Profile, PKPROCESS Process, PVOID ImageBase, SIZE_T ImageSize, ULONG BucketSize, KPROFILE_SOURCE ProfileSource, KAFFINITY Affinity)
Definition: profobj.c:28
VOID NTAPI KeSetProfileIrql(IN KIRQL ProfileIrql)
Definition: profobj.c:369
VOID NTAPI KeSetIntervalProfile(IN ULONG Interval, IN KPROFILE_SOURCE ProfileSource)
Definition: profobj.c:264
ULONG KiProfileTimeInterval
Definition: profobj.c:21
VOID NTAPI KeProfileInterrupt(IN PKTRAP_FRAME TrapFrame)
Definition: profobj.c:296
LIST_ENTRY KiProfileListHead
Definition: profobj.c:18
KIRQL KiProfileIrql
Definition: profobj.c:17
KSPIN_LOCK KiProfileLock
Definition: profobj.c:20
VOID NTAPI KiParseProfileList(IN PKTRAP_FRAME TrapFrame, IN KPROFILE_SOURCE Source, IN PLIST_ENTRY ListHead)
Definition: profobj.c:304
ULONG KiProfileAlignmentFixupInterval
Definition: profobj.c:22
LIST_ENTRY KiProfileSourceListHead
Definition: profobj.c:19
BOOLEAN NTAPI KeStopProfile(IN PKPROFILE Profile)
Definition: profobj.c:153
VOID NTAPI KeProfileInterruptWithSource(IN PKTRAP_FRAME TrapFrame, IN KPROFILE_SOURCE Source)
Definition: profobj.c:354
ULONG NTAPI KeQueryIntervalProfile(IN KPROFILE_SOURCE ProfileSource)
Definition: profobj.c:219
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135
KPROFILE_SOURCE Source
Definition: haltypes.h:339
LIST_ENTRY ProfileListHead
Definition: ketypes.h:2085
LIST_ENTRY ListEntry
Definition: ke.h:22
KPROFILE_SOURCE Source
Definition: ke.h:21
struct _KPROCESS * Process
Definition: ketypes.h:919
CSHORT Size
Definition: ketypes.h:917
ULONG BucketShift
Definition: ketypes.h:922
PVOID RangeLimit
Definition: ketypes.h:921
KPROFILE_SOURCE Source
Definition: ketypes.h:926
PVOID Buffer
Definition: ketypes.h:923
BOOLEAN Started
Definition: ketypes.h:927
PVOID RangeBase
Definition: ketypes.h:920
CSHORT Type
Definition: ketypes.h:916
KAFFINITY Affinity
Definition: ketypes.h:925
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
_In_ ULONG _In_ ULONG _In_ ULONG _Out_ PKIRQL _Out_ PKAFFINITY Affinity
Definition: halfuncs.h:174
#define HalQuerySystemInformation
Definition: haltypes.h:294
@ HalProfileSourceInterval
Definition: haltypes.h:49
@ HalProfileSourceInformation
Definition: haltypes.h:20
#define HalSetSystemInformation
Definition: haltypes.h:295
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778