]> git.saurik.com Git - apple/xnu.git/blame - osfmk/profiling/i386/profile-md.h
xnu-792.6.56.tar.gz
[apple/xnu.git] / osfmk / profiling / i386 / profile-md.h
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
ff6e181a
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
1c79356b 12 *
ff6e181a
A
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
ff6e181a
A
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
1c79356b
A
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*
24 * @OSF_COPYRIGHT@
25 */
26/*
27 * HISTORY
28 *
29 * Revision 1.1.1.1 1998/09/22 21:05:49 wsanchez
30 * Import of Mac OS X kernel (~semeria)
31 *
32 * Revision 1.1.1.1 1998/03/07 02:26:08 wsanchez
33 * Import of OSF Mach kernel (~mburg)
34 *
35 * Revision 1.1.5.2 1996/07/31 09:57:36 paire
36 * Added some more constraints to __asm__ functions for compilation
37 * under gcc2.7.1 for PROF_CNT_[L]{ADD|SUB} macros
38 * [96/06/14 paire]
39 *
40 * Revision 1.1.5.1 1995/01/06 19:53:52 devrcs
41 * mk6 CR668 - 1.3b26 merge
42 * new file for mk6
43 * [1994/10/12 22:25:27 dwm]
44 *
45 * Revision 1.1.2.2 1994/05/16 19:19:26 meissner
46 * Add {,L}PROF_CNT_{SUB,LSUB,OVERFLOW} macros for gprof command.
47 * [1994/05/10 10:36:06 meissner]
48 *
49 * Correct 64-bit integer asms to specify result values as inputs, and use =g instead of =m.
50 * Cast the integer argument to PROF_CNT_ADD to unsigned long, so a short register is widened.
51 * Add more support for writing the gprof command.
52 * PROF_CNT_{EQ,NE} should not use ^=, it just uses ^.
53 * Round PROF_CNT_DIGITS up to 24 bytes so it is word aligned.
54 * _profile_cnt_to_decimal now takes the low/high values as separate arguments.
55 * Delete _profile_cnt_to_hex.
56 * [1994/04/28 21:45:07 meissner]
57 *
58 * Add more 64 bit arithmetic macros to support writing gprof.
59 * [1994/04/20 15:47:05 meissner]
60 *
61 * Revision 1.1.2.1 1994/04/08 17:51:56 meissner
62 * Correct spelling on LPROF_CNT_TO_LDOUBLE macro.
63 * [1994/04/08 16:18:06 meissner]
64 *
65 * Make LHISTCOUNTER be 64 bits.
66 * Define LPROF_CNT_INC to increment LHISTCOUNTER.
67 * [1994/04/08 12:40:32 meissner]
68 *
69 * Make most stats 64 bits, except for things like memory allocation.
70 * [1994/04/02 14:58:34 meissner]
71 *
72 * Add overflow support for {gprof,prof,old,dummy}_mcount counters.
73 * [1994/03/17 20:13:37 meissner]
74 *
75 * Add gprof/prof overflow support
76 * [1994/03/17 14:56:56 meissner]
77 *
78 * Define LHISTCOUNTER.
79 * [1994/02/28 12:05:16 meissner]
80 *
81 * Set HISTFRACTION to 4, so new lprofil call takes the same space.
82 * [1994/02/24 16:15:34 meissner]
83 *
84 * Add too_low/too_high to profile_stats.
85 * [1994/02/16 22:38:23 meissner]
86 *
87 * Make prof_cnt_t unsigned long.
88 * [1994/02/11 16:52:09 meissner]
89 *
90 * Remember function unique ptr in gfuncs structure to reset profiling.
91 * Add support for range checking gprof arc {from,self}pc addresses.
92 * Add counter for # times acontext was locked.
93 * Expand copyright.
94 * [1994/02/07 12:41:08 meissner]
95 *
96 * Keep track of the number of times the kernel overflows the HISTCOUNTER counter.
97 * [1994/02/03 20:13:31 meissner]
98 *
99 * Add stats for {user,kernel,idle} mode in the kernel.
100 * [1994/02/03 15:17:36 meissner]
101 *
102 * No change.
103 * [1994/02/03 00:58:59 meissner]
104 *
105 * Combine _profile_{vars,stats,md}; Allow more than one _profile_vars.
106 * [1994/02/01 12:04:04 meissner]
107 *
108 * Split # records to # gprof and # prof records.
109 * Add my_cpu/max_cpu fields.
110 * [1994/01/28 23:33:30 meissner]
111 *
112 * Eliminate hash_{size,mask} from gfuncs structure.
113 * [1994/01/26 20:23:41 meissner]
114 *
115 * Add structure size fields to _profile_{vars,stats,md}.
116 * Add major/minor version number to _profile_md.
117 * Move allocation context block pointer to main structure.
118 * Delete shift count for allocation contexts.
119 * [1994/01/25 01:46:08 meissner]
120 *
121 * Add HASHFRACTION
122 * [1994/01/22 01:14:02 meissner]
123 *
124 * Split profile-md.h into profile-internal.h and profile-md.
125 * [1994/01/20 20:57:18 meissner]
126 *
127 * Fixup copyright.
128 * [1994/01/18 23:08:14 meissner]
129 *
130 * Make flags byte-sized.
131 * Add have_bb flag.
132 * Add init_format flag.
133 * [1994/01/18 21:57:18 meissner]
134 *
135 * CR 10198 - Initial version.
136 * [1994/01/18 19:44:59 meissner]
137 *
138 * $EndLog$
139 */
140
141#ifndef _PROFILE_MD_H
142#define _PROFILE_MD_H
143
55e303ae
A
144#include <types.h>
145
1c79356b
A
146/*
147 * Define the interfaces between the assembly language profiling support
148 * that is common between the kernel, mach servers, and user space library.
149 */
150
151/*
152 * Integer types used.
153 */
154
155typedef long prof_ptrint_t; /* hold either pointer or signed int */
156typedef unsigned long prof_uptrint_t; /* hold either pointer or unsigned int */
157typedef long prof_lock_t; /* lock word type */
158typedef unsigned char prof_flag_t; /* type for boolean flags */
159
160/*
161 * Double precision counter.
162 */
163
164typedef struct prof_cnt_t {
165 prof_uptrint_t low; /* low 32 bits of counter */
166 prof_uptrint_t high; /* high 32 bits of counter */
167} prof_cnt_t;
168
169#if defined(__GNUC__) && !defined(lint)
170#define PROF_CNT_INC(cnt) \
171 __asm__("addl $1,%0; adcl $0,%1" \
172 : "=g" ((cnt).low), "=g" ((cnt).high) \
173 : "0" ((cnt).low), "1" ((cnt).high))
174
175#define PROF_CNT_ADD(cnt,val) \
176 __asm__("addl %2,%0; adcl $0,%1" \
177 : "=g,r" ((cnt).low), "=g,r" ((cnt).high) \
178 : "r,g" ((unsigned long)(val)), \
179 "0,0" ((cnt).low), "1,1" ((cnt).high))
180
181#define PROF_CNT_LADD(cnt,val) \
182 __asm__("addl %2,%0; adcl %3,%1" \
183 : "=g,r" ((cnt).low), "=g,r" ((cnt).high) \
184 : "r,g" ((val).low), "r,g" ((val).high), \
185 "0,0" ((cnt).low), "1,1" ((cnt).high))
186
187#define PROF_CNT_SUB(cnt,val) \
188 __asm__("subl %2,%0; sbbl $0,%1" \
189 : "=g,r" ((cnt).low), "=g,r" ((cnt).high) \
190 : "r,g" ((unsigned long)(val)), \
191 "0,0" ((cnt).low), "1,1" ((cnt).high))
192
193#define PROF_CNT_LSUB(cnt,val) \
194 __asm__("subl %2,%0; sbbl %3,%1" \
195 : "=g,r" ((cnt).low), "=g,r" ((cnt).high) \
196 : "r,g" ((val).low), "r,g" ((val).high), \
197 "0,0" ((cnt).low), "1,1" ((cnt).high))
198
199#else
200#define PROF_CNT_INC(cnt) ((++((cnt).low) == 0) ? ++((cnt).high) : 0)
201#define PROF_CNT_ADD(cnt,val) (((((cnt).low + (val)) < (val)) ? ((cnt).high++) : 0), ((cnt).low += (val)))
202#define PROF_CNT_LADD(cnt,val) (PROF_CNT_ADD(cnt,(val).low), (cnt).high += (val).high)
203#define PROF_CNT_SUB(cnt,val) (((((cnt).low - (val)) > (cnt).low) ? ((cnt).high--) : 0), ((cnt).low -= (val)))
204#define PROF_CNT_LSUB(cnt,val) (PROF_CNT_SUB(cnt,(val).low), (cnt).high -= (val).high)
205#endif
206
207#define PROF_ULONG_TO_CNT(cnt,val) (((cnt).high = 0), ((cnt).low = val))
208#define PROF_CNT_OVERFLOW(cnt,high,low) (((high) = (cnt).high), ((low) = (cnt).low))
209#define PROF_CNT_TO_ULONG(cnt) (((cnt).high == 0) ? (cnt).low : 0xffffffffu)
210#define PROF_CNT_TO_LDOUBLE(cnt) ((((long double)(cnt).high) * 4294967296.0L) + (long double)(cnt).low)
211#define PROF_CNT_TO_DECIMAL(buf,cnt) _profile_cnt_to_decimal(buf, (cnt).low, (cnt).high)
212#define PROF_CNT_EQ_0(cnt) (((cnt).high | (cnt).low) == 0)
213#define PROF_CNT_NE_0(cnt) (((cnt).high | (cnt).low) != 0)
214#define PROF_CNT_EQ(cnt1,cnt2) ((((cnt1).high ^ (cnt2).high) | ((cnt1).low ^ (cnt2).low)) == 0)
215#define PROF_CNT_NE(cnt1,cnt2) ((((cnt1).high ^ (cnt2).high) | ((cnt1).low ^ (cnt2).low)) != 0)
216#define PROF_CNT_GT(cnt1,cnt2) (((cnt1).high > (cnt2).high) || ((cnt1).low > (cnt2).low))
217#define PROF_CNT_LT(cnt1,cnt2) (((cnt1).high < (cnt2).high) || ((cnt1).low < (cnt2).low))
218
219/* max # digits + null to hold prof_cnt_t values (round up to multiple of 4) */
220#define PROF_CNT_DIGITS 24
221
222/*
223 * Types of the profil counter.
224 */
225
226typedef unsigned short HISTCOUNTER; /* profil */
227typedef prof_cnt_t LHISTCOUNTER; /* lprofil */
228
229#define LPROF_ULONG_TO_CNT(cnt,val) PROF_ULONG_TO_CNT(cnt,val)
230#define LPROF_CNT_INC(lp) PROF_CNT_INC(lp)
231#define LPROF_CNT_ADD(lp,val) PROF_CNT_ADD(lp,val)
232#define LPROF_CNT_LADD(lp,val) PROF_CNT_LADD(lp,val)
233#define LPROF_CNT_SUB(lp,val) PROF_CNT_SUB(lp,val)
234#define LPROF_CNT_LSUB(lp,val) PROF_CNT_LSUB(lp,val)
235#define LPROF_CNT_OVERFLOW(lp,high,low) PROF_CNT_OVERFLOW(lp,high,low)
236#define LPROF_CNT_TO_ULONG(lp) PROF_CNT_TO_ULONG(lp)
237#define LPROF_CNT_TO_LDOUBLE(lp) PROF_CNT_TO_LDOUBLE(lp)
238#define LPROF_CNT_TO_DECIMAL(buf,cnt) PROF_CNT_TO_DECIMAL(buf,cnt)
239#define LPROF_CNT_EQ_0(cnt) PROF_CNT_EQ_0(cnt)
240#define LPROF_CNT_NE_0(cnt) PROF_CNT_NE_0(cnt)
241#define LPROF_CNT_EQ(cnt1,cnt2) PROF_CNT_EQ(cnt1,cnt2)
242#define LPROF_CNT_NE(cnt1,cnt2) PROF_CNT_NE(cnt1,cnt2)
243#define LPROF_CNT_GT(cnt1,cnt2) PROF_CNT_GT(cnt1,cnt2)
244#define LPROF_CNT_LT(cnt1,cnt2) PROF_CNT_LT(cnt1,cnt2)
245#define LPROF_CNT_DIGITS PROF_CNT_DIGITS
246
247/*
248 * fraction of text space to allocate for histogram counters
249 */
250
251#define HISTFRACTION 4
252
253/*
254 * Fraction of text space to allocate for from hash buckets.
255 */
256
257#define HASHFRACTION HISTFRACTION
258
259/*
260 * Prof call count, external format.
261 */
262
263struct prof_ext {
264 prof_uptrint_t cvalue; /* caller address */
265 prof_uptrint_t cncall; /* # of calls */
266};
267
268/*
269 * Prof call count, internal format.
270 */
271
272struct prof_int {
273 struct prof_ext prof; /* external prof struct */
274 prof_uptrint_t overflow; /* # times prof counter overflowed */
275};
276
277/*
278 * Gprof arc, external format.
279 */
280
281struct gprof_arc {
282 prof_uptrint_t frompc; /* caller's caller */
283 prof_uptrint_t selfpc; /* caller's address */
284 prof_uptrint_t count; /* # times arc traversed */
285};
286
287/*
288 * Gprof arc, internal format.
289 */
290
291struct hasharc {
292 struct hasharc *next; /* next gprof record */
293 struct gprof_arc arc; /* gprof record */
294 prof_uptrint_t overflow; /* # times counter overflowed */
295};
296
297/*
298 * Linked list of all function profile blocks.
299 */
300
301#define MAX_CACHE 3 /* # cache table entries */
302
303struct gfuncs {
304 struct hasharc **hash_ptr; /* gprof hash table */
305 struct hasharc **unique_ptr; /* function unique pointer */
306 struct prof_int prof; /* -p stats for elf */
307 struct hasharc *cache_ptr[MAX_CACHE]; /* cache element pointers */
308};
309
310/*
311 * Profile information which might be written out in ELF {,g}mon.out files.
312 */
313
314#define MAX_BUCKETS 9 /* max bucket chain to print out */
315
316struct profile_stats { /* Debugging counters */
317 prof_uptrint_t major_version; /* major version number */
318 prof_uptrint_t minor_version; /* minor version number */
319 prof_uptrint_t stats_size; /* size of profile_vars structure */
320 prof_uptrint_t profil_buckets; /* # profil buckets */
321 prof_uptrint_t my_cpu; /* identify current cpu/thread */
322 prof_uptrint_t max_cpu; /* identify max cpu/thread */
323 prof_uptrint_t prof_records; /* # of functions profiled */
324 prof_uptrint_t gprof_records; /* # of gprof arcs */
325 prof_uptrint_t hash_buckets; /* # gprof hash buckets */
326 prof_uptrint_t bogus_count; /* # of bogus functions found in gprof */
327
328 prof_cnt_t cnt; /* # of calls to _{,g}prof_mcount */
329 prof_cnt_t dummy; /* # of calls to _dummy_mcount */
330 prof_cnt_t old_mcount; /* # of calls to old mcount */
331 prof_cnt_t hash_search; /* # hash buckets searched */
332 prof_cnt_t hash_num; /* # times hash table searched */
333 prof_cnt_t user_ticks; /* # ticks in user space */
334 prof_cnt_t kernel_ticks; /* # ticks in kernel space */
335 prof_cnt_t idle_ticks; /* # ticks in idle mode */
336 prof_cnt_t overflow_ticks; /* # ticks where HISTCOUNTER overflowed */
337 prof_cnt_t acontext_locked; /* # times an acontext was locked */
338 prof_cnt_t too_low; /* # times a histogram tick was too low */
339 prof_cnt_t too_high; /* # times a histogram tick was too high */
340 prof_cnt_t prof_overflow; /* # times a prof count field overflowed */
341 prof_cnt_t gprof_overflow; /* # times a gprof count field overflowed */
342
343 /* allocation statistics */
344 prof_uptrint_t num_alloc [(int)ACONTEXT_MAX]; /* # allocations */
345 prof_uptrint_t bytes_alloc[(int)ACONTEXT_MAX]; /* bytes allocated */
346 prof_uptrint_t num_context[(int)ACONTEXT_MAX]; /* # contexts */
347 prof_uptrint_t wasted [(int)ACONTEXT_MAX]; /* wasted bytes */
348 prof_uptrint_t overhead [(int)ACONTEXT_MAX]; /* overhead bytes */
349
350 prof_uptrint_t buckets[MAX_BUCKETS+1]; /* # hash indexes that have n buckets */
351 prof_cnt_t cache_hits[MAX_CACHE]; /* # times nth cache entry matched */
352
353 prof_cnt_t stats_unused[64]; /* reserved for future use */
354};
355
356#define PROFILE_MAJOR_VERSION 1
357#define PROFILE_MINOR_VERSION 1
358
359/*
360 * Machine dependent fields.
361 */
362
363struct profile_md {
364 int major_version; /* major version number */
365 int minor_version; /* minor version number */
366 size_t md_size; /* size of profile_md structure */
367 struct hasharc **hash_ptr; /* gprof hash table */
368 size_t hash_size; /* size of hash table */
369 prof_uptrint_t num_cache; /* # of cache entries */
370 void (*save_mcount_ptr)(void); /* save for _mcount_ptr */
371 void (**mcount_ptr_ptr)(void); /* pointer to _mcount_ptr */
372 struct hasharc *dummy_ptr; /* pointer to dummy gprof record */
373 void *(*alloc_pages)(size_t); /* pointer to _profile_alloc_pages */
374 char num_buffer[PROF_CNT_DIGITS]; /* convert 64 bit ints to string */
375 long md_unused[58]; /* add unused fields */
376};
377
378/*
379 * Record information about each function call. Specify
380 * caller, caller's caller, and a unique label for use by
381 * the profiling routines.
382 */
383extern void _prof_mcount(void);
384extern void _gprof_mcount(void);
385extern void _dummy_mcount(void);
386extern void (*_mcount_ptr)(void);
387
388/*
389 * Function in profile-md.c to convert prof_cnt_t to string format (decimal & hex).
390 */
391extern char *_profile_cnt_to_decimal(char *, prof_uptrint_t, prof_uptrint_t);
392
393#endif /* _PROFILE_MD_H */