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