3 * kProfiler Mark 2 - Core Header Template.
7 * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
33 * Mixed case name macro.
36 # define KPRF_NAME(Name) Name
40 * Upper case type name macro.
43 # define KPRF_TYPE(Prefix,Name) Prefix##Name
46 /** @type KPRF_DECL_FUNC
47 * The calling convention used.
49 #ifndef KPRF_DECL_FUNC
50 # define KPRF_DECL_FUNC(type, name) type name
54 * The bitsize of the format.
61 * The basic unsigned interger pointer type.
64 * The basic signed interger pointer type.
67 typedef KU16
KPRF_TYPE(,UPTR
);
68 typedef KI16
KPRF_TYPE(,IPTR
);
70 typedef KU32
KPRF_TYPE(,UPTR
);
71 typedef KI32
KPRF_TYPE(,IPTR
);
73 typedef KU64
KPRF_TYPE(,UPTR
);
74 typedef KI64
KPRF_TYPE(,IPTR
);
76 # error "KPRF_BITS has an invalid value. Supported values are 16, 32 and 64."
78 /** @type KPRF_TYPE(P,UPTR)
79 * Pointer to the basic pointer type.
81 typedef KPRF_TYPE(,UPTR
) *KPRF_TYPE(P
,UPTR
);
87 enum KPRF_TYPE(,CONSTANTS
)
89 /** Magic for the profiler header. (Unix Epoc) */
90 KPRF_TYPE(,HDR_MAGIC
) = 0x19700101
95 * The profile data header.
97 typedef struct KPRF_TYPE(,HDR
)
99 /** [0] The magic number for file data. (KPRF_TYPE(,HDR_MAGIC)) */
101 /** [4] KPRF_BITS. */
103 /** [8] The base address which all pointers should be relative to. */
104 KPRF_TYPE(,UPTR
) uBasePtr
;
113 /** [10] The size of this data set. */
115 /** [10] The allocated data set size. */
118 /** [18] The max number of functions the function table can hold. */
120 /** [1c] The current number of functions in the function table. */
122 /** [20] The offset of the function table (relative to this header). */
124 /** [24] The size of a function entry. */
127 /** [28] The max number of bytes the module segments can occupy. */
129 /** [2c] The current size of the module segment records. */
131 /** [30] The offset of the module segment records (relative to this header). */
134 /** [34] The max number of threads the thread table can contain. */
136 /** [38] The current number of threads in the thread table. */
138 /** [3c] The offset of the thread table (relative to this header). */
140 /** [40] The size of a thread entry. */
143 /** [44] The max number of stacks the stack table can contain. */
145 /** [48] The max number of stacks.
146 * Unlike the other members, the stacks can be reused. It follows that
147 * this count doesn't specify the number of used slots from the start. */
149 /** [4c] The offset of the thread table (relative to this header).
150 * This is usually 0 in a stored data set. */
152 /** [50] The size of a stack. */
154 /** [54] The maxium stack depth. */
155 KU32 cMaxStackFrames
;
157 /** [58] The process commandline.
158 * Might not always apply is will be 0 in those cases. This is normally written
159 * where the stacks used to be.
162 /** [5c] The length of the command line. (excludes the terminator). */
165 /** [60] The function lookup table (it contains indexes).
166 * This is sorted by address so that a binary search can be performed.
167 * Access to this table is managed externally, but generally a read/write lock is employed. */
170 /** Pointer to a profiler data header. */
171 typedef KPRF_TYPE(,HDR
) *KPRF_TYPE(P
,HDR
);
172 /** Pointer to a const profiler data header. */
173 typedef const KPRF_TYPE(,HDR
) *KPRF_TYPE(PC
,HDR
);
179 typedef struct KPRF_TYPE(,TIMESTAT
) /** @todo bad names and descriptions! */
181 /** The minimum period */
182 KU64
volatile MinTicks
;
183 /** The maximum period */
184 KU64
volatile MaxTicks
;
185 /** The sum of all periods. */
186 KU64
volatile SumTicks
;
187 } KPRF_TYPE(,TIMESTAT
);
188 /** Pointer to time statistics. */
189 typedef KPRF_TYPE(,TIMESTAT
) *KPRF_TYPE(P
,TIMESTAT
);
190 /** Pointer to const time statistics. */
191 typedef const KPRF_TYPE(,TIMESTAT
) *KPRF_TYPE(PC
,TIMESTAT
);
197 typedef struct KPRF_TYPE(,MODSEG
)
199 /** The address of the segment. (relative address) */
200 KPRF_TYPE(,UPTR
) uBasePtr
;
201 /** The size of the segment minus one (so the entire address space can be covered). */
202 KPRF_TYPE(,UPTR
) cbSegmentMinusOne
;
203 /** The segment number. (0 based) */
205 /** Flag indicating whether this segment is loaded or not.
206 * (A 16-bit value was choosen out of convenience, all that's stored is 0 or 1 anyway.) */
208 /** The length of the path.
209 * This is used to calculate the length of the record: offsetof(MODSEG, szPath) + cchPath + 1 */
211 /** The module name. */
213 } KPRF_TYPE(,MODSEG
);
214 /** Pointer to a module segment. */
215 typedef KPRF_TYPE(,MODSEG
) *KPRF_TYPE(P
,MODSEG
);
216 /** Pointer to a const module segment. */
217 typedef const KPRF_TYPE(,MODSEG
) *KPRF_TYPE(PC
,MODSEG
);
221 * The profiler data for a function.
223 typedef struct KPRF_TYPE(,FUNC
)
225 /** The entry address of the function. (relative address)
226 * This is the return address of the entry hook (_mcount, _penter, _ProfileHook32, ...). */
227 KPRF_TYPE(,UPTR
) uEntryPtr
;
228 /** Offset (relative to the profiler header) of the module segment to which this function belongs. */
231 /** The number times on the stack. */
232 KU64
volatile cOnStack
;
233 /** The number of calls made from this function. */
234 KU64
volatile cCalls
;
236 /** Time on stack. */
237 KPRF_TYPE(,TIMESTAT
) OnStack
;
238 /** Time on top of the stack, i.e. executing. */
239 KPRF_TYPE(,TIMESTAT
) OnTopOfStack
;
241 /** @todo recursion */
244 /** Pointer to the profiler data for a function. */
245 typedef KPRF_TYPE(,FUNC
) *KPRF_TYPE(P
,FUNC
);
246 /** Pointer to the const profiler data for a function. */
247 typedef const KPRF_TYPE(,FUNC
) *KPRF_TYPE(PC
,FUNC
);
253 typedef struct KPRF_TYPE(,FRAME
)
255 /** The accumulated overhead.
256 * Over head is accumulated by the parent frame when a child is poped off the stack. */
258 /** The current (top of stack) overhead. */
259 KU64 CurOverheadTicks
;
260 /** The accumulated sleep ticks.
261 * It's possible to notify the profiler that the thread is being put into a wait/sleep/yield
262 * state. The time spent sleeping is transfered to the parent frame when poping of a child one. */
264 /** The start of the on-stack period. */
266 /** The accumulated time on top (excludes overhead (sleep doesn't apply here obviously)). */
267 KU64 OnTopOfStackTicks
;
268 /** The start of the current on-top-of-stack period.
269 * This is also to mark the start of a sleeping period, the ResumeThread function will always
270 * treat it as the start of the suspend period. */
271 KU64 OnTopOfStackStart
;
272 /** The number of calls made from this stack frame. */
274 /** Stack address of this frame.
275 * This is used to detect throw and longjmp, and is also used to deal with overflow. (relative address) */
276 KPRF_TYPE(,UPTR
) uFramePtr
;
277 /** Offset (relative to the profiler header) to the function record.
278 * This is 0 if we're out of function space. */
281 /** Pointer to a stack frame. */
282 typedef KPRF_TYPE(,FRAME
) *KPRF_TYPE(P
,FRAME
);
283 /** Pointer to a const stack frame. */
284 typedef const KPRF_TYPE(,FRAME
) *KPRF_TYPE(PC
,FRAME
);
290 typedef struct KPRF_TYPE(,STACK
)
292 /** The offset (relative to the profiler header) of the thread owning the stack.
293 * This is zero if not in use, and non-zero if in use. */
295 /** The number of active stack frames. */
297 /** The stack frames.
298 * The actual size of this array is specified in the header. */
299 KPRF_TYPE(,FRAME
) aFrames
[1];
301 /** Pointer to a stack. */
302 typedef KPRF_TYPE(,STACK
) *KPRF_TYPE(P
,STACK
);
303 /** Pointer to a const stack. */
304 typedef const KPRF_TYPE(,STACK
) *KPRF_TYPE(PC
,STACK
);
310 typedef enum KPRF_TYPE(,THREADSTATE
)
312 /** The thread hasn't been used yet. */
313 KPRF_TYPE(,THREADSTATE_UNUSED
) = 0,
314 /** The thread is activly being profiled.
315 * A thread is added in the suspended state and then activated when
316 * starting to execute the first function.
318 KPRF_TYPE(,THREADSTATE_ACTIVE
),
319 /** The thread is currently suspended from profiling.
320 * Upon entering profiler code the thread is suspended, it's reactivated
321 * upon normal return.
323 KPRF_TYPE(,THREADSTATE_SUSPENDED
),
324 /** The thread is currently suspended due of stack overflow.
325 * When we overflow the stack frame array, the thread enter the overflow state. In this
326 * state nothing is profiled but we keep looking for the exit of the top frame. */
327 KPRF_TYPE(,THREADSTATE_OVERFLOWED
),
328 /** The thread is terminated.
329 * When we received a thread termination notification the thread is unwinded, statistics
330 * updated and the state changed to terminated. A terminated thread cannot be revivied. */
331 KPRF_TYPE(,THREADSTATE_TERMINATED
),
333 /** Ensure 32-bit size. */
334 KPRF_TYPE(,THREADSTATE_32BIT_HACK
) = 0x7fffffff
335 } KPRF_TYPE(,THREADSTATE
);
339 * Thread statistics and stack.
341 typedef struct KPRF_TYPE(,THREAD
)
343 /** The native thread id. */
345 /** The thread name. (optional) */
347 /** The thread current thread state. */
348 KPRF_TYPE(,THREADSTATE
) enmState
;
350 KPRF_TYPE(,THREADSTATE
) Reserved0
;
351 /** The base pointer of the thread stack. (relative address) */
352 KPRF_TYPE(,UPTR
) uStackBasePtr
;
353 /** The maximum depth of the thread stack (bytes). */
354 KPRF_TYPE(,UPTR
) cbMaxStack
;
355 /** The number of calls done by this thread. */
357 /** The number of times the stack overflowed. */
359 /** The number of times stack entries has been rejected because of a stack switch. */
360 KU64 cStackSwitchRejects
;
361 /** The number of times the stack has been unwinded more than one frame. */
364 /** The profiled ticks. (This does not include sleep or overhead ticks.)
365 * This is the accumulated on-stack values for the final stack frames. */
367 /** The accumulated overhead of this thread. */
369 /** The accumulated sleep ticks for this thread.
370 * See KPRF_TYPE(,FRAME)::SleepTicks for details. */
373 /** The offset of the stack. */
375 } KPRF_TYPE(,THREAD
);
376 /** Pointer to a thread. */
377 typedef KPRF_TYPE(,THREAD
) *KPRF_TYPE(P
,THREAD
);
378 /** Pointer to a const thread. */
379 typedef const KPRF_TYPE(,THREAD
) *KPRF_TYPE(PC
,THREAD
);