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