3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/profile.c
6 * PURPOSE: Kernel Profiling
8 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
13 #include <internal/debug.h>
15 extern LIST_ENTRY ProcessProfileListHashTable
[PROFILE_HASH_TABLE_SIZE
];
16 extern LIST_ENTRY SystemProfileList
;
17 extern KSPIN_LOCK ProfileListLock
;
18 extern BOOLEAN ProfileInitDone
;
20 /* FUNCTIONS *****************************************************************/
23 KiAddProfileEventToProcess(PLIST_ENTRY ListHead
, PVOID Eip
)
25 * Add a profile event to the profile objects for a particular process
30 PLIST_ENTRY current_entry
;
32 current_entry
= ListHead
->Flink
;
33 while (current_entry
!= ListHead
)
35 current
= CONTAINING_RECORD(current_entry
, KPROFILE
, ListEntry
);
37 if (current
->Base
> Eip
)
42 if (current
->Base
<= Eip
&& ((char*)current
->Base
+ current
->Size
) > (char*)Eip
&&
47 Bucket
= ((ULONG
)((char*)Eip
- (char*)current
->Base
)) >> current
->BucketShift
;
49 if ((Bucket
*4) < current
->BufferSize
)
51 current
->Buffer
[Bucket
]++;
55 current_entry
= current_entry
->Flink
;
60 KiAddProfileEvent(KPROFILE_SOURCE Source
, ULONG Eip
)
66 PKPROCESS_PROFILE current
;
67 PLIST_ENTRY current_entry
;
75 Pid
= PsGetCurrentProcessId();
77 ProcessProfileListHashTable
[(ULONG
)Pid
% PROFILE_HASH_TABLE_SIZE
].Flink
;
79 KeAcquireSpinLockAtDpcLevel(&ProfileListLock
);
81 current_entry
= ListHead
;
82 while (current_entry
!= ListHead
)
84 current
= CONTAINING_RECORD(current_entry
, KPROCESS_PROFILE
, ListEntry
);
86 if (current
->Pid
== Pid
)
88 KiAddProfileEventToProcess(¤t
->ProfileListHead
, (PVOID
)Eip
);
92 current_entry
= current_entry
->Flink
;
95 KiAddProfileEventToProcess(&SystemProfileList
, (PVOID
)Eip
);
97 KeReleaseSpinLockFromDpcLevel(&ProfileListLock
);
101 KiInsertProfileIntoProcess(PLIST_ENTRY ListHead
, PKPROFILE Profile
)
103 * Insert a profile object into the list for a process or the system
107 PLIST_ENTRY current_entry
;
109 current_entry
= ListHead
;
110 while (current_entry
!= ListHead
)
112 current
= CONTAINING_RECORD(current_entry
, KPROFILE
, ListEntry
);
114 if (current
->Base
> Profile
->Base
)
116 Profile
->ListEntry
.Flink
= current_entry
;
117 Profile
->ListEntry
.Blink
= current_entry
->Blink
;
118 current_entry
->Blink
->Flink
= &Profile
->ListEntry
;
119 current_entry
->Blink
= &Profile
->ListEntry
;
123 current_entry
= current_entry
->Flink
;
125 InsertTailList(ListHead
, &Profile
->ListEntry
);
129 KiInsertProfile(PKPROFILE Profile
)
131 * Insert a profile into the relevant data structures
136 KeAcquireSpinLock(&ProfileListLock
, &oldIrql
);
138 if (Profile
->Process
== NULL
)
140 KiInsertProfileIntoProcess(&SystemProfileList
, Profile
);
145 PKPROCESS_PROFILE current
;
146 PLIST_ENTRY current_entry
;
147 PLIST_ENTRY ListHead
;
149 Pid
= Profile
->Process
->UniqueProcessId
;
150 ListHead
= &ProcessProfileListHashTable
[(ULONG_PTR
)Pid
% PROFILE_HASH_TABLE_SIZE
];
152 current_entry
= ListHead
;
153 while(current_entry
!= ListHead
)
155 current
= CONTAINING_RECORD(current_entry
, KPROCESS_PROFILE
,
158 if (current
->Pid
== Pid
)
160 KiInsertProfileIntoProcess(¤t
->ProfileListHead
, Profile
);
161 KeReleaseSpinLock(&ProfileListLock
, oldIrql
);
165 current_entry
= current_entry
->Flink
;
168 current
= ExAllocatePool(NonPagedPool
, sizeof(KPROCESS_PROFILE
));
171 InitializeListHead(¤t
->ProfileListHead
);
172 InsertTailList(ListHead
, ¤t
->ListEntry
);
174 KiInsertProfileIntoProcess(¤t
->ProfileListHead
, Profile
);
177 KeReleaseSpinLock(&ProfileListLock
, oldIrql
);
180 VOID
KiRemoveProfile(PKPROFILE Profile
)
184 KeAcquireSpinLock(&ProfileListLock
, &oldIrql
);
186 if (Profile
->Process
== NULL
)
188 RemoveEntryList(&Profile
->ListEntry
);
193 PLIST_ENTRY ListHead
;
194 PKPROCESS_PROFILE current
;
195 PLIST_ENTRY current_entry
;
197 RemoveEntryList(&Profile
->ListEntry
);
199 Pid
= Profile
->Process
->UniqueProcessId
;
200 ListHead
= &ProcessProfileListHashTable
[(ULONG_PTR
)Pid
% PROFILE_HASH_TABLE_SIZE
];
202 current_entry
= ListHead
;
203 while(current_entry
!= ListHead
)
205 current
= CONTAINING_RECORD(current_entry
, KPROCESS_PROFILE
,
208 if (current
->Pid
== Pid
)
210 if (IsListEmpty(¤t
->ProfileListHead
))
212 RemoveEntryList(¤t
->ListEntry
);
215 KeReleaseSpinLock(&ProfileListLock
, oldIrql
);
219 current_entry
= current_entry
->Flink
;
224 KeReleaseSpinLock(&ProfileListLock
, oldIrql
);
228 KiDeleteProfile(PVOID ObjectBody
)
232 Profile
= (PKPROFILE
)ObjectBody
;
234 KiRemoveProfile(Profile
);
235 if (Profile
->Process
!= NULL
)
237 ObDereferenceObject(Profile
->Process
);
238 Profile
->Process
= NULL
;
241 if (Profile
->BufferMdl
->MappedSystemVa
!= NULL
)
243 MmUnmapLockedPages(Profile
->BufferMdl
->MappedSystemVa
,
246 MmUnlockPages(Profile
->BufferMdl
);
247 ExFreePool(Profile
->BufferMdl
);
248 Profile
->BufferMdl
= NULL
;
257 PKTRAP_FRAME TrapFrame
268 KeProfileInterruptWithSource(
269 IN PKTRAP_FRAME TrapFrame
,
270 IN KPROFILE_SOURCE Source
289 NtQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceCounter
,
290 OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL
)
292 LARGE_INTEGER PerfCounter
;
293 LARGE_INTEGER PerfFrequency
;
294 KPROCESSOR_MODE PreviousMode
;
295 NTSTATUS Status
= STATUS_SUCCESS
;
297 PreviousMode
= ExGetPreviousMode();
299 if(PreviousMode
!= KernelMode
)
303 ProbeForWrite(PerformanceCounter
,
304 sizeof(LARGE_INTEGER
),
306 if(PerformanceFrequency
!= NULL
)
308 ProbeForWrite(PerformanceFrequency
,
309 sizeof(LARGE_INTEGER
),
315 Status
= _SEH_GetExceptionCode();
319 if(!NT_SUCCESS(Status
))
325 PerfCounter
= KeQueryPerformanceCounter(&PerfFrequency
);
329 *PerformanceCounter
= PerfCounter
;
330 if(PerformanceFrequency
!= NULL
)
332 *PerformanceFrequency
= PerfFrequency
;
337 Status
= _SEH_GetExceptionCode();