1. fixed NtCreateProcess to do some buffer checks and moved the implementation to...
[reactos.git] / reactos / ntoskrnl / ke / profile.c
1 /* $Id$
2 *
3 * FILE: ntoskrnl/ke/profile.c
4 * PURPOSE: Kernel Profiling
5 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
6 * UPDATE HISTORY:
7 * Created 23/06/04
8 */
9
10 #include <ntoskrnl.h>
11 #define NDEBUG
12 #include <internal/debug.h>
13
14 extern LIST_ENTRY ProcessProfileListHashTable[PROFILE_HASH_TABLE_SIZE];
15 extern LIST_ENTRY SystemProfileList;
16 extern KSPIN_LOCK ProfileListLock;
17 extern BOOLEAN ProfileInitDone;
18
19 /* FUNCTIONS *****************************************************************/
20
21 VOID
22 KiAddProfileEventToProcess(PLIST_ENTRY ListHead, PVOID Eip)
23 /*
24 * Add a profile event to the profile objects for a particular process
25 * or the system
26 */
27 {
28 PKPROFILE current;
29 PLIST_ENTRY current_entry;
30
31 current_entry = ListHead->Flink;
32 while (current_entry != ListHead)
33 {
34 current = CONTAINING_RECORD(current_entry, KPROFILE, ListEntry);
35
36 if (current->Base > Eip)
37 {
38 return;
39 }
40
41 if (current->Base <= Eip && ((char*)current->Base + current->Size) > (char*)Eip &&
42 current->Started)
43 {
44 ULONG Bucket;
45
46 Bucket = ((ULONG)((char*)Eip - (char*)current->Base)) >> current->BucketShift;
47
48 if ((Bucket*4) < current->BufferSize)
49 {
50 current->Buffer[Bucket]++;
51 }
52 }
53
54 current_entry = current_entry->Flink;
55 }
56 }
57
58 VOID
59 KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Eip)
60 /*
61 * Add a profile event
62 */
63 {
64 HANDLE Pid;
65 PKPROCESS_PROFILE current;
66 PLIST_ENTRY current_entry;
67 PLIST_ENTRY ListHead;
68
69 if (!ProfileInitDone)
70 {
71 return;
72 }
73
74 Pid = PsGetCurrentProcessId();
75 ListHead =
76 ProcessProfileListHashTable[(ULONG)Pid % PROFILE_HASH_TABLE_SIZE].Flink;
77
78 KeAcquireSpinLockAtDpcLevel(&ProfileListLock);
79
80 current_entry = ListHead;
81 while (current_entry != ListHead)
82 {
83 current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE, ListEntry);
84
85 if (current->Pid == Pid)
86 {
87 KiAddProfileEventToProcess(&current->ProfileListHead, (PVOID)Eip);
88 break;
89 }
90
91 current_entry = current_entry->Flink;
92 }
93
94 KiAddProfileEventToProcess(&SystemProfileList, (PVOID)Eip);
95
96 KeReleaseSpinLockFromDpcLevel(&ProfileListLock);
97 }
98
99 VOID
100 KiInsertProfileIntoProcess(PLIST_ENTRY ListHead, PKPROFILE Profile)
101 /*
102 * Insert a profile object into the list for a process or the system
103 */
104 {
105 PKPROFILE current;
106 PLIST_ENTRY current_entry;
107
108 current_entry = ListHead;
109 while (current_entry != ListHead)
110 {
111 current = CONTAINING_RECORD(current_entry, KPROFILE, ListEntry);
112
113 if (current->Base > Profile->Base)
114 {
115 Profile->ListEntry.Flink = current_entry;
116 Profile->ListEntry.Blink = current_entry->Blink;
117 current_entry->Blink->Flink = &Profile->ListEntry;
118 current_entry->Blink = &Profile->ListEntry;
119 return;
120 }
121
122 current_entry = current_entry->Flink;
123 }
124 InsertTailList(ListHead, &Profile->ListEntry);
125 }
126
127 VOID
128 KiInsertProfile(PKPROFILE Profile)
129 /*
130 * Insert a profile into the relevant data structures
131 */
132 {
133 KIRQL oldIrql;
134
135 KeAcquireSpinLock(&ProfileListLock, &oldIrql);
136
137 if (Profile->Process == NULL)
138 {
139 KiInsertProfileIntoProcess(&SystemProfileList, Profile);
140 }
141 else
142 {
143 HANDLE Pid;
144 PKPROCESS_PROFILE current;
145 PLIST_ENTRY current_entry;
146 PLIST_ENTRY ListHead;
147
148 Pid = Profile->Process->UniqueProcessId;
149 ListHead = &ProcessProfileListHashTable[(ULONG_PTR)Pid % PROFILE_HASH_TABLE_SIZE];
150
151 current_entry = ListHead;
152 while(current_entry != ListHead)
153 {
154 current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE,
155 ListEntry);
156
157 if (current->Pid == Pid)
158 {
159 KiInsertProfileIntoProcess(&current->ProfileListHead, Profile);
160 KeReleaseSpinLock(&ProfileListLock, oldIrql);
161 return;
162 }
163
164 current_entry = current_entry->Flink;
165 }
166
167 current = ExAllocatePool(NonPagedPool, sizeof(KPROCESS_PROFILE));
168
169 current->Pid = Pid;
170 InitializeListHead(&current->ProfileListHead);
171 InsertTailList(ListHead, &current->ListEntry);
172
173 KiInsertProfileIntoProcess(&current->ProfileListHead, Profile);
174 }
175
176 KeReleaseSpinLock(&ProfileListLock, oldIrql);
177 }
178
179 VOID KiRemoveProfile(PKPROFILE Profile)
180 {
181 KIRQL oldIrql;
182
183 KeAcquireSpinLock(&ProfileListLock, &oldIrql);
184
185 if (Profile->Process == NULL)
186 {
187 RemoveEntryList(&Profile->ListEntry);
188 }
189 else
190 {
191 HANDLE Pid;
192 PLIST_ENTRY ListHead;
193 PKPROCESS_PROFILE current;
194 PLIST_ENTRY current_entry;
195
196 RemoveEntryList(&Profile->ListEntry);
197
198 Pid = Profile->Process->UniqueProcessId;
199 ListHead = &ProcessProfileListHashTable[(ULONG_PTR)Pid % PROFILE_HASH_TABLE_SIZE];
200
201 current_entry = ListHead;
202 while(current_entry != ListHead)
203 {
204 current = CONTAINING_RECORD(current_entry, KPROCESS_PROFILE,
205 ListEntry);
206
207 if (current->Pid == Pid)
208 {
209 if (IsListEmpty(&current->ProfileListHead))
210 {
211 RemoveEntryList(&current->ListEntry);
212 ExFreePool(current);
213 }
214 KeReleaseSpinLock(&ProfileListLock, oldIrql);
215 return;
216 }
217
218 current_entry = current_entry->Flink;
219 }
220 KEBUGCHECK(0);
221 }
222
223 KeReleaseSpinLock(&ProfileListLock, oldIrql);
224 }
225
226 VOID STDCALL
227 KiDeleteProfile(PVOID ObjectBody)
228 {
229 PKPROFILE Profile;
230
231 Profile = (PKPROFILE)ObjectBody;
232
233 KiRemoveProfile(Profile);
234 if (Profile->Process != NULL)
235 {
236 ObDereferenceObject(Profile->Process);
237 Profile->Process = NULL;
238 }
239
240 if (Profile->BufferMdl->MappedSystemVa != NULL)
241 {
242 MmUnmapLockedPages(Profile->BufferMdl->MappedSystemVa,
243 Profile->BufferMdl);
244 }
245 MmUnlockPages(Profile->BufferMdl);
246 ExFreePool(Profile->BufferMdl);
247 Profile->BufferMdl = NULL;
248 }
249
250 /*
251 * @unimplemented
252 */
253 STDCALL
254 VOID
255 KeProfileInterrupt(
256 PKTRAP_FRAME TrapFrame
257 )
258 {
259 UNIMPLEMENTED;
260 }
261
262 /*
263 * @unimplemented
264 */
265 STDCALL
266 VOID
267 KeProfileInterruptWithSource(
268 IN PKTRAP_FRAME TrapFrame,
269 IN KPROFILE_SOURCE Source
270 )
271 {
272 UNIMPLEMENTED;
273 }
274
275 /*
276 * @unimplemented
277 */
278 STDCALL
279 VOID
280 KeSetProfileIrql(
281 IN KIRQL ProfileIrql
282 )
283 {
284 UNIMPLEMENTED;
285 }