Annotation of XNU/osfmk/profiling/i386/profile-md.c, revision 1.1.1.1

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.1  1995/01/06  19:53:45  devrcs
                     35:  *     mk6 CR668 - 1.3b26 merge
                     36:  *     new file for mk6
                     37:  *     [1994/10/12  22:25:24  dwm]
                     38:  *
                     39:  * Revision 1.1.2.2  1994/05/16  19:19:22  meissner
                     40:  *     Protect against hash_ptr being null in _profile_update_stats.
                     41:  *     [1994/05/16  17:23:53  meissner]
                     42:  * 
                     43:  *     Remove _profile_cnt_to_hex, _profile_strbuffer.
                     44:  *     _profile_print_stats now takes const pointers.
                     45:  *     Use the new 64-bit arithmetic support instead of converting to double.
                     46:  *     Add _profile_merge_stats to merge statistics.
                     47:  *     [1994/04/28  21:45:04  meissner]
                     48:  * 
                     49:  *     If MACH_ASSERT is on in server or kernel, turn on profiling printfs.
                     50:  *     Print out fractional digits for average # of hash searches in stats.
                     51:  *     Update overflow_ticks for # times the lprofil counter overflows into high word.
                     52:  *     Don't make sizes of C/asm structures a const array, since it has pointers in it.
                     53:  *     Add support for converting 64 bit ints to a string.
                     54:  *     Use PROF_CNT_TO_DECIMAL where possible instead of PROF_CNT_TO_LDOUBLE.
                     55:  *     [1994/04/20  15:47:02  meissner]
                     56:  * 
                     57:  * Revision 1.1.2.1  1994/04/08  17:51:51  meissner
                     58:  *     no change
                     59:  *     [1994/04/08  02:11:40  meissner]
                     60:  * 
                     61:  *     Make most stats 64 bits, except for things like memory allocation.
                     62:  *     [1994/04/02  14:58:28  meissner]
                     63:  * 
                     64:  *     Add some printfs under #idef DEBUG_PROFILE.
                     65:  *     [1994/03/29  21:00:11  meissner]
                     66:  * 
                     67:  *     Further changes for gprof/prof overflow support.
                     68:  *     Add overflow support for {gprof,prof,old,dummy}_mcount counters.
                     69:  *     [1994/03/17  20:13:31  meissner]
                     70:  * 
                     71:  *     Add gprof/prof overflow support
                     72:  *     [1994/03/17  14:56:51  meissner]
                     73:  * 
                     74:  *     Use memset instead of bzero.
                     75:  *     [1994/02/28  23:56:10  meissner]
                     76:  * 
                     77:  *     Add size of histogram counters & unused fields to profile_profil struct
                     78:  *     [1994/02/17  21:41:50  meissner]
                     79:  * 
                     80:  *     Allocate slop space for server in addition to microkernel.
                     81:  *     Add 3rd argument to _profile_print_stats for profil info.
                     82:  *     Print # histogram ticks too low/too high for server/mk.
                     83:  *     [1994/02/16  22:38:18  meissner]
                     84:  * 
                     85:  *     Calculate percentages for # of hash buckets.
                     86:  *     [1994/02/11  16:52:04  meissner]
                     87:  * 
                     88:  *     Print stats as an unsigned number.
                     89:  *     [1994/02/07  18:47:05  meissner]
                     90:  * 
                     91:  *     For kernel and server, include <kern/assert.h> not <assert.h>.
                     92:  *     Always do assert on comparing asm vs. C structure sizes.
                     93:  *     Add _profile_reset to reset profiling information.
                     94:  *     Add _profile_update_stats to update the statistics.
                     95:  *     Move _gprof_write code that updates hash stats to _profile_update_stats.
                     96:  *     Don't allocate space for basic block support just yet.
                     97:  *     Add support for range checking the gprof arc {from,self}pc addresses.
                     98:  *     _profile_debug now calls _profile_update_stats.
                     99:  *     Print how many times the acontext was locked.
                    100:  *     If DEBUG_PROFILE is defined, set pv->debug to 1.
                    101:  *     Expand copyright.
                    102:  *     [1994/02/07  12:41:03  meissner]
                    103:  * 
                    104:  *     Keep track of the number of times the kernel overflows the HISTCOUNTER counter.
                    105:  *     [1994/02/03  20:13:28  meissner]
                    106:  * 
                    107:  *     Add stats for {user,kernel,idle} mode in the kernel.
                    108:  *     [1994/02/03  15:17:31  meissner]
                    109:  * 
                    110:  *     Print unused stats in hex as well as decimal.
                    111:  *     [1994/02/03  14:52:20  meissner]
                    112:  * 
                    113:  *     _profile_print_stats no longer takes profile_{vars,md} pointer arguments.
                    114:  *     If stream is NULL, _profile_print_stats will use stdout.
                    115:  *     Separate _profile_update_stats from _gprof_write.
                    116:  *     [1994/02/03  00:58:55  meissner]
                    117:  * 
                    118:  *     Combine _profile_{vars,stats,md}; Allow more than one _profile_vars.
                    119:  *     [1994/02/01  12:04:01  meissner]
                    120:  * 
                    121:  *     Add allocation flag to _profile_md_init.
                    122:  *     Fix core dumps in _profile_print_stats if no profile_vars ptr passed.
                    123:  *     Print numbers in 12 columns, not 8.
                    124:  *     Print my_cpu/max_cpu if max_cpu != 0.
                    125:  *     Make allocations print like other stats.
                    126:  *     Use ACONTEXT_FIRST to start loop on, not ACONTEXT_PROF.
                    127:  *     [1994/01/28  23:33:26  meissner]
                    128:  * 
                    129:  *     Move callback pointers into separate allocation context.
                    130:  *     Add size fields for other structures to profile-vars.
                    131:  *     [1994/01/26  20:23:37  meissner]
                    132:  * 
                    133:  *     Allocate initial memory at startup.
                    134:  *     Print structure sizes and version number when printing stats.
                    135:  *     Initialize size fields and version numbers.
                    136:  *     Allocation context pointers moved to _profile_vars.
                    137:  *     [1994/01/25  01:46:04  meissner]
                    138:  * 
                    139:  *     Move init code here from assembly language.
                    140:  *     [1994/01/22  01:13:21  meissner]
                    141:  * 
                    142:  *     Include <profile/profile-internal.h> instead of "profile-md.h".
                    143:  *     [1994/01/20  20:56:49  meissner]
                    144:  * 
                    145:  *     Fixup copyright.
                    146:  *     [1994/01/18  23:08:02  meissner]
                    147:  * 
                    148:  *     Rename profile.h -> profile-md.h.
                    149:  *     [1994/01/18  19:44:57  meissner]
                    150:  * 
                    151:  *     Write out stats unused fields.
                    152:  *     Make _prof_write write out the prof stats gprof collects.
                    153:  *     [1994/01/15  18:40:37  meissner]
                    154:  * 
                    155:  *     Remove debug code called from profile-asm.s.
                    156:  *     Always print out the # of profil buckets.
                    157:  *     [1994/01/15  00:59:06  meissner]
                    158:  * 
                    159:  *     Fix typo.
                    160:  *     [1994/01/04  16:34:46  meissner]
                    161:  * 
                    162:  *     Move max hash bucket calculation into _gprof_write & put info in stats structure.
                    163:  *     [1994/01/04  16:15:17  meissner]
                    164:  * 
                    165:  *     Use _profile_printf to write diagnostics; add diag_stream to hold stream to write to.
                    166:  *     [1994/01/04  15:37:46  meissner]
                    167:  * 
                    168:  *     Correctly handle case where more than one allocation context was
                    169:  *     allocated due to multiple threads.
                    170:  *     Cast stats to long for output.
                    171:  *     Print number of profil buckets field in _profile_stats.
                    172:  *     Add support for GFUNC allocation context.
                    173:  *     [1994/01/04  14:26:00  meissner]
                    174:  * 
                    175:  *     CR 10198 - Initial version.
                    176:  *     [1994/01/01  22:44:10  meissne
                    177:  * 
                    178:  * $EndLog$
                    179:  */
                    180: 
                    181: #include <profiling/profile-internal.h>
                    182: #include <stdlib.h>
                    183: #include <string.h>
                    184: 
                    185: #if defined(MACH_KERNEL) || defined(_KERNEL)
                    186: 
                    187: #include <mach_assert.h>
                    188: #if MACH_ASSERT && !defined(DEBUG_PROFILE)
                    189: #define DEBUG_PROFILE 1
                    190: #endif
                    191: 
                    192: extern int printf(const char *, ...);
                    193: extern void panic(const char *);
                    194: #else
                    195: #include <assert.h>
                    196: #define panic(str) exit(1)
                    197: #endif
                    198: 
                    199: #ifndef PROFILE_NUM_FUNCS
                    200: #define        PROFILE_NUM_FUNCS       2000
                    201: #endif
                    202: 
                    203: #ifndef PROFILE_NUM_ARCS
                    204: #define        PROFILE_NUM_ARCS        8000
                    205: #endif
                    206: 
                    207: /*
                    208:  * Information passed on from profile-asm.s
                    209:  */
                    210: 
                    211: extern int _profile_do_stats;
                    212: extern size_t _profile_size;
                    213: extern size_t _profile_stats_size;
                    214: extern size_t _profile_md_size;
                    215: extern size_t _profile_profil_size;
                    216: extern size_t _profile_hash_size;
                    217: 
                    218: /*
                    219:  * All profiling variables, and a dummy gprof record.
                    220:  */
                    221: 
                    222: struct profile_vars _profile_vars = { 0 };
                    223: struct hasharc _gprof_dummy = { 0 };
                    224: 
                    225: /*
                    226:  * Forward references.
                    227:  */
                    228: 
                    229: static void *_profile_md_acontext(struct profile_vars *pv,
                    230:                                  void *ptr,
                    231:                                  size_t len,
                    232:                                  acontext_type_t type);
                    233: 
                    234: static void _profile_reset_alloc(struct profile_vars *,
                    235:                                 acontext_type_t);
                    236: 
                    237: extern void _bogus_function(void);
                    238: 
                    239: /*
                    240:  * Function to set up the initial allocation for a context block.
                    241:  */
                    242: 
                    243: static void *
                    244: _profile_md_acontext(struct profile_vars *pv,
                    245:                     void *ptr,
                    246:                     size_t len,
                    247:                     acontext_type_t type)
                    248: {
                    249:        struct memory {
                    250:                struct alloc_context context;
                    251:                struct page_list plist;
                    252:                int data[1];
                    253:        };
                    254: 
                    255:        struct memory *mptr = (struct memory *)ptr;
                    256:        struct alloc_context *context = &mptr->context;
                    257:        struct page_list *plist = &mptr->plist;
                    258: 
                    259: #ifdef DEBUG_PROFILE
                    260:        _profile_printf("_profile_md_acontext: pv= 0x%lx, ptr= 0x%lx, len= %6ld, type= %d\n",
                    261:                        (long)pv,
                    262:                        (long)ptr,
                    263:                        (long)len,
                    264:                        (int)type);
                    265: #endif
                    266: 
                    267:        /* Fill in context block header */
                    268:        context->next = pv->acontext[type];
                    269:        context->plist = plist;
                    270:        context->lock = 0;
                    271: 
                    272:        /* Fill in first page list information */
                    273:        plist->ptr = plist->first = (void *)&mptr->data[0];
                    274:        plist->next = (struct page_list *)0;
                    275:        plist->bytes_free = len - ((char *)plist->ptr - (char *)ptr);
                    276:        plist->bytes_allocated = 0;
                    277:        plist->num_allocations = 0;
                    278: 
                    279:        /* Update statistics */
                    280:        pv->stats.num_context[type]++;
                    281:        pv->stats.wasted[type] += plist->bytes_free;
                    282:        pv->stats.overhead[type] += len - plist->bytes_free;
                    283: 
                    284:        /* And setup context block */
                    285:        pv->acontext[type] = context;
                    286: 
                    287:        return (void *)((char *)ptr+len);
                    288: }
                    289: 
                    290: 
                    291: /*
                    292:  * Machine dependent function to initialize things.
                    293:  */
                    294: 
                    295: void
                    296: _profile_md_init(struct profile_vars *pv,
                    297:                 profile_type_t type,
                    298:                 profile_alloc_mem_t alloc_mem)
                    299: {
                    300:        size_t page_size = pv->page_size;
                    301:        size_t arc_size;
                    302:        size_t func_size;
                    303:        size_t misc_size;
                    304:        size_t hash_size;
                    305:        size_t extra_arc_size;
                    306:        size_t extra_func_size;
                    307:        size_t callback_size = page_size;
                    308:        void *ptr;
                    309:        acontext_type_t ac;
                    310:        int i;
                    311:        static struct {
                    312:                size_t      c_size;             /* size C thinks structure is */
                    313:                size_t     *asm_size_ptr;       /* pointer to size asm thinks struct is */
                    314:                const char *name;               /* structure name */
                    315:        } sizes[] = {
                    316:                { sizeof(struct profile_profil), &_profile_profil_size, "profile_profil" },
                    317:                { sizeof(struct profile_stats),  &_profile_stats_size,  "profile_stats" },
                    318:                { sizeof(struct profile_md),     &_profile_md_size,     "profile_md" },
                    319:                { sizeof(struct profile_vars),   &_profile_size,        "profile_vars" }};
                    320: 
                    321: #ifdef DEBUG_PROFILE
                    322:        _profile_printf("_profile_md_init: pv = 0x%lx, type = %d, alloc = %d\n",
                    323:                        (long) pv,
                    324:                        (int)type,
                    325:                        (int)alloc_mem);
                    326: #endif
                    327: 
                    328:        for (i = 0; i < sizeof (sizes) / sizeof(sizes[0]); i++) {
                    329:                if (sizes[i].c_size != *sizes[i].asm_size_ptr) {
                    330:                        _profile_printf("C thinks struct %s is %ld bytes, asm thinks it is %ld bytes\n",
                    331:                                        sizes[i].name,
                    332:                                        (long)sizes[i].c_size,
                    333:                                        (long)*sizes[i].asm_size_ptr);
                    334: 
                    335:                        panic(sizes[i].name);
                    336:                }
                    337:        }
                    338: 
                    339:        /* Figure out which function will handle compiler generated profiling */
                    340:        if (type == PROFILE_GPROF) {
                    341:                pv->md.save_mcount_ptr = _gprof_mcount;
                    342: 
                    343:        } else if (type == PROFILE_PROF) {
                    344:                pv->md.save_mcount_ptr = _prof_mcount;
                    345: 
                    346:        } else {
                    347:                pv->md.save_mcount_ptr = _dummy_mcount;
                    348:        }
                    349: 
                    350:        pv->vars_size         = sizeof(struct profile_vars);
                    351:        pv->plist_size        = sizeof(struct page_list);
                    352:        pv->acontext_size     = sizeof(struct alloc_context);
                    353:        pv->callback_size     = sizeof(struct callback);
                    354:        pv->major_version     = PROFILE_MAJOR_VERSION;
                    355:        pv->minor_version     = PROFILE_MINOR_VERSION;
                    356:        pv->type              = type;
                    357:        pv->do_profile        = 1;
                    358:        pv->use_dci           = 1;
                    359:        pv->use_profil        = 1;
                    360:        pv->output_uarea      = 1;
                    361:        pv->output_stats      = (prof_flag_t) _profile_do_stats;
                    362:        pv->output_clock      = 1;
                    363:        pv->multiple_sections = 1;
                    364:        pv->init_format       = 0;
                    365:        pv->bogus_func        = _bogus_function;
                    366: 
                    367: #ifdef DEBUG_PROFILE
                    368:        pv->debug             = 1;
                    369: #endif
                    370: 
                    371:        if (!pv->error_msg) {
                    372:                pv->error_msg = "error in profiling";
                    373:        }
                    374: 
                    375:        if (!pv->page_size) {
                    376:                pv->page_size = 4096;
                    377:        }
                    378: 
                    379:        pv->stats.stats_size    = sizeof(struct profile_stats);
                    380:        pv->stats.major_version = PROFILE_MAJOR_VERSION;
                    381:        pv->stats.minor_version = PROFILE_MINOR_VERSION;
                    382: 
                    383:        pv->md.md_size         = sizeof(struct profile_md);
                    384:        pv->md.major_version   = PROFILE_MAJOR_VERSION;
                    385:        pv->md.minor_version   = PROFILE_MINOR_VERSION;
                    386:        pv->md.hash_size       = _profile_hash_size;
                    387:        pv->md.num_cache       = MAX_CACHE;
                    388:        pv->md.mcount_ptr_ptr  = &_mcount_ptr;
                    389:        pv->md.dummy_ptr       = &_gprof_dummy;
                    390:        pv->md.alloc_pages     = _profile_alloc_pages;
                    391: 
                    392:        /* zero out all allocation context blocks */
                    393:        for (ac = ACONTEXT_FIRST; ac < ACONTEXT_MAX; ac++) {
                    394:                pv->acontext[ac] = (struct alloc_context *)0;
                    395:        }
                    396: 
                    397:        /* Don't allocate memory if not desired */
                    398:        if (!alloc_mem) {
                    399:                return;
                    400:        }
                    401: 
                    402:        /* Allocate some space for the initial allocations */
                    403:        switch (type) {
                    404:        default:
                    405:                misc_size = page_size;
                    406:                ptr = _profile_alloc_pages(misc_size + callback_size);
                    407:                ptr = _profile_md_acontext(pv, ptr, misc_size, ACONTEXT_MISC);
                    408:                ptr = _profile_md_acontext(pv, ptr, callback_size, ACONTEXT_CALLBACK);
                    409:                break;
                    410: 
                    411:        case PROFILE_GPROF:
                    412: 
                    413: #if defined(MACH_KERNEL) || defined(_KERNEL)
                    414:                /*
                    415:                 * For the MK & server allocate some slop space now for the
                    416:                 * secondary context blocks in case allocations are done at
                    417:                 * interrupt level when another allocation is being done.  This
                    418:                 * is done before the main allocation blocks and will be pushed
                    419:                 * so that it will only be used when the main allocation block
                    420:                 * is locked.
                    421:                 */
                    422:                extra_arc_size = 4*page_size;
                    423:                extra_func_size = 2*page_size;
                    424: #else
                    425:                extra_arc_size = extra_func_size = 0;
                    426: #endif
                    427: 
                    428:                /* Set up allocation areas */
                    429:                arc_size = ROUNDUP(PROFILE_NUM_ARCS * sizeof(struct hasharc), page_size);
                    430:                func_size = ROUNDUP(PROFILE_NUM_FUNCS * sizeof(struct gfuncs), page_size);
                    431:                hash_size = _profile_hash_size * sizeof (struct hasharc *);
                    432:                misc_size = ROUNDUP(hash_size + page_size, page_size);
                    433: 
                    434:                ptr = _profile_alloc_pages(arc_size
                    435:                                           + func_size
                    436:                                           + misc_size
                    437:                                           + callback_size
                    438:                                           + extra_arc_size
                    439:                                           + extra_func_size);
                    440: 
                    441: #if defined(MACH_KERNEL) || defined(_KERNEL)
                    442:                ptr = _profile_md_acontext(pv, ptr, extra_arc_size, ACONTEXT_GPROF);
                    443:                ptr = _profile_md_acontext(pv, ptr, extra_func_size, ACONTEXT_GFUNC);
                    444: #endif
                    445:                ptr = _profile_md_acontext(pv, ptr, arc_size, ACONTEXT_GPROF);
                    446:                ptr = _profile_md_acontext(pv, ptr, func_size, ACONTEXT_GFUNC);
                    447:                ptr = _profile_md_acontext(pv, ptr, misc_size, ACONTEXT_MISC);
                    448:                ptr = _profile_md_acontext(pv, ptr, callback_size, ACONTEXT_CALLBACK);
                    449: 
                    450:                /* Allocate hash table */
                    451:                pv->md.hash_ptr = (struct hasharc **) _profile_alloc(pv, hash_size, ACONTEXT_MISC);
                    452:                break;
                    453: 
                    454:        case PROFILE_PROF:
                    455:                /* Set up allocation areas */
                    456:                func_size = ROUNDUP(PROFILE_NUM_FUNCS * sizeof(struct prof_ext), page_size);
                    457:                misc_size = page_size;
                    458: 
                    459:                ptr = _profile_alloc_pages(func_size
                    460:                                           + misc_size
                    461:                                           + callback_size);
                    462: 
                    463:                ptr = _profile_md_acontext(pv, ptr, func_size, ACONTEXT_PROF);
                    464:                ptr = _profile_md_acontext(pv, ptr, misc_size, ACONTEXT_MISC);
                    465:                ptr = _profile_md_acontext(pv, ptr, callback_size, ACONTEXT_CALLBACK);
                    466:                break;
                    467:        }
                    468: }
                    469: 
                    470: 
                    471: /*
                    472:  * Machine dependent functions to start and stop profiling.
                    473:  */
                    474: 
                    475: int
                    476: _profile_md_start(void)
                    477: {
                    478:        _mcount_ptr = _profile_vars.md.save_mcount_ptr;
                    479:        return 0;
                    480: }
                    481: 
                    482: int
                    483: _profile_md_stop(void)
                    484: {
                    485:        _mcount_ptr = _dummy_mcount;
                    486:        return 0;
                    487: }
                    488: 
                    489: 
                    490: /*
                    491:  * Free up all memory in a memory context block.
                    492:  */
                    493: 
                    494: static void
                    495: _profile_reset_alloc(struct profile_vars *pv, acontext_type_t ac)
                    496: {
                    497:        struct alloc_context *aptr;
                    498:        struct page_list *plist;
                    499: 
                    500:        for (aptr = pv->acontext[ac];
                    501:             aptr != (struct alloc_context *)0;
                    502:             aptr = aptr->next) {
                    503: 
                    504:                for (plist = aptr->plist;
                    505:                     plist != (struct page_list *)0;
                    506:                     plist = plist->next) {
                    507: 
                    508:                        plist->ptr = plist->first;
                    509:                        plist->bytes_free += plist->bytes_allocated;
                    510:                        plist->bytes_allocated = 0;
                    511:                        plist->num_allocations = 0;
                    512:                        memset(plist->first, '\0', plist->bytes_allocated);
                    513:                }
                    514:        }
                    515: }
                    516: 
                    517: 
                    518: /*
                    519:  * Reset profiling.  Since the only user of this function is the kernel
                    520:  * and the server, we don't have to worry about other stuff than gprof.
                    521:  */
                    522: 
                    523: void
                    524: _profile_reset(struct profile_vars *pv)
                    525: {
                    526:        struct alloc_context *aptr;
                    527:        struct page_list *plist;
                    528:        struct gfuncs *gfunc;
                    529: 
                    530:        if (pv->active) {
                    531:                _profile_md_stop();
                    532:        }
                    533: 
                    534:        /* Reset all function unique pointers back to 0 */
                    535:        for (aptr = pv->acontext[ACONTEXT_GFUNC];
                    536:             aptr != (struct alloc_context *)0;
                    537:             aptr = aptr->next) {
                    538: 
                    539:                for (plist = aptr->plist;
                    540:                     plist != (struct page_list *)0;
                    541:                     plist = plist->next) {
                    542: 
                    543:                        for (gfunc = (struct gfuncs *)plist->first;
                    544:                             gfunc < (struct gfuncs *)plist->ptr;
                    545:                             gfunc++) {
                    546: 
                    547:                                *(gfunc->unique_ptr) = (struct hasharc *)0;
                    548:                        }
                    549:                }
                    550:        }
                    551: 
                    552:        /* Release memory */
                    553:        _profile_reset_alloc(pv, ACONTEXT_GPROF);
                    554:        _profile_reset_alloc(pv, ACONTEXT_GFUNC);
                    555:        _profile_reset_alloc(pv, ACONTEXT_PROF);
                    556: 
                    557:        memset((void *)pv->profil_buf, '\0', pv->profil_info.profil_len);
                    558:        memset((void *)pv->md.hash_ptr, '\0', pv->md.hash_size * sizeof(struct hasharc *));
                    559:        memset((void *)&pv->stats, '\0', sizeof(pv->stats));
                    560: 
                    561:        pv->stats.stats_size    = sizeof(struct profile_stats);
                    562:        pv->stats.major_version = PROFILE_MAJOR_VERSION;
                    563:        pv->stats.minor_version = PROFILE_MINOR_VERSION;
                    564: 
                    565:        if (pv->active) {
                    566:                _profile_md_start();
                    567:        }
                    568: }
                    569: 
                    570: 
                    571: /*
                    572:  * Machine dependent function to write out gprof records.
                    573:  */
                    574: 
                    575: size_t
                    576: _gprof_write(struct profile_vars *pv, struct callback *callback_ptr)
                    577: {
                    578:        struct alloc_context *aptr;
                    579:        struct page_list *plist;
                    580:        size_t bytes = 0;
                    581:        struct hasharc *hptr;
                    582:        int i;
                    583: 
                    584:        for (aptr = pv->acontext[ACONTEXT_GPROF];
                    585:             aptr != (struct alloc_context *)0;
                    586:             aptr = aptr->next) {
                    587: 
                    588:                for (plist = aptr->plist; plist != (struct page_list *)0; plist = plist->next) {
                    589:                        hptr = (struct hasharc *)plist->first;
                    590:                        for (i = 0; i < plist->num_allocations; (i++, hptr++)) {
                    591: 
                    592:                                struct gprof_arc arc = hptr->arc;
                    593:                                int nrecs = 1 + (hptr->overflow * 2);
                    594:                                int j;
                    595: 
                    596:                                if (pv->check_funcs) {
                    597:                                        if (arc.frompc < pv->profil_info.lowpc ||
                    598:                                            arc.frompc > pv->profil_info.highpc) {
                    599: 
                    600:                                                arc.frompc = (prof_uptrint_t)pv->bogus_func;
                    601:                                        }
                    602: 
                    603:                                        if (arc.selfpc < pv->profil_info.lowpc ||
                    604:                                            arc.selfpc > pv->profil_info.highpc) {
                    605: 
                    606:                                                arc.selfpc = (prof_uptrint_t)pv->bogus_func;
                    607:                                        }
                    608:                                }
                    609: 
                    610:                                /* For each overflow, emit 2 extra records with the count
                    611:                                   set to 0x80000000 */
                    612:                                for (j = 0; j < nrecs; j++) {
                    613:                                        bytes += sizeof (arc);
                    614:                                        if ((*pv->fwrite_func)((void *)&arc,
                    615:                                                               sizeof(arc),
                    616:                                                               1,
                    617:                                                               pv->stream) != 1) {
                    618: 
                    619:                                                _profile_error(pv);
                    620:                                        }
                    621: 
                    622:                                        arc.count = 0x80000000;
                    623:                                }
                    624:                        }
                    625:                }
                    626:        }
                    627: 
                    628:        return bytes;
                    629: }
                    630: 
                    631: 
                    632: /*
                    633:  * Machine dependent function to write out prof records.
                    634:  */
                    635: 
                    636: size_t
                    637: _prof_write(struct profile_vars *pv, struct callback *callback_ptr)
                    638: {
                    639:        struct alloc_context *aptr;
                    640:        struct page_list *plist;
                    641:        size_t bytes = 0;
                    642:        struct prof_ext prof_st;
                    643:        struct prof_int *pptr;
                    644:        struct gfuncs *gptr;
                    645:        int nrecs;
                    646:        int i, j;
                    647: 
                    648:        /* Write out information prof_mcount collects */
                    649:        for (aptr = pv->acontext[ACONTEXT_PROF];
                    650:             aptr != (struct alloc_context *)0;
                    651:             aptr = aptr->next) {
                    652: 
                    653:                for (plist = aptr->plist; plist != (struct page_list *)0; plist = plist->next) {
                    654:                        pptr = (struct prof_int *)plist->first;
                    655: 
                    656:                        for (i = 0; i < plist->num_allocations; (i++, pptr++)) {
                    657: 
                    658:                                /* Write out 2 records for each overflow, each with a
                    659:                                   count of 0x80000000 + the normal record */
                    660:                                prof_st = pptr->prof;
                    661:                                nrecs = 1 + (pptr->overflow * 2);
                    662: 
                    663:                                for (j = 0; j < nrecs; j++) {
                    664:                                        bytes += sizeof (struct prof_ext);
                    665:                                        if ((*pv->fwrite_func)((void *)&prof_st,
                    666:                                                               sizeof(prof_st),
                    667:                                                               1,
                    668:                                                               pv->stream) != 1) {
                    669: 
                    670:                                                _profile_error(pv);
                    671:                                        }
                    672: 
                    673:                                        prof_st.cncall = 0x80000000;
                    674:                                }
                    675:                        }
                    676:                }
                    677:        }
                    678: 
                    679:        /* Now write out the prof information that gprof collects */
                    680:        for (aptr = pv->acontext[ACONTEXT_GFUNC];
                    681:             aptr != (struct alloc_context *)0;
                    682:             aptr = aptr->next) {
                    683: 
                    684:                for (plist = aptr->plist; plist != (struct page_list *)0; plist = plist->next) {
                    685:                        gptr = (struct gfuncs *)plist->first;
                    686: 
                    687:                        for (i = 0; i < plist->num_allocations; (i++, gptr++)) {
                    688: 
                    689:                                /* Write out 2 records for each overflow, each with a
                    690:                                   count of 0x80000000 + the normal record */
                    691:                                prof_st = gptr->prof.prof;
                    692:                                nrecs = 1 + (gptr->prof.overflow * 2);
                    693: 
                    694:                                for (j = 0; j < nrecs; j++) {
                    695:                                        bytes += sizeof (struct prof_ext);
                    696:                                        if ((*pv->fwrite_func)((void *)&prof_st,
                    697:                                                               sizeof(prof_st),
                    698:                                                               1,
                    699:                                                               pv->stream) != 1) {
                    700: 
                    701:                                                _profile_error(pv);
                    702:                                        }
                    703: 
                    704:                                        prof_st.cncall = 0x80000000;
                    705:                                }
                    706:                        }
                    707:                }
                    708:        }
                    709: 
                    710:        return bytes;
                    711: }
                    712: 
                    713: 
                    714: /*
                    715:  * Update any statistics.  For the 386, calculate the hash table loading factor.
                    716:  * Also figure out how many overflows occured.
                    717:  */
                    718: 
                    719: void
                    720: _profile_update_stats(struct profile_vars *pv)
                    721: {
                    722:        struct alloc_context *aptr;
                    723:        struct page_list *plist;
                    724:        struct hasharc *hptr;
                    725:        struct prof_int *pptr;
                    726:        struct gfuncs *fptr;
                    727:        LHISTCOUNTER *lptr;
                    728:        int i;
                    729: 
                    730:        for(i = 0; i < MAX_BUCKETS+1; i++) {
                    731:                pv->stats.buckets[i] = 0;
                    732:        }
                    733: 
                    734:        pv->stats.hash_buckets = 0;
                    735: 
                    736:        if (pv->md.hash_ptr) {
                    737:                for (i = 0; i < pv->md.hash_size; i++) {
                    738:                        long nbuckets = 0;
                    739:                        struct hasharc *hptr;
                    740: 
                    741:                        for (hptr = pv->md.hash_ptr[i]; hptr; hptr = hptr->next) {
                    742:                                nbuckets++;
                    743:                        }
                    744: 
                    745:                        pv->stats.buckets[ (nbuckets < MAX_BUCKETS) ? nbuckets : MAX_BUCKETS ]++;
                    746:                        if (pv->stats.hash_buckets < nbuckets) {
                    747:                                pv->stats.hash_buckets = nbuckets;
                    748:                        }
                    749:                }
                    750:        }
                    751: 
                    752:        /* Count how many times functions are out of bounds */
                    753:        if (pv->check_funcs) {
                    754:                pv->stats.bogus_count = 0;
                    755: 
                    756:                for (aptr = pv->acontext[ACONTEXT_GPROF];
                    757:                     aptr != (struct alloc_context *)0;
                    758:                     aptr = aptr->next) {
                    759: 
                    760:                        for (plist = aptr->plist;
                    761:                             plist != (struct page_list *)0;
                    762:                             plist = plist->next) {
                    763: 
                    764:                                hptr = (struct hasharc *)plist->first;
                    765:                                for (i = 0; i < plist->num_allocations; (i++, hptr++)) {
                    766: 
                    767:                                        if (hptr->arc.frompc < pv->profil_info.lowpc ||
                    768:                                            hptr->arc.frompc > pv->profil_info.highpc) {
                    769:                                                pv->stats.bogus_count++;
                    770:                                        }
                    771: 
                    772:                                        if (hptr->arc.selfpc < pv->profil_info.lowpc ||
                    773:                                            hptr->arc.selfpc > pv->profil_info.highpc) {
                    774:                                                pv->stats.bogus_count++;
                    775:                                        }
                    776:                                }
                    777:                        }
                    778:                }
                    779:        }
                    780: 
                    781:        /* Figure out how many overflows occurred */
                    782:        PROF_ULONG_TO_CNT(pv->stats.prof_overflow, 0);
                    783:        PROF_ULONG_TO_CNT(pv->stats.gprof_overflow, 0);
                    784: 
                    785:        for (aptr = pv->acontext[ACONTEXT_GPROF];
                    786:             aptr != (struct alloc_context *)0;
                    787:             aptr = aptr->next) {
                    788: 
                    789:                for (plist = aptr->plist;
                    790:                     plist != (struct page_list *)0;
                    791:                     plist = plist->next) {
                    792: 
                    793:                        hptr = (struct hasharc *)plist->first;
                    794:                        for (i = 0; i < plist->num_allocations; (i++, hptr++)) {
                    795:                                PROF_CNT_ADD(pv->stats.gprof_overflow, hptr->overflow);
                    796:                        }
                    797:                }
                    798:        }
                    799: 
                    800:        for (aptr = pv->acontext[ACONTEXT_PROF];
                    801:             aptr != (struct alloc_context *)0;
                    802:             aptr = aptr->next) {
                    803: 
                    804:                for (plist = aptr->plist;
                    805:                     plist != (struct page_list *)0;
                    806:                     plist = plist->next) {
                    807: 
                    808:                        pptr = (struct prof_int *)plist->first;
                    809:                        for (i = 0; i < plist->num_allocations; (i++, pptr++)) {
                    810:                                PROF_CNT_ADD(pv->stats.prof_overflow, pptr->overflow);
                    811:                        }
                    812:                }
                    813:        }
                    814: 
                    815:        for (aptr = pv->acontext[ACONTEXT_GFUNC];
                    816:             aptr != (struct alloc_context *)0;
                    817:             aptr = aptr->next) {
                    818: 
                    819:                for (plist = aptr->plist;
                    820:                     plist != (struct page_list *)0;
                    821:                     plist = plist->next) {
                    822: 
                    823:                        fptr = (struct gfuncs *)plist->first;
                    824:                        for (i = 0; i < plist->num_allocations; (i++, fptr++)) {
                    825:                                PROF_CNT_ADD(pv->stats.prof_overflow, fptr->prof.overflow);
                    826:                        }
                    827:                }
                    828:        }
                    829: 
                    830:        /* Now go through & count how many times the LHISTCOUNTER overflowed into a 2nd word */
                    831:        lptr = (LHISTCOUNTER *)pv->profil_buf;
                    832: 
                    833:        if (pv->use_profil &&
                    834:            pv->profil_info.counter_size == sizeof(LHISTCOUNTER) &&
                    835:            lptr != (LHISTCOUNTER *)0) {
                    836: 
                    837:                PROF_ULONG_TO_CNT(pv->stats.overflow_ticks, 0);
                    838:                for (i = 0; i < pv->stats.profil_buckets; i++) {
                    839:                        PROF_CNT_ADD(pv->stats.overflow_ticks, lptr[i].high);
                    840:                }
                    841:        }
                    842: }
                    843: 
                    844: #if !defined(_KERNEL) && !defined(MACH_KERNEL)
                    845: 
                    846: /*
                    847:  * Routine callable from the debugger that prints the statistics.
                    848:  */
                    849: 
                    850: int _profile_debug(void)
                    851: {
                    852:        _profile_update_stats(&_profile_vars);
                    853:        _profile_print_stats(stderr, &_profile_vars.stats, &_profile_vars.profil_info);
                    854:        return 0;
                    855: }
                    856: 
                    857: /*
                    858:  * Print the statistics structure in a meaningful way.
                    859:  */
                    860: 
                    861: void _profile_print_stats(FILE *stream,
                    862:                          const struct profile_stats *stats,
                    863:                          const struct profile_profil *pinfo)
                    864: {
                    865:        int i;
                    866:        prof_cnt_t total_hits;
                    867:        acontext_type_t ac;
                    868:        int width_cname = 0;
                    869:        int width_alloc = 0;
                    870:        int width_wasted = 0;
                    871:        int width_overhead = 0;
                    872:        int width_context = 0;
                    873:        static const char *cname[ACONTEXT_MAX] = ACONTEXT_NAMES;
                    874:        char buf[20];
                    875: 
                    876:        if (!stats) {
                    877:                return;
                    878:        }
                    879: 
                    880:        if (!stream) {
                    881:                stream = stdout;
                    882:        }
                    883: 
                    884:        sprintf(buf, "%ld.%ld", (long)stats->major_version, (long)stats->minor_version);
                    885:        fprintf(stream, "%12s profiling version number\n", buf);
                    886:        fprintf(stream, "%12lu size of profile_vars\n", (long unsigned)sizeof(struct profile_vars));
                    887:        fprintf(stream, "%12lu size of profile_stats\n", (long unsigned)sizeof(struct profile_stats));
                    888:        fprintf(stream, "%12lu size of profile_md\n", (long unsigned)sizeof(struct profile_md));
                    889:        fprintf(stream, "%12s calls to _{,g}prof_mcount\n", PROF_CNT_TO_DECIMAL((char *)0, stats->cnt));
                    890:        fprintf(stream, "%12s calls to old mcount\n", PROF_CNT_TO_DECIMAL((char *)0, stats->old_mcount));
                    891:        fprintf(stream, "%12s calls to _dummy_mcount\n", PROF_CNT_TO_DECIMAL((char *)0, stats->dummy));
                    892:        fprintf(stream, "%12lu functions profiled\n", (long unsigned)stats->prof_records);
                    893:        fprintf(stream, "%12lu gprof arcs\n", (long unsigned)stats->gprof_records);
                    894: 
                    895:        if (pinfo) {
                    896:                fprintf(stream, "%12lu profil buckets\n", (long unsigned)stats->profil_buckets);
                    897:                fprintf(stream, "%12lu profil lowpc  [0x%lx]\n",
                    898:                        (long unsigned)pinfo->lowpc,
                    899:                        (long unsigned)pinfo->lowpc);
                    900: 
                    901:                fprintf(stream, "%12lu profil highpc [0x%lx]\n",
                    902:                        (long unsigned)pinfo->highpc,
                    903:                        (long unsigned)pinfo->highpc);
                    904: 
                    905:                fprintf(stream, "%12lu profil highpc-lowpc\n", (long unsigned)(pinfo->highpc - pinfo->lowpc));
                    906:                fprintf(stream, "%12lu profil buffer length\n", (long unsigned)pinfo->profil_len);
                    907:                fprintf(stream, "%12lu profil sizeof counters\n", (long unsigned)pinfo->counter_size);
                    908:                fprintf(stream, "%12lu profil scale (%g)\n",
                    909:                        (long unsigned)pinfo->scale,
                    910:                        ((double)pinfo->scale) / ((double) 0x10000));
                    911: 
                    912: 
                    913:                for (i = 0; i < sizeof (pinfo->profil_unused) / sizeof (pinfo->profil_unused[0]); i++) {
                    914:                        if (pinfo->profil_unused[i]) {
                    915:                                fprintf(stream, "%12lu profil unused[%2d] {0x%.8lx}\n",
                    916:                                        (long unsigned)pinfo->profil_unused[i],
                    917:                                        i,
                    918:                                        (long unsigned)pinfo->profil_unused[i]);
                    919:                        }
                    920:                }
                    921:        }
                    922: 
                    923:        if (stats->max_cpu) {
                    924:                fprintf(stream, "%12lu current cpu/thread\n", (long unsigned)stats->my_cpu);
                    925:                fprintf(stream, "%12lu max cpu/thread+1\n", (long unsigned)stats->max_cpu);
                    926:        }
                    927: 
                    928:        if (stats->bogus_count != 0) {
                    929:                fprintf(stream,
                    930:                        "%12lu gprof functions found outside of range\n",
                    931:                        (long unsigned)stats->bogus_count);
                    932:        }
                    933: 
                    934:        if (PROF_CNT_NE_0(stats->too_low)) {
                    935:                fprintf(stream,
                    936:                        "%12s histogram ticks were too low\n",
                    937:                        PROF_CNT_TO_DECIMAL((char *)0, stats->too_low));
                    938:        }
                    939: 
                    940:        if (PROF_CNT_NE_0(stats->too_high)) {
                    941:                fprintf(stream,
                    942:                        "%12s histogram ticks were too high\n",
                    943:                        PROF_CNT_TO_DECIMAL((char *)0, stats->too_high));
                    944:        }
                    945: 
                    946:        if (PROF_CNT_NE_0(stats->acontext_locked)) {
                    947:                fprintf(stream,
                    948:                        "%12s times an allocation context was locked\n",
                    949:                        PROF_CNT_TO_DECIMAL((char *)0, stats->acontext_locked));
                    950:        }
                    951: 
                    952:        if (PROF_CNT_NE_0(stats->kernel_ticks)
                    953:            || PROF_CNT_NE_0(stats->user_ticks)
                    954:            || PROF_CNT_NE_0(stats->idle_ticks)) {
                    955: 
                    956:                prof_cnt_t total_ticks;
                    957:                long double total_ticks_dbl;
                    958: 
                    959:                total_ticks = stats->kernel_ticks;
                    960:                PROF_CNT_LADD(total_ticks, stats->user_ticks);
                    961:                PROF_CNT_LADD(total_ticks, stats->idle_ticks);
                    962:                total_ticks_dbl = PROF_CNT_TO_LDOUBLE(total_ticks);
                    963: 
                    964:                fprintf(stream,
                    965:                        "%12s total ticks\n",
                    966:                        PROF_CNT_TO_DECIMAL((char *)0, total_ticks));
                    967: 
                    968:                fprintf(stream,
                    969:                        "%12s ticks within the kernel (%5.2Lf%%)\n",
                    970:                        PROF_CNT_TO_DECIMAL((char *)0, stats->kernel_ticks),
                    971:                        100.0L * (PROF_CNT_TO_LDOUBLE(stats->kernel_ticks) / total_ticks_dbl));
                    972: 
                    973:                fprintf(stream,
                    974:                        "%12s ticks within user space (%5.2Lf%%)\n",
                    975:                        PROF_CNT_TO_DECIMAL((char *)0, stats->user_ticks),
                    976:                        100.0L * (PROF_CNT_TO_LDOUBLE(stats->user_ticks) / total_ticks_dbl));
                    977: 
                    978:                fprintf(stream,
                    979:                        "%12s ticks idle              (%5.2Lf%%)\n",
                    980:                        PROF_CNT_TO_DECIMAL((char *)0, stats->idle_ticks),
                    981:                        100.0L * (PROF_CNT_TO_LDOUBLE(stats->idle_ticks) / total_ticks_dbl));
                    982:        }
                    983: 
                    984:        if (PROF_CNT_NE_0(stats->overflow_ticks)) {
                    985:                fprintf(stream, "%12s times a HISTCOUNTER counter would have overflowed\n",
                    986:                        PROF_CNT_TO_DECIMAL((char *)0, stats->overflow_ticks));
                    987:        }
                    988: 
                    989:        if (PROF_CNT_NE_0(stats->hash_num)) {
                    990:                long double total_buckets = 0.0L;
                    991: 
                    992:                for (i = 0; i <= MAX_BUCKETS; i++) {
                    993:                        total_buckets += (long double)stats->buckets[i];
                    994:                }
                    995: 
                    996:                fprintf(stream, "%12lu max bucket(s) on hash chain.\n", (long unsigned)stats->hash_buckets);
                    997:                for (i = 0; i < MAX_BUCKETS; i++) {
                    998:                        if (stats->buckets[i] != 0) {
                    999:                                fprintf(stream, "%12lu bucket(s) had %d entries (%5.2Lf%%)\n",
                   1000:                                        (long unsigned)stats->buckets[i], i,
                   1001:                                        100.0L * ((long double)stats->buckets[i] / total_buckets));
                   1002:                        }
                   1003:                }
                   1004: 
                   1005:                if (stats->buckets[MAX_BUCKETS] != 0) {
                   1006:                        fprintf(stream, "%12lu bucket(s) had more than %d entries (%5.2Lf%%)\n",
                   1007:                                (long unsigned)stats->buckets[MAX_BUCKETS], MAX_BUCKETS,
                   1008:                                100.0L * ((long double)stats->buckets[MAX_BUCKETS] / total_buckets));
                   1009:                }
                   1010:        }
                   1011: 
                   1012:        PROF_ULONG_TO_CNT(total_hits, 0);
                   1013:        for (i = 0; i < MAX_CACHE; i++) {
                   1014:                PROF_CNT_LADD(total_hits, stats->cache_hits[i]);
                   1015:        }
                   1016: 
                   1017:        if (PROF_CNT_NE_0(total_hits)) {
                   1018:                long double total               = PROF_CNT_TO_LDOUBLE(stats->cnt);
                   1019:                long double total_hits_dbl      = PROF_CNT_TO_LDOUBLE(total_hits);
                   1020: 
                   1021:                fprintf(stream,
                   1022:                        "%12s cache hits (%.2Lf%%)\n",
                   1023:                        PROF_CNT_TO_DECIMAL((char *)0, total_hits),
                   1024:                        100.0L * (total_hits_dbl / total));
                   1025: 
                   1026:                for (i = 0; i < MAX_CACHE; i++) {
                   1027:                        if (PROF_CNT_NE_0(stats->cache_hits[i])) {
                   1028:                                fprintf(stream,
                   1029:                                        "%12s times cache#%d matched (%5.2Lf%% of cache hits, %5.2Lf%% total)\n",
                   1030:                                        PROF_CNT_TO_DECIMAL((char *)0, stats->cache_hits[i]),
                   1031:                                        i+1,
                   1032:                                        100.0L * (PROF_CNT_TO_LDOUBLE(stats->cache_hits[i]) / total_hits_dbl),
                   1033:                                        100.0L * (PROF_CNT_TO_LDOUBLE(stats->cache_hits[i]) / total));
                   1034:                        }
                   1035:                }
                   1036: 
                   1037:                if (PROF_CNT_NE_0(stats->hash_num)) {
                   1038:                        fprintf(stream, "%12s times hash table searched\n", PROF_CNT_TO_DECIMAL((char *)0, stats->hash_num));
                   1039:                        fprintf(stream, "%12s hash buckets searched\n", PROF_CNT_TO_DECIMAL((char *)0, stats->hash_search));
                   1040:                        fprintf(stream, "%12.4Lf average buckets searched\n",
                   1041:                                PROF_CNT_TO_LDOUBLE(stats->hash_search) / PROF_CNT_TO_LDOUBLE(stats->hash_num));
                   1042:                }
                   1043:        }
                   1044: 
                   1045:        for (i = 0; i < sizeof (stats->stats_unused) / sizeof (stats->stats_unused[0]); i++) {
                   1046:                if (PROF_CNT_NE_0(stats->stats_unused[i])) {
                   1047:                        fprintf(stream, "%12s unused[%2d] {0x%.8lx 0x%.8lx}\n",
                   1048:                                PROF_CNT_TO_DECIMAL((char *)0, stats->stats_unused[i]),
                   1049:                                i,
                   1050:                                (unsigned long)stats->stats_unused[i].high,
                   1051:                                (unsigned long)stats->stats_unused[i].low);
                   1052:                }
                   1053:        }
                   1054: 
                   1055:        /* Get the width for the allocation contexts */
                   1056:        for (ac = ACONTEXT_FIRST; ac < ACONTEXT_MAX; ac++) {
                   1057:                int len;
                   1058: 
                   1059:                if (stats->num_context[ac] == 0) {
                   1060:                        continue;
                   1061:                }
                   1062: 
                   1063:                len = strlen (cname[ac]);
                   1064:                if (len > width_cname)
                   1065:                        width_cname = len;
                   1066: 
                   1067:                len = sprintf (buf, "%lu", (long unsigned)stats->num_alloc[ac]);
                   1068:                if (len > width_alloc)
                   1069:                        width_alloc = len;
                   1070: 
                   1071:                len = sprintf (buf, "%lu", (long unsigned)stats->wasted[ac]);
                   1072:                if (len > width_wasted)
                   1073:                        width_wasted = len;
                   1074: 
                   1075:                len = sprintf (buf, "%lu", (long unsigned)stats->overhead[ac]);
                   1076:                if (len > width_overhead)
                   1077:                        width_overhead = len;
                   1078: 
                   1079:                len = sprintf (buf, "%lu", (long unsigned)stats->num_context[ac]);
                   1080:                if (len > width_context)
                   1081:                        width_context = len;
                   1082:        }
                   1083: 
                   1084:        /* Print info about allocation contexts */
                   1085:        for (ac = ACONTEXT_FIRST; ac < ACONTEXT_MAX; ac++) {
                   1086:                if (stats->num_context[ac] == 0) {
                   1087:                        continue;
                   1088:                }
                   1089: 
                   1090:                fprintf (stream,
                   1091:                         "%12lu bytes in %-*s %*lu alloc, %*lu unused, %*lu over, %*lu context\n",
                   1092:                         (long unsigned)stats->bytes_alloc[ac],
                   1093:                         width_cname,    cname[ac],
                   1094:                         width_alloc,    (long unsigned)stats->num_alloc[ac],
                   1095:                         width_wasted,   (long unsigned)stats->wasted[ac],
                   1096:                         width_overhead, (long unsigned)stats->overhead[ac],
                   1097:                         width_context,  (long unsigned)stats->num_context[ac]);
                   1098:        }
                   1099: }
                   1100: 
                   1101: 
                   1102: /*
                   1103:  * Merge a new statistics field into an old one.
                   1104:  */
                   1105: 
                   1106: void _profile_merge_stats(struct profile_stats  *old_stats, const struct profile_stats  *new_stats)
                   1107: {
                   1108:        int i;
                   1109: 
                   1110:        /* If nothing passed, just return */
                   1111:        if (!old_stats || !new_stats)
                   1112:                return;
                   1113: 
                   1114:        /* If the old_stats has not been initialized, just copy in the new stats */
                   1115:        if (old_stats->major_version == 0) {
                   1116:            *old_stats = *new_stats;
                   1117: 
                   1118:        /* Otherwise, update stats, field by field */
                   1119:        } else {
                   1120:                if (old_stats->prof_records < new_stats->prof_records)
                   1121:                        old_stats->prof_records = new_stats->prof_records;
                   1122: 
                   1123:                if (old_stats->gprof_records < new_stats->gprof_records)
                   1124:                        old_stats->gprof_records = new_stats->gprof_records;
                   1125: 
                   1126:                if (old_stats->hash_buckets < new_stats->hash_buckets)
                   1127:                        old_stats->hash_buckets = new_stats->hash_buckets;
                   1128: 
                   1129:                if (old_stats->bogus_count < new_stats->bogus_count)
                   1130:                        old_stats->bogus_count = new_stats->bogus_count;
                   1131: 
                   1132:                PROF_CNT_LADD(old_stats->cnt,             new_stats->cnt);
                   1133:                PROF_CNT_LADD(old_stats->dummy,           new_stats->dummy);
                   1134:                PROF_CNT_LADD(old_stats->old_mcount,      new_stats->old_mcount);
                   1135:                PROF_CNT_LADD(old_stats->hash_search,     new_stats->hash_search);
                   1136:                PROF_CNT_LADD(old_stats->hash_num,        new_stats->hash_num);
                   1137:                PROF_CNT_LADD(old_stats->user_ticks,      new_stats->user_ticks);
                   1138:                PROF_CNT_LADD(old_stats->kernel_ticks,    new_stats->kernel_ticks);
                   1139:                PROF_CNT_LADD(old_stats->idle_ticks,      new_stats->idle_ticks);
                   1140:                PROF_CNT_LADD(old_stats->overflow_ticks,  new_stats->overflow_ticks);
                   1141:                PROF_CNT_LADD(old_stats->acontext_locked, new_stats->acontext_locked);
                   1142:                PROF_CNT_LADD(old_stats->too_low,         new_stats->too_low);
                   1143:                PROF_CNT_LADD(old_stats->too_high,        new_stats->too_high);
                   1144:                PROF_CNT_LADD(old_stats->prof_overflow,   new_stats->prof_overflow);
                   1145:                PROF_CNT_LADD(old_stats->gprof_overflow,  new_stats->gprof_overflow);
                   1146: 
                   1147:                for (i = 0; i < (int)ACONTEXT_MAX; i++) {
                   1148:                        if (old_stats->num_alloc[i] < new_stats->num_alloc[i])
                   1149:                                old_stats->num_alloc[i] = new_stats->num_alloc[i];
                   1150: 
                   1151:                        if (old_stats->bytes_alloc[i] < new_stats->bytes_alloc[i])
                   1152:                                old_stats->bytes_alloc[i] = new_stats->bytes_alloc[i];
                   1153: 
                   1154:                        if (old_stats->num_context[i] < new_stats->num_context[i])
                   1155:                                old_stats->num_context[i] = new_stats->num_context[i];
                   1156: 
                   1157:                        if (old_stats->wasted[i] < new_stats->wasted[i])
                   1158:                                old_stats->wasted[i] = new_stats->wasted[i];
                   1159: 
                   1160:                        if (old_stats->overhead[i] < new_stats->overhead[i])
                   1161:                                old_stats->overhead[i] = new_stats->overhead[i];
                   1162: 
                   1163:                }
                   1164: 
                   1165:                for (i = 0; i < MAX_BUCKETS+1; i++) {
                   1166:                        if (old_stats->buckets[i] < new_stats->buckets[i])
                   1167:                                old_stats->buckets[i] = new_stats->buckets[i];
                   1168:                }
                   1169: 
                   1170:                for (i = 0; i < MAX_CACHE; i++) {
                   1171:                        PROF_CNT_LADD(old_stats->cache_hits[i], new_stats->cache_hits[i]);
                   1172:                }
                   1173: 
                   1174:                for (i = 0; i < sizeof(old_stats->stats_unused) / sizeof(old_stats->stats_unused[0]); i++) {
                   1175:                        PROF_CNT_LADD(old_stats->stats_unused[i], new_stats->stats_unused[i]);
                   1176:                }
                   1177:        }
                   1178: }
                   1179: 
                   1180: #endif
                   1181: 
                   1182: 
                   1183: /*
                   1184:  * Invalid function address used when checking of function addresses is
                   1185:  * desired for gprof arcs, and we discover an address out of bounds.
                   1186:  * There should be no callers of this function.
                   1187:  */
                   1188: 
                   1189: void
                   1190: _bogus_function(void)
                   1191: {
                   1192: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.