summaryrefslogtreecommitdiffstats
path: root/src/lib/kStuff/kProfiler2/prfcore.h.h
blob: d4413d102cd6be76d11fdc38a7c52e4755353f44 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
/* $Id: prfcore.h.h 29 2009-07-01 20:30:29Z bird $ */
/** @file
 * kProfiler Mark 2 - Core Header Template.
 */

/*
 * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */


/** @def KPRF_NAME
 * Mixed case name macro.
 */
#ifndef KPRF_NAME
# define KPRF_NAME(Name)        Name
#endif

/** @def KPRF_TYPE
 * Upper case type name macro.
 */
#ifndef KPRF_TYPE
# define KPRF_TYPE(Prefix,Name) Prefix##Name
#endif

/** @type KPRF_DECL_FUNC
 * The calling convention used.
 */
#ifndef KPRF_DECL_FUNC
# define KPRF_DECL_FUNC(type, name) type name
#endif

/** @def KPRF_BITS
 * The bitsize of the format.
 */
#ifndef KPRF_BITS
# define KPRF_BITS  32
#endif

/** @type UPTR
 * The basic unsigned interger pointer type.
 */
/** @type IPTR
 * The basic signed interger pointer type.
 */
#if KPRF_BITS == 16
typedef KU16    KPRF_TYPE(,UPTR);
typedef KI16    KPRF_TYPE(,IPTR);
#elif KPRF_BITS == 32
typedef KU32    KPRF_TYPE(,UPTR);
typedef KI32    KPRF_TYPE(,IPTR);
#elif KPRF_BITS == 64
typedef KU64    KPRF_TYPE(,UPTR);
typedef KI64    KPRF_TYPE(,IPTR);
#else
# error "KPRF_BITS has an invalid value. Supported values are 16, 32 and 64."
#endif
/** @type KPRF_TYPE(P,UPTR)
 * Pointer to the basic pointer type.
 */
typedef KPRF_TYPE(,UPTR) *KPRF_TYPE(P,UPTR);


/**
 * Various constants.
 */
enum KPRF_TYPE(,CONSTANTS)
{
    /** Magic for the profiler header. (Unix Epoc) */
    KPRF_TYPE(,HDR_MAGIC) = 0x19700101
};


/**
 * The profile data header.
 */
typedef struct KPRF_TYPE(,HDR)
{
    /** [0] The magic number for file data. (KPRF_TYPE(,HDR_MAGIC)) */
    KU32                    u32Magic;
    /** [4] KPRF_BITS. */
    KU32                    cFormatBits;
    /** [8] The base address which all pointers should be relative to. */
    KPRF_TYPE(,UPTR)        uBasePtr;
#if KPRF_BITS <= 16
    /** [a] Reserved. */
    KU16                    u16Reserved;
#endif
#if KPRF_BITS <= 32
    /** [c] Reserved. */
    KU32                    u32Reserved;
#endif
    /** [10] The size of this data set. */
    KU32                    cb;
    /** [10] The allocated data set size. */
    KU32                    cbAllocated;

    /** [18] The max number of functions the function table can hold. */
    KU32                    cMaxFunctions;
    /** [1c] The current number of functions in the function table. */
    KU32                    cFunctions;
    /** [20] The offset of the function table (relative to this header). */
    KU32                    offFunctions;
    /** [24] The size of a function entry. */
    KU32                    cbFunction;

    /** [28] The max number of bytes the module segments can occupy. */
    KU32                    cbMaxModSegs;
    /** [2c] The current size of the module segment records. */
    KU32                    cbModSegs;
    /** [30] The offset of the module segment records (relative to this header). */
    KU32                    offModSegs;

    /** [34] The max number of threads the thread table can contain. */
    KU32                    cMaxThreads;
    /** [38] The current number of threads in the thread table. */
    KU32                    cThreads;
    /** [3c] The offset of the thread table (relative to this header). */
    KU32                    offThreads;
    /** [40] The size of a thread entry. */
    KU32                    cbThread;

    /** [44] The max number of stacks the stack table can contain. */
    KU32                    cMaxStacks;
    /** [48] The max number of stacks.
     * Unlike the other members, the stacks can be reused. It follows that
     * this count doesn't specify the number of used slots from the start. */
    KU32                    cStacks;
    /** [4c] The offset of the thread table (relative to this header).
     * This is usually 0 in a stored data set. */
    KU32                    offStacks;
    /** [50] The size of a stack. */
    KU32                    cbStack;
    /** [54] The maxium stack depth. */
    KU32                    cMaxStackFrames;

    /** [58] The process commandline.
     * Might not always apply is will be 0 in those cases. This is normally written
     * where the stacks used to be.
     */
    KU32                    offCommandLine;
    /** [5c] The length of the command line. (excludes the terminator). */
    KU32                    cchCommandLine;

    /** [60]  The function lookup table (it contains indexes).
     * This is sorted by address so that a binary search can be performed.
     * Access to this table is managed externally, but generally a read/write lock is employed. */
    KU32                    aiFunctions[1];
} KPRF_TYPE(,HDR);
/** Pointer to a profiler data header. */
typedef KPRF_TYPE(,HDR) *KPRF_TYPE(P,HDR);
/** Pointer to a const profiler data header. */
typedef const KPRF_TYPE(,HDR) *KPRF_TYPE(PC,HDR);


/**
 * Time statistics.
 */
typedef struct KPRF_TYPE(,TIMESTAT)      /** @todo bad names and descriptions! */
{
    /** The minimum period */
    KU64 volatile           MinTicks;
    /** The maximum period */
    KU64 volatile           MaxTicks;
    /** The sum of all periods. */
    KU64 volatile           SumTicks;
} KPRF_TYPE(,TIMESTAT);
/** Pointer to time statistics. */
typedef KPRF_TYPE(,TIMESTAT) *KPRF_TYPE(P,TIMESTAT);
/** Pointer to const time statistics. */
typedef const KPRF_TYPE(,TIMESTAT) *KPRF_TYPE(PC,TIMESTAT);


/**
 * A Module Segment.
 */
typedef struct KPRF_TYPE(,MODSEG)
{
    /** The address of the segment. (relative address) */
    KPRF_TYPE(,UPTR)        uBasePtr;
    /** The size of the segment minus one (so the entire address space can be covered). */
    KPRF_TYPE(,UPTR)        cbSegmentMinusOne;
    /** The segment number. (0 based) */
    KU32                    iSegment;
    /** Flag indicating whether this segment is loaded or not.
     * (A 16-bit value was choosen out of convenience, all that's stored is 0 or 1 anyway.) */
    KU16                    fLoaded;
    /** The length of the path.
     * This is used to calculate the length of the record: offsetof(MODSEG, szPath) + cchPath + 1 */
    KU16                    cchPath;
    /** The module name. */
    char                    szPath[1];
} KPRF_TYPE(,MODSEG);
/** Pointer to a module segment. */
typedef KPRF_TYPE(,MODSEG) *KPRF_TYPE(P,MODSEG);
/** Pointer to a const module segment. */
typedef const KPRF_TYPE(,MODSEG) *KPRF_TYPE(PC,MODSEG);


/**
 * The profiler data for a function.
 */
typedef struct KPRF_TYPE(,FUNC)
{
    /** The entry address of the function. (relative address)
     * This is the return address of the entry hook (_mcount, _penter, _ProfileHook32, ...). */
    KPRF_TYPE(,UPTR)        uEntryPtr;
    /** Offset (relative to the profiler header) of the module segment to which this function belongs. */
    KU32                    offModSeg;

    /** The number times on the stack. */
    KU64 volatile           cOnStack;
    /** The number of calls made from this function. */
    KU64 volatile           cCalls;

    /** Time on stack. */
    KPRF_TYPE(,TIMESTAT)    OnStack;
    /** Time on top of the stack, i.e. executing. */
    KPRF_TYPE(,TIMESTAT)    OnTopOfStack;

    /** @todo recursion */

} KPRF_TYPE(,FUNC);
/** Pointer to the profiler data for a function. */
typedef KPRF_TYPE(,FUNC)       *KPRF_TYPE(P,FUNC);
/** Pointer to the const profiler data for a function. */
typedef const KPRF_TYPE(,FUNC) *KPRF_TYPE(PC,FUNC);


/**
 * Stack frame.
 */
typedef struct KPRF_TYPE(,FRAME)
{
    /** The accumulated overhead.
     * Over head is accumulated by the parent frame when a child is poped off the stack. */
    KU64                    OverheadTicks;
    /** The current (top of stack) overhead. */
    KU64                    CurOverheadTicks;
    /** The accumulated sleep ticks.
     * It's possible to notify the profiler that the thread is being put into a wait/sleep/yield
     * state. The time spent sleeping is transfered to the parent frame when poping of a child one. */
    KU64                    SleepTicks;
    /** The start of the on-stack period. */
    KU64                    OnStackStart;
    /** The accumulated time on top (excludes overhead (sleep doesn't apply here obviously)). */
    KU64                    OnTopOfStackTicks;
    /** The start of the current on-top-of-stack period.
     * This is also to mark the start of a sleeping period, the ResumeThread function will always
     * treat it as the start of the suspend period. */
    KU64                    OnTopOfStackStart;
    /** The number of calls made from this stack frame. */
    KU64                    cCalls;
    /** Stack address of this frame.
     * This is used to detect throw and longjmp, and is also used to deal with overflow. (relative address) */
    KPRF_TYPE(,UPTR)        uFramePtr;
    /** Offset (relative to the profiler header) to the function record.
     * This is 0 if we're out of function space. */
    KU32                    offFunction;
} KPRF_TYPE(,FRAME);
/** Pointer to a stack frame. */
typedef KPRF_TYPE(,FRAME) *KPRF_TYPE(P,FRAME);
/** Pointer to a const stack frame. */
typedef const KPRF_TYPE(,FRAME) *KPRF_TYPE(PC,FRAME);


/**
 * Stack.
 */
typedef struct KPRF_TYPE(,STACK)
{
    /** The offset (relative to the profiler header) of the thread owning the stack.
     * This is zero if not in use, and non-zero if in use. */
    KU32                        offThread;
    /** The number of active stack frames. */
    KU32                        cFrames;
    /** The stack frames.
     * The actual size of this array is specified in the header. */
    KPRF_TYPE(,FRAME)           aFrames[1];
} KPRF_TYPE(,STACK);
/** Pointer to a stack. */
typedef KPRF_TYPE(,STACK) *KPRF_TYPE(P,STACK);
/** Pointer to a const stack. */
typedef const KPRF_TYPE(,STACK) *KPRF_TYPE(PC,STACK);


/**
 * The thread state.
 */
typedef enum KPRF_TYPE(,THREADSTATE)
{
    /** The thread hasn't been used yet. */
    KPRF_TYPE(,THREADSTATE_UNUSED) = 0,
    /** The thread is activly being profiled.
     * A thread is added in the suspended state and then activated when
     * starting to execute the first function.
     */
    KPRF_TYPE(,THREADSTATE_ACTIVE),
    /** The thread is currently suspended from profiling.
     * Upon entering profiler code the thread is suspended, it's reactivated
     * upon normal return.
     */
    KPRF_TYPE(,THREADSTATE_SUSPENDED),
    /** The thread is currently suspended due of stack overflow.
     * When we overflow the stack frame array, the thread enter the overflow state. In this
     * state nothing is profiled but we keep looking for the exit of the top frame. */
    KPRF_TYPE(,THREADSTATE_OVERFLOWED),
    /** The thread is terminated.
     * When we received a thread termination notification the thread is unwinded, statistics
     * updated and the state changed to terminated. A terminated thread cannot be revivied. */
    KPRF_TYPE(,THREADSTATE_TERMINATED),

    /** Ensure 32-bit size. */
    KPRF_TYPE(,THREADSTATE_32BIT_HACK) = 0x7fffffff
} KPRF_TYPE(,THREADSTATE);


/**
 * Thread statistics and stack.
 */
typedef struct KPRF_TYPE(,THREAD)
{
    /** The native thread id. */
    KU64                        ThreadId;
    /** The thread name. (optional) */
    char                        szName[32];
    /** The thread current thread state. */
    KPRF_TYPE(,THREADSTATE)     enmState;
    /** Alignment. */
    KPRF_TYPE(,THREADSTATE)     Reserved0;
    /** The base pointer of the thread stack. (relative address) */
    KPRF_TYPE(,UPTR)            uStackBasePtr;
    /** The maximum depth of the thread stack (bytes). */
    KPRF_TYPE(,UPTR)            cbMaxStack;
    /** The number of calls done by this thread. */
    KU64                        cCalls;
    /** The number of times the stack overflowed. */
    KU64                        cOverflows;
    /** The number of times stack entries has been rejected because of a stack switch. */
    KU64                        cStackSwitchRejects;
    /** The number of times the stack has been unwinded more than one frame. */
    KU64                        cUnwinds;

    /** The profiled ticks. (This does not include sleep or overhead ticks.)
     * This is the accumulated on-stack values for the final stack frames. */
    KU64                        ProfiledTicks;
    /** The accumulated overhead of this thread. */
    KU64                        OverheadTicks;
    /** The accumulated sleep ticks for this thread.
     * See KPRF_TYPE(,FRAME)::SleepTicks for details. */
    KU64                        SleepTicks;

    /** The offset of the stack. */
    KU32                        offStack;
} KPRF_TYPE(,THREAD);
/** Pointer to a thread. */
typedef KPRF_TYPE(,THREAD) *KPRF_TYPE(P,THREAD);
/** Pointer to a const thread. */
typedef const KPRF_TYPE(,THREAD) *KPRF_TYPE(PC,THREAD);