VirtualBox

source: kStuff/trunk/kProfiler2/prfcore.cpp.h@ 2

Last change on this file since 2 was 2, checked in by bird, 17 years ago

Imported http://svn.netlabs.org/repos/libc/trunk/kStuff, revision 3612.

  • Property svn:keywords set to Id Revision
File size: 19.8 KB
Line 
1/* $Id: prfcore.cpp.h 2 2007-11-16 16:07:14Z bird $ */
2/** @file
3 * kProfiler Mark 2 - Core Code Template.
4 */
5
6/*
7 * Copyright (c) 2006-2007 knut st. osmundsen <bird-src-spam@anduin.net>
8 *
9 * This file is part of kProfiler.
10 *
11 * kProfiler is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * kProfiler is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with kProfiler; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27
28/**
29 * Gets a function, create a new one if necessary.
30 */
31static KPRF_TYPE(P,FUNC) KPRF_NAME(GetFunction)(KPRF_TYPE(P,HDR) pHdr, KPRF_TYPE(,UPTR) uPC)
32{
33 /*
34 * Perform a binary search of the function lookup table.
35 */
36 KPRF_TYPE(P,FUNC) paFunctions = KPRF_OFF2PTR(P,FUNC, pHdr->offFunctions, pHdr);
37
38 KPRF_FUNCS_READ_LOCK();
39 KI32 iStart = 0;
40 KI32 iLast = pHdr->cFunctions - 1;
41 KI32 i = iLast / 2;
42 for (;;)
43 {
44 KU32 iFunction = pHdr->aiFunctions[i];
45 KPRF_TYPE(,IPTR) iDiff = uPC - paFunctions[iFunction].uEntryPtr;
46 if (!iDiff)
47 {
48 KPRF_FUNCS_READ_UNLOCK();
49 return &paFunctions[iFunction];
50 }
51 if (iLast == iStart)
52 break;
53 if (iDiff < 0)
54 iLast = i - 1;
55 else
56 iStart = i + 1;
57 if (iLast < iStart)
58 break;
59 i = iStart + (iLast - iStart) / 2;
60 }
61 KPRF_FUNCS_READ_UNLOCK();
62
63 /*
64 * It wasn't found, try add it.
65 */
66 if (pHdr->cFunctions < pHdr->cMaxFunctions)
67 return KPRF_NAME(NewFunction)(pHdr, uPC);
68 return NULL;
69}
70
71
72/**
73 * Unwind one frame.
74 */
75static KU64* KPRF_NAME(UnwindOne)(KPRF_TYPE(P,HDR) pHdr, KPRF_TYPE(P,STACK) pStack, KPRF_TYPE(,UPTR) uPC, KU64 TS)
76{
77 /*
78 * Pop off the frame and update the frame below / thread.
79 */
80 KPRF_TYPE(P,FRAME) pFrame = &pStack->aFrames[--pStack->cFrames];
81 KU64 *pCurOverheadTicks;
82 if (pStack->cFrames)
83 {
84 KPRF_TYPE(P,FRAME) pTopFrame = pFrame - 1;
85 pTopFrame->OverheadTicks += pFrame->OverheadTicks + pFrame->CurOverheadTicks;
86 pTopFrame->SleepTicks += pFrame->SleepTicks;
87 pTopFrame->OnTopOfStackStart = TS;
88 pTopFrame->CurOverheadTicks = 0;
89
90 pCurOverheadTicks = &pTopFrame->CurOverheadTicks;
91 }
92 else
93 {
94 KPRF_TYPE(P,THREAD) pThread = KPRF_OFF2PTR(P,THREAD, pStack->offThread, pHdr);
95 pThread->ProfiledTicks += TS - pFrame->OnStackStart - pFrame->CurOverheadTicks - pFrame->OverheadTicks - pFrame->SleepTicks;
96 pThread->OverheadTicks += pFrame->OverheadTicks + pFrame->CurOverheadTicks;
97 pThread->SleepTicks += pFrame->SleepTicks;
98
99 pCurOverheadTicks = &pThread->OverheadTicks;
100 }
101
102 /*
103 * Update the function (if any).
104 */
105 if (pFrame->offFunction)
106 {
107 KPRF_TYPE(P,FUNC) pFunc = KPRF_OFF2PTR(P,FUNC, pFrame->offFunction, pHdr);
108
109 /* Time on stack */
110 KU64 Ticks = TS - pFrame->OnStackStart;
111 Ticks -= pFrame->OverheadTicks + pFrame->CurOverheadTicks + pFrame->SleepTicks;
112/** @todo adjust overhead */
113KPRF_ASSERT(!(Ticks >> 63));
114 if (pFunc->OnStack.MinTicks > Ticks)
115 KPRF_ATOMIC_SET64(&pFunc->OnStack.MinTicks, Ticks);
116 if (pFunc->OnStack.MaxTicks < Ticks)
117 KPRF_ATOMIC_SET64(&pFunc->OnStack.MaxTicks, Ticks);
118 KPRF_ATOMIC_ADD64(&pFunc->OnStack.SumTicks, Ticks);
119
120 /* Time on top of stack */
121 Ticks = TS - pFrame->OnTopOfStackStart;
122 Ticks -= pFrame->CurOverheadTicks;
123 Ticks += pFrame->OnTopOfStackTicks;
124/** @todo adjust overhead */
125KPRF_ASSERT(!(Ticks >> 63));
126 if (pFunc->OnTopOfStack.MinTicks > Ticks)
127 KPRF_ATOMIC_SET64(&pFunc->OnTopOfStack.MinTicks, Ticks);
128 if (pFunc->OnTopOfStack.MaxTicks < Ticks)
129 KPRF_ATOMIC_SET64(&pFunc->OnTopOfStack.MaxTicks, Ticks);
130 KPRF_ATOMIC_ADD64(&pFunc->OnTopOfStack.SumTicks, Ticks);
131
132 /* calls */
133 if (pFrame->cCalls)
134 KPRF_ATOMIC_ADD64(&pFunc->cCalls, pFrame->cCalls);
135 }
136
137 return pCurOverheadTicks;
138}
139
140
141/**
142 * Unwinds the stack.
143 *
144 * On MSC+AMD64 we have to be very very careful here, because the uFramePtr cannot be trusted.
145 */
146static KU64* KPRF_NAME(UnwindInt)(KPRF_TYPE(P,HDR) pHdr, KPRF_TYPE(P,STACK) pStack, KPRF_TYPE(,UPTR) uPC, KPRF_TYPE(,UPTR) uFramePtr, KU64 TS)
147{
148 /** @todo need to deal with alternative stacks! */
149
150 /*
151 * Pop the stack until we're down below the current frame (uFramePtr).
152 */
153 KI32 iFrame = pStack->cFrames - 1;
154 KPRF_TYPE(P,FRAME) pFrame = &pStack->aFrames[iFrame];
155
156 /* the most frequent case first. */
157#if K_OS == K_OS_WINDOWS && K_ARCH == K_ARCH_AMD64
158 if ( uFramePtr == pFrame->uFramePtr
159 || ( pFrame->uFramePtr < uFramePtr
160 && iFrame > 0
161 && pFrame[-1].uFramePtr > uFramePtr))
162 return KPRF_NAME(UnwindOne)(pHdr, pStack, uPC, TS);
163#else
164 if (uFramePtr == pFrame->uFramePtr)
165 return KPRF_NAME(UnwindOne)(pHdr, pStack, uPC, TS);
166#endif
167
168 /* none? */
169 if (pFrame->uFramePtr > uFramePtr)
170 return &pFrame->CurOverheadTicks;
171
172 /* one or more, possibly all */
173 KU64 *pCurOverheadTicks = KPRF_NAME(UnwindOne)(pHdr, pStack, uPC, TS);
174 pFrame--;
175 if ( iFrame > 0
176#if K_OS == K_OS_WINDOWS && K_ARCH == K_ARCH_AMD64
177 && pFrame->uFramePtr <= uFramePtr
178 && pFrame[-1].uFramePtr > uFramePtr)
179#else
180 && pFrame->uFramePtr <= uFramePtr)
181#endif
182 {
183 KPRF_TYPE(P,THREAD) pThread = KPRF_OFF2PTR(P,THREAD, pStack->offThread, pHdr);
184 pThread->cUnwinds++; /* (This is the reason for what looks like a bad loop unrolling.) */
185
186 pCurOverheadTicks = KPRF_NAME(UnwindOne)(pHdr, pStack, uPC, TS);
187 iFrame -= 2;
188 pFrame--;
189#if K_OS == K_OS_WINDOWS && K_ARCH == K_ARCH_AMD64
190 while ( iFrame > 0
191 && pFrame->uFramePtr <= uFramePtr
192 && pFrame[-1].uFramePtr > uFramePtr)
193#else
194 while ( iFrame >= 0
195 && pFrame->uFramePtr <= uFramePtr)
196#endif
197 {
198 pCurOverheadTicks = KPRF_NAME(UnwindOne)(pHdr, pStack, uPC, TS);
199 iFrame--;
200 pFrame--;
201 }
202 }
203
204 return pCurOverheadTicks;
205}
206
207
208
209/**
210 * Enter function.
211 *
212 * @returns Where to account overhead.
213 * @returns NULL if profiling is inactive.
214 *
215 * @param uPC The program counter register. (not relative)
216 * @param uFramePtr The stack frame address. This must match the one passed to kPrfLeave. (not relative)
217 * @param TS The timestamp when we entered into the profiler.
218 * This must not be modified touched!
219 *
220 * @internal ?
221 */
222KPRF_DECL_FUNC(KU64 *, Enter)(KPRF_TYPE(,UPTR) uPC, KPRF_TYPE(,UPTR) uFramePtr, const KU64 TS)
223{
224 /*
225 * Is profiling active ?
226 */
227 if (!KPRF_IS_ACTIVE())
228 return NULL;
229
230 /*
231 * Get the header and adjust input addresses.
232 */
233 KPRF_TYPE(P,HDR) pHdr = KPRF_GET_HDR();
234 if (!pHdr)
235 return NULL;
236 const KPRF_TYPE(,UPTR) uBasePtr = pHdr->uBasePtr;
237 if (uBasePtr)
238 {
239 uFramePtr -= uBasePtr;
240 uPC -= uBasePtr;
241 }
242
243 /*
244 * Get the current thread. Reject unknown, inactive (in whatever way),
245 * and thread which has performed a stack switch.
246 */
247 KPRF_TYPE(P,THREAD) pThread = KPRF_GET_THREAD();
248 if (!pThread)
249 return NULL;
250 KPRF_TYPE(,THREADSTATE) enmThreadState = pThread->enmState;
251 if ( enmThreadState != KPRF_TYPE(,THREADSTATE_ACTIVE)
252 && enmThreadState != KPRF_TYPE(,THREADSTATE_OVERFLOWED)
253 )
254 return NULL;
255 if (pThread->uStackBasePtr < uFramePtr) /* ASSUMES stack direction */
256 {
257 pThread->cStackSwitchRejects++;
258 return NULL;
259 }
260 pThread->enmState = KPRF_TYPE(,THREADSTATE_SUSPENDED);
261
262
263 /*
264 * Update the thread statistics.
265 */
266 pThread->cCalls++;
267 KPRF_TYPE(,UPTR) cbStack = pThread->uStackBasePtr - uFramePtr; /* ASSUMES stack direction */
268 if (pThread->cbMaxStack < cbStack)
269 pThread->cbMaxStack = cbStack;
270
271 /*
272 * Check if an longjmp or throw has taken place.
273 * This check will not work if a stack switch has taken place (can fix that later).
274 */
275 KPRF_TYPE(P,STACK) pStack = KPRF_OFF2PTR(P,STACK, pThread->offStack, pHdr);
276 KU32 iFrame = pStack->cFrames;
277 KPRF_TYPE(P,FRAME) pFrame = &pStack->aFrames[iFrame];
278 if ( iFrame
279#if K_OS == K_OS_WINDOWS && K_ARCH == K_ARCH_AMD64
280 && 0) /* don't bother her yet because of _penter/_pexit frame problems. */
281#else
282 && pThread->uStackBasePtr >= uFramePtr /* ASSUMES stack direction */
283 && pFrame[-1].uFramePtr + (KPRF_BITS - 8) / 8 < uFramePtr) /* ASSUMES stack direction */
284#endif
285 {
286 KPRF_NAME(UnwindInt)(pHdr, pStack, uPC, uFramePtr, TS);
287 iFrame = pStack->cFrames;
288 }
289
290 /*
291 * Allocate a new stack frame.
292 */
293 if (iFrame >= pHdr->cMaxStackFrames)
294 {
295 /* overflow */
296 pThread->enmState = KPRF_TYPE(,THREADSTATE_OVERFLOWED);
297 pThread->cOverflows += enmThreadState != KPRF_TYPE(,THREADSTATE_OVERFLOWED);
298 return &pStack->aFrames[iFrame - 1].CurOverheadTicks;
299 }
300 pStack->cFrames++;
301
302 /*
303 * Update the old top frame if any.
304 */
305 if (iFrame)
306 {
307 KPRF_TYPE(P,FRAME) pOldFrame = pFrame - 1;
308 pOldFrame->OnTopOfStackTicks += TS - pOldFrame->OnTopOfStackStart;
309 pOldFrame->cCalls++;
310 }
311
312 /*
313 * Fill in the new frame.
314 */
315 pFrame->CurOverheadTicks = 0;
316 pFrame->OverheadTicks = 0;
317 pFrame->SleepTicks = 0;
318 pFrame->OnStackStart = TS;
319 pFrame->OnTopOfStackStart = TS;
320 pFrame->OnTopOfStackTicks = 0;
321 pFrame->cCalls = 0;
322 pFrame->uFramePtr = uFramePtr;
323
324 /*
325 * Find the relevant function.
326 */
327 KPRF_TYPE(P,FUNC) pFunc = KPRF_NAME(GetFunction)(pHdr, uPC);
328 if (pFunc)
329 {
330 pFrame->offFunction = KPRF_PTR2OFF(pFunc, pHdr);
331 pFunc->cOnStack++;
332 }
333 else
334 pFrame->offFunction = 0;
335
336 /*
337 * Nearly done, We only have to reactivate the thread and account overhead.
338 * The latter is delegated to the caller.
339 */
340 pThread->enmState = KPRF_TYPE(,THREADSTATE_ACTIVE);
341 return &pFrame->CurOverheadTicks;
342}
343
344
345/**
346 * Leave function.
347 *
348 * @returns Where to account overhead.
349 * @returns NULL if profiling is inactive.
350 *
351 * @param uPC The program counter register.
352 * @param uFramePtr The stack frame address. This must match the one passed to kPrfEnter.
353 * @param TS The timestamp when we entered into the profiler.
354 * This must not be modified because the caller could be using it!
355 * @internal
356 */
357KPRF_DECL_FUNC(KU64 *, Leave)(KPRF_TYPE(,UPTR) uPC, KPRF_TYPE(,UPTR) uFramePtr, const KU64 TS)
358{
359 /*
360 * Is profiling active ?
361 */
362 if (!KPRF_IS_ACTIVE())
363 return NULL;
364
365 /*
366 * Get the header and adjust input addresses.
367 */
368 KPRF_TYPE(P,HDR) pHdr = KPRF_GET_HDR();
369 if (!pHdr)
370 return NULL;
371 const KPRF_TYPE(,UPTR) uBasePtr = pHdr->uBasePtr;
372 if (uBasePtr)
373 {
374 uFramePtr -= uBasePtr;
375 uPC -= uBasePtr;
376 }
377
378 /*
379 * Get the current thread and suspend profiling of the thread until we leave this function.
380 * Also reject threads which aren't active in some way.
381 */
382 KPRF_TYPE(P,THREAD) pThread = KPRF_GET_THREAD();
383 if (!pThread)
384 return NULL;
385 KPRF_TYPE(,THREADSTATE) enmThreadState = pThread->enmState;
386 if ( enmThreadState != KPRF_TYPE(,THREADSTATE_ACTIVE)
387 && enmThreadState != KPRF_TYPE(,THREADSTATE_OVERFLOWED)
388 )
389 return NULL;
390 KPRF_TYPE(P,STACK) pStack = KPRF_OFF2PTR(P,STACK, pThread->offStack, pHdr);
391 if (!pStack->cFrames)
392 return NULL;
393 pThread->enmState = KPRF_TYPE(,THREADSTATE_SUSPENDED);
394
395 /*
396 * Unwind the stack down to and including the entry indicated by uFramePtr.
397 * Leave it to the caller to update the overhead.
398 */
399 KU64 *pCurOverheadTicks = KPRF_NAME(UnwindInt)(pHdr, pStack, uPC, uFramePtr, TS);
400
401 pThread->enmState = enmThreadState;
402 return pCurOverheadTicks;
403}
404
405
406/**
407 * Register the current thread.
408 *
409 * A thread can only be profiled if it has been registered by a call to this function.
410 *
411 * @param uPC The program counter register.
412 * @param uStackBasePtr The base of the stack.
413 */
414KPRF_DECL_FUNC(KPRF_TYPE(P,THREAD), RegisterThread)(KPRF_TYPE(,UPTR) uStackBasePtr, const char *pszName)
415{
416 /*
417 * Get the header and adjust input address.
418 * (It doesn't matter whether we're active or not.)
419 */
420 KPRF_TYPE(P,HDR) pHdr = KPRF_GET_HDR();
421 if (!pHdr)
422 return NULL;
423 const KPRF_TYPE(,UPTR) uBasePtr = pHdr->uBasePtr;
424 if (uBasePtr)
425 uStackBasePtr -= uBasePtr;
426
427
428 /*
429 * Allocate a thread and a stack.
430 */
431 KPRF_THREADS_LOCK();
432 if (pHdr->cThreads < pHdr->cMaxThreads)
433 {
434 KPRF_TYPE(P,STACK) pStack = KPRF_OFF2PTR(P,STACK, pHdr->offStacks, pHdr);
435 KU32 cLeft = pHdr->cMaxStacks;
436 do
437 {
438 if (!pStack->offThread)
439 {
440 /* init the stack. */
441 pStack->cFrames = 0;
442 pStack->offThread = pHdr->offThreads + pHdr->cbThread * pHdr->cThreads++;
443 pHdr->cStacks++;
444
445 /* init the thread */
446 KPRF_TYPE(P,THREAD) pThread = KPRF_OFF2PTR(P,THREAD, pStack->offThread, pHdr);
447 pThread->ThreadId = KPRF_GET_THREADID();
448 unsigned i = 0;
449 if (pszName)
450 while (i < sizeof(pThread->szName) - 1 && *pszName)
451 pThread->szName[i++] = *pszName++;
452 while (i < sizeof(pThread->szName))
453 pThread->szName[i++] = '\0';
454 pThread->enmState = KPRF_TYPE(,THREADSTATE_SUSPENDED);
455 pThread->Reserved0 = KPRF_TYPE(,THREADSTATE_TERMINATED);
456 pThread->uStackBasePtr = uStackBasePtr;
457 pThread->cbMaxStack = 0;
458 pThread->cCalls = 0;
459 pThread->cOverflows = 0;
460 pThread->cStackSwitchRejects = 0;
461 pThread->cUnwinds = 0;
462 pThread->ProfiledTicks = 0;
463 pThread->OverheadTicks = 0;
464 pThread->SleepTicks = 0;
465 pThread->offStack = KPRF_PTR2OFF(pStack, pHdr);
466
467
468 /* set the thread and make it active. */
469 KPRF_THREADS_UNLOCK();
470 KPRF_SET_THREAD(pThread);
471 pThread->enmState = KPRF_TYPE(,THREADSTATE_ACTIVE);
472 return pThread;
473 }
474
475 /* next */
476 pStack = KPRF_TYPE(P,STACK)(((KPRF_TYPE(,UPTR))pStack + pHdr->cbStack));
477 } while (--cLeft > 0);
478 }
479
480 KPRF_THREADS_UNLOCK();
481 return NULL;
482}
483
484
485/**
486 * Terminates a thread.
487 *
488 * To terminate the current thread use DeregisterThread(), because that
489 * cleans up the TLS entry too.
490 *
491 * @param pHdr The profiler data set header.
492 * @param pThread The thread to terminate.
493 * @param TS The timestamp to use when terminating the thread.
494 */
495KPRF_DECL_FUNC(void, TerminateThread)(KPRF_TYPE(P,HDR) pHdr, KPRF_TYPE(P,THREAD) pThread, KU64 TS)
496{
497 if (pThread->enmState == KPRF_TYPE(,THREADSTATE_TERMINATED))
498 return;
499 pThread->enmState = KPRF_TYPE(,THREADSTATE_TERMINATED);
500
501 /*
502 * Unwind the entire stack.
503 */
504 if (pThread->offStack)
505 {
506 KPRF_TYPE(P,STACK) pStack = KPRF_OFF2PTR(P,STACK, pThread->offStack, pHdr);
507 for (KU32 cFrames = pStack->cFrames; cFrames > 0; cFrames--)
508 KPRF_NAME(UnwindOne)(pHdr, pStack, 0, TS);
509
510 /*
511 * Free the stack.
512 */
513 pThread->offStack = 0;
514 KPRF_THREADS_LOCK();
515 pStack->offThread = 0;
516 pHdr->cStacks--;
517 KPRF_THREADS_UNLOCK();
518 }
519}
520
521
522/**
523 * Deregister (terminate) the current thread.
524 */
525KPRF_DECL_FUNC(void, DeregisterThread)(void)
526{
527 KU64 TS = KPRF_NOW();
528
529 /*
530 * Get the header, then get the thread and mark it terminated.
531 * (It doesn't matter whether we're active or not.)
532 */
533 KPRF_TYPE(P,HDR) pHdr = KPRF_GET_HDR();
534 if (!pHdr)
535 return;
536
537 KPRF_TYPE(P,THREAD) pThread = KPRF_GET_THREAD();
538 KPRF_SET_THREAD(NULL);
539 if (!pThread)
540 return;
541 KPRF_NAME(TerminateThread)(pHdr, pThread, TS);
542}
543
544
545/**
546 * Resumes / restarts a thread.
547 *
548 * @param fReset If set the stack is reset.
549 */
550KPRF_DECL_FUNC(void, ResumeThread)(int fReset)
551{
552 KU64 TS = KPRF_NOW();
553
554 /*
555 * Get the header, then get the thread and mark it terminated.
556 * (It doesn't matter whether we're active or not.)
557 */
558 KPRF_TYPE(P,HDR) pHdr = KPRF_GET_HDR();
559 if (!pHdr)
560 return;
561
562 KPRF_TYPE(P,THREAD) pThread = KPRF_GET_THREAD();
563 if (!pThread)
564 return;
565 if (pThread->enmState != KPRF_TYPE(,THREADSTATE_SUSPENDED))
566 return;
567
568 /*
569 * Reset (unwind) the stack?
570 */
571 KPRF_TYPE(P,STACK) pStack = KPRF_OFF2PTR(P,STACK, pThread->offStack, pHdr);
572 if (fReset)
573 {
574 KU32 cFrames = pStack->cFrames;
575 while (cFrames-- > 0)
576 KPRF_NAME(UnwindOne)(pHdr, pStack, 0, TS);
577 }
578 /*
579 * If we've got any thing on the stack, we'll have to stop the sleeping period.
580 */
581 else if (pStack->cFrames > 0)
582 {
583 KPRF_TYPE(P,FRAME) pFrame = &pStack->aFrames[pStack->cFrames - 1];
584
585 /* update the sleeping time and set the start of the new top-of-stack period. */
586 pFrame->SleepTicks += TS - pFrame->OnTopOfStackStart;
587 pFrame->OnTopOfStackStart = TS;
588 }
589 /** @todo we're not accounting overhead here! */
590
591 /*
592 * We're done, switch the thread to active state.
593 */
594 pThread->enmState = KPRF_TYPE(,THREADSTATE_ACTIVE);
595}
596
597
598/**
599 * Suspend / completes a thread.
600 *
601 * The thread will be in a suspend state where the time will be accounted for as sleeping.
602 *
603 * @param fUnwind If set the stack is unwound and the thread statistics updated.
604 */
605KPRF_DECL_FUNC(void, SuspendThread)(int fUnwind)
606{
607 KU64 TS = KPRF_NOW();
608
609 /*
610 * Get the header, then get the thread and mark it terminated.
611 * (It doesn't matter whether we're active or not.)
612 */
613 KPRF_TYPE(P,HDR) pHdr = KPRF_GET_HDR();
614 if (!pHdr)
615 return;
616
617 KPRF_TYPE(P,THREAD) pThread = KPRF_GET_THREAD();
618 if (!pThread)
619 return;
620 if ( pThread->enmState != KPRF_TYPE(,THREADSTATE_ACTIVE)
621 && pThread->enmState != KPRF_TYPE(,THREADSTATE_OVERFLOWED)
622 && (pThread->enmState != KPRF_TYPE(,THREADSTATE_SUSPENDED) || fUnwind))
623 return;
624
625 pThread->enmState = KPRF_TYPE(,THREADSTATE_SUSPENDED);
626
627 /*
628 * Unwind the stack?
629 */
630 KPRF_TYPE(P,STACK) pStack = KPRF_OFF2PTR(P,STACK, pThread->offStack, pHdr);
631 if (fUnwind)
632 {
633 KU32 cFrames = pStack->cFrames;
634 while (cFrames-- > 0)
635 KPRF_NAME(UnwindOne)(pHdr, pStack, 0, TS);
636 }
637 /*
638 * If we've got any thing on the stack, we'll have to record the sleeping period
639 * of the thread. If not we'll ignore it (for now at least).
640 */
641 else if (pStack->cFrames > 0)
642 {
643 KPRF_TYPE(P,FRAME) pFrame = &pStack->aFrames[pStack->cFrames - 1];
644
645 /* update the top of stack time and set the start of the sleep period. */
646 pFrame->OnTopOfStackTicks += TS - pFrame->OnTopOfStackStart;
647 pFrame->OnTopOfStackStart = TS;
648 }
649
650 /** @todo we're not accounting overhead here! */
651}
652
653
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette