17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 567298654Sdamico * Common Development and Distribution License (the "License"). 667298654Sdamico * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 2192ed1782Smike_s 227c478bd9Sstevel@tonic-gate /* 23*b9bd317cSab196087 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2492ed1782Smike_s * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <ctype.h> 307c478bd9Sstevel@tonic-gate #include <string.h> 317c478bd9Sstevel@tonic-gate #include <sys/param.h> 327c478bd9Sstevel@tonic-gate #include <stdlib.h> 33*b9bd317cSab196087 #include "conv.h" 347c478bd9Sstevel@tonic-gate #include "gprof.h" 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate void print_demangled_name(int, nltype *); 377c478bd9Sstevel@tonic-gate void striped_name(char *, nltype **); 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate extern long hz; 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate /* 427c478bd9Sstevel@tonic-gate * Symbols that must never be printed, no matter what. 437c478bd9Sstevel@tonic-gate */ 447c478bd9Sstevel@tonic-gate char *splsym[] = { 457c478bd9Sstevel@tonic-gate PRF_ETEXT, 467c478bd9Sstevel@tonic-gate PRF_EXTSYM, 477c478bd9Sstevel@tonic-gate PRF_MEMTERM, 4892ed1782Smike_s NULL 497c478bd9Sstevel@tonic-gate }; 507c478bd9Sstevel@tonic-gate 5192ed1782Smike_s static bool is_special_sym(nltype *nlp); 5292ed1782Smike_s 53*b9bd317cSab196087 const char * 547c478bd9Sstevel@tonic-gate demangled_name(nltype *selfp) 557c478bd9Sstevel@tonic-gate { 567c478bd9Sstevel@tonic-gate if (!Cflag) 577c478bd9Sstevel@tonic-gate return (selfp->name); 587c478bd9Sstevel@tonic-gate 59*b9bd317cSab196087 return (conv_demangle_name(selfp->name)); 607c478bd9Sstevel@tonic-gate } 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate void 6392ed1782Smike_s printprof(void) 647c478bd9Sstevel@tonic-gate { 657c478bd9Sstevel@tonic-gate nltype *np; 667c478bd9Sstevel@tonic-gate nltype **sortednlp; 677c478bd9Sstevel@tonic-gate int i, index; 687c478bd9Sstevel@tonic-gate int print_count = number_funcs_toprint; 697c478bd9Sstevel@tonic-gate bool print_flag = TRUE; 707c478bd9Sstevel@tonic-gate mod_info_t *mi; 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate actime = 0.0; 7392ed1782Smike_s (void) printf("\f\n"); 747c478bd9Sstevel@tonic-gate flatprofheader(); 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate /* 777c478bd9Sstevel@tonic-gate * Sort the symbol table in by time 787c478bd9Sstevel@tonic-gate */ 797c478bd9Sstevel@tonic-gate sortednlp = (nltype **) calloc(total_names, sizeof (nltype *)); 807c478bd9Sstevel@tonic-gate if (sortednlp == (nltype **) 0) { 8192ed1782Smike_s (void) fprintf(stderr, 827c478bd9Sstevel@tonic-gate "[printprof] ran out of memory for time sorting\n"); 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate index = 0; 867c478bd9Sstevel@tonic-gate for (mi = &modules; mi; mi = mi->next) { 877c478bd9Sstevel@tonic-gate for (i = 0; i < mi->nname; i++) 887c478bd9Sstevel@tonic-gate sortednlp[index++] = &(mi->nl[i]); 897c478bd9Sstevel@tonic-gate } 907c478bd9Sstevel@tonic-gate 9192ed1782Smike_s qsort(sortednlp, total_names, sizeof (nltype *), timecmp); 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate for (index = 0; (index < total_names) && print_flag; index += 1) { 947c478bd9Sstevel@tonic-gate np = sortednlp[index]; 957c478bd9Sstevel@tonic-gate flatprofline(np); 967c478bd9Sstevel@tonic-gate if (nflag) { 977c478bd9Sstevel@tonic-gate if (--print_count == 0) 987c478bd9Sstevel@tonic-gate print_flag = FALSE; 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate } 1017c478bd9Sstevel@tonic-gate actime = 0.0; 1027c478bd9Sstevel@tonic-gate free(sortednlp); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate int 10692ed1782Smike_s timecmp(const void *arg1, const void *arg2) 1077c478bd9Sstevel@tonic-gate { 10892ed1782Smike_s nltype **npp1 = (nltype **)arg1; 10992ed1782Smike_s nltype **npp2 = (nltype **)arg2; 1107c478bd9Sstevel@tonic-gate double timediff; 1117c478bd9Sstevel@tonic-gate long calldiff; 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate timediff = (*npp2)->time - (*npp1)->time; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate if (timediff > 0.0) 1167c478bd9Sstevel@tonic-gate return (1); 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate if (timediff < 0.0) 1197c478bd9Sstevel@tonic-gate return (-1); 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate calldiff = (*npp2)->ncall - (*npp1)->ncall; 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate if (calldiff > 0) 1247c478bd9Sstevel@tonic-gate return (1); 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate if (calldiff < 0) 1277c478bd9Sstevel@tonic-gate return (-1); 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate return (strcmp((*npp1)->name, (*npp2)->name)); 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate /* 1337c478bd9Sstevel@tonic-gate * header for flatprofline 1347c478bd9Sstevel@tonic-gate */ 1357c478bd9Sstevel@tonic-gate void 1367c478bd9Sstevel@tonic-gate flatprofheader() 1377c478bd9Sstevel@tonic-gate { 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate if (bflag) 1407c478bd9Sstevel@tonic-gate printblurb(FLAT_BLURB); 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate if (old_style) { 14392ed1782Smike_s (void) printf( 14492ed1782Smike_s "\ngranularity: each sample hit covers %d byte(s)", 1457c478bd9Sstevel@tonic-gate (long)scale * sizeof (UNIT)); 1467c478bd9Sstevel@tonic-gate if (totime > 0.0) { 14792ed1782Smike_s (void) printf(" for %.2f%% of %.2f seconds\n\n", 1487c478bd9Sstevel@tonic-gate 100.0/totime, totime / hz); 1497c478bd9Sstevel@tonic-gate } else { 15092ed1782Smike_s (void) printf(" no time accumulated\n\n"); 1517c478bd9Sstevel@tonic-gate /* 1527c478bd9Sstevel@tonic-gate * this doesn't hurt since all the numerators will 1537c478bd9Sstevel@tonic-gate * be zero. 1547c478bd9Sstevel@tonic-gate */ 1557c478bd9Sstevel@tonic-gate totime = 1.0; 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate 15992ed1782Smike_s (void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n", 1607c478bd9Sstevel@tonic-gate "% ", "cumulative", "self ", "", "self ", "total ", ""); 16192ed1782Smike_s (void) printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n", 1627c478bd9Sstevel@tonic-gate "time", "seconds ", "seconds", "calls", 1637c478bd9Sstevel@tonic-gate "ms/call", "ms/call", "name"); 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate void 1677c478bd9Sstevel@tonic-gate flatprofline(nltype *np) 1687c478bd9Sstevel@tonic-gate { 1697c478bd9Sstevel@tonic-gate if (zflag == 0 && np->ncall == 0 && np->time == 0) 1707c478bd9Sstevel@tonic-gate return; 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* 1737c478bd9Sstevel@tonic-gate * Do not print certain special symbols, like PRF_EXTSYM, etc. 1747c478bd9Sstevel@tonic-gate * even if zflag was on. 1757c478bd9Sstevel@tonic-gate */ 1767c478bd9Sstevel@tonic-gate if (is_special_sym(np)) 1777c478bd9Sstevel@tonic-gate return; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate actime += np->time; 1807c478bd9Sstevel@tonic-gate 18192ed1782Smike_s (void) printf("%5.1f %10.2f %8.2f", 1827c478bd9Sstevel@tonic-gate 100 * np->time / totime, actime / hz, np->time / hz); 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate if (np->ncall != 0) { 18592ed1782Smike_s (void) printf(" %8lld %8.2f %8.2f ", np->ncall, 1867c478bd9Sstevel@tonic-gate 1000 * np->time / hz / np->ncall, 1877c478bd9Sstevel@tonic-gate 1000 * (np->time + np->childtime) / hz / np->ncall); 1887c478bd9Sstevel@tonic-gate } else { 1897c478bd9Sstevel@tonic-gate if (!Cflag) 19092ed1782Smike_s (void) printf(" %8.8s %8.8s %8.8s ", "", "", ""); 1917c478bd9Sstevel@tonic-gate else 19292ed1782Smike_s (void) printf(" %8.8s %8.8s %8.8s ", "", "", ""); 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate printname(np); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate if (Cflag) 1987c478bd9Sstevel@tonic-gate print_demangled_name(55, np); 1997c478bd9Sstevel@tonic-gate 20092ed1782Smike_s (void) printf("\n"); 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate void 2047c478bd9Sstevel@tonic-gate gprofheader() 2057c478bd9Sstevel@tonic-gate { 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate if (bflag) 2087c478bd9Sstevel@tonic-gate printblurb(CALLG_BLURB); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate if (old_style) { 2117c478bd9Sstevel@tonic-gate 21292ed1782Smike_s (void) printf( 21392ed1782Smike_s "\ngranularity: each sample hit covers %d byte(s)", 2147c478bd9Sstevel@tonic-gate (long)scale * sizeof (UNIT)); 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate if (printtime > 0.0) { 21792ed1782Smike_s (void) printf(" for %.2f%% of %.2f seconds\n\n", 2187c478bd9Sstevel@tonic-gate 100.0/printtime, printtime / hz); 2197c478bd9Sstevel@tonic-gate } else { 22092ed1782Smike_s (void) printf(" no time propagated\n\n"); 2217c478bd9Sstevel@tonic-gate /* 2227c478bd9Sstevel@tonic-gate * this doesn't hurt, since all the numerators 2237c478bd9Sstevel@tonic-gate * will be 0.0 2247c478bd9Sstevel@tonic-gate */ 2257c478bd9Sstevel@tonic-gate printtime = 1.0; 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate } else { 22892ed1782Smike_s (void) printf( 22992ed1782Smike_s "\ngranularity: each pc-hit is considered 1 tick"); 2307c478bd9Sstevel@tonic-gate if (hz != 1) { 23192ed1782Smike_s (void) printf(" (@ %4.3f seconds per tick)", 2327c478bd9Sstevel@tonic-gate (double)1.0 / hz); 2337c478bd9Sstevel@tonic-gate } 23492ed1782Smike_s (void) puts("\n\n"); 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate 23792ed1782Smike_s (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", 2387c478bd9Sstevel@tonic-gate "", "", "", "", "called", "total", "parents"); 23992ed1782Smike_s (void) printf("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n", 2407c478bd9Sstevel@tonic-gate "index", "%time", "self", "descendents", 2417c478bd9Sstevel@tonic-gate "called", "self", "name", "index"); 24292ed1782Smike_s (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", 2437c478bd9Sstevel@tonic-gate "", "", "", "", "called", "total", "children"); 24492ed1782Smike_s (void) printf("\n"); 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate void 2487c478bd9Sstevel@tonic-gate gprofline(nltype *np) 2497c478bd9Sstevel@tonic-gate { 2507c478bd9Sstevel@tonic-gate char kirkbuffer[BUFSIZ]; 2517c478bd9Sstevel@tonic-gate 25292ed1782Smike_s (void) sprintf(kirkbuffer, "[%d]", np->index); 25392ed1782Smike_s (void) printf("%-6.6s %5.1f %7.2f %11.2f", kirkbuffer, 2547c478bd9Sstevel@tonic-gate 100 * (np->propself + np->propchild) / printtime, 2557c478bd9Sstevel@tonic-gate np->propself / hz, np->propchild / hz); 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate if ((np->ncall + np->selfcalls) != 0) { 25892ed1782Smike_s (void) printf(" %7lld", np->ncall); 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate if (np->selfcalls != 0) 26192ed1782Smike_s (void) printf("+%-7lld ", np->selfcalls); 2627c478bd9Sstevel@tonic-gate else 26392ed1782Smike_s (void) printf(" %7.7s ", ""); 2647c478bd9Sstevel@tonic-gate } else { 26592ed1782Smike_s (void) printf(" %7.7s %7.7s ", "", ""); 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate printname(np); 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate if (Cflag) 2717c478bd9Sstevel@tonic-gate print_demangled_name(50, np); 2727c478bd9Sstevel@tonic-gate 27392ed1782Smike_s (void) printf("\n"); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate static bool 2777c478bd9Sstevel@tonic-gate is_special_sym(nltype *nlp) 2787c478bd9Sstevel@tonic-gate { 2797c478bd9Sstevel@tonic-gate int i; 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate if (nlp->name == NULL) 2827c478bd9Sstevel@tonic-gate return (FALSE); 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate for (i = 0; splsym[i]; i++) 2857c478bd9Sstevel@tonic-gate if (strcmp(splsym[i], nlp->name) == 0) 2867c478bd9Sstevel@tonic-gate return (TRUE); 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate return (FALSE); 2897c478bd9Sstevel@tonic-gate } 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate void 2927c478bd9Sstevel@tonic-gate printgprof(nltype **timesortnlp) 2937c478bd9Sstevel@tonic-gate { 2947c478bd9Sstevel@tonic-gate int index; 2957c478bd9Sstevel@tonic-gate nltype *parentp; 2967c478bd9Sstevel@tonic-gate int print_count = number_funcs_toprint; 2977c478bd9Sstevel@tonic-gate bool count_flag = TRUE; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate /* 3007c478bd9Sstevel@tonic-gate * Print out the structured profiling list 3017c478bd9Sstevel@tonic-gate */ 3027c478bd9Sstevel@tonic-gate gprofheader(); 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate for (index = 0; index < total_names + ncycle && count_flag; index++) { 3057c478bd9Sstevel@tonic-gate parentp = timesortnlp[index]; 3067c478bd9Sstevel@tonic-gate if (zflag == 0 && parentp->ncall == 0 && 3077c478bd9Sstevel@tonic-gate parentp->selfcalls == 0 && parentp->propself == 0 && 3087c478bd9Sstevel@tonic-gate parentp -> propchild == 0) 3097c478bd9Sstevel@tonic-gate continue; 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate if (!parentp->printflag) 3127c478bd9Sstevel@tonic-gate continue; 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate /* 3157c478bd9Sstevel@tonic-gate * Do not print certain special symbols, like PRF_EXTSYM, etc. 3167c478bd9Sstevel@tonic-gate * even if zflag was on. 3177c478bd9Sstevel@tonic-gate */ 3187c478bd9Sstevel@tonic-gate if (is_special_sym(parentp)) 3197c478bd9Sstevel@tonic-gate continue; 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate if (parentp->name == 0 && parentp->cycleno != 0) { 3227c478bd9Sstevel@tonic-gate /* 3237c478bd9Sstevel@tonic-gate * cycle header 3247c478bd9Sstevel@tonic-gate */ 3257c478bd9Sstevel@tonic-gate printcycle(parentp); 3267c478bd9Sstevel@tonic-gate printmembers(parentp); 3277c478bd9Sstevel@tonic-gate } else { 3287c478bd9Sstevel@tonic-gate printparents(parentp); 3297c478bd9Sstevel@tonic-gate gprofline(parentp); 3307c478bd9Sstevel@tonic-gate printchildren(parentp); 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate 33392ed1782Smike_s (void) printf("\n"); 33492ed1782Smike_s (void) printf( 33592ed1782Smike_s "-----------------------------------------------\n"); 33692ed1782Smike_s (void) printf("\n"); 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate if (nflag) { 3397c478bd9Sstevel@tonic-gate --print_count; 3407c478bd9Sstevel@tonic-gate if (print_count == 0) 3417c478bd9Sstevel@tonic-gate count_flag = FALSE; 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate free(timesortnlp); 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate /* 3487c478bd9Sstevel@tonic-gate * sort by decreasing propagated time 3497c478bd9Sstevel@tonic-gate * if times are equal, but one is a cycle header, 3507c478bd9Sstevel@tonic-gate * say that's first (e.g. less, i.e. -1). 3517c478bd9Sstevel@tonic-gate * if one's name doesn't have an underscore and the other does, 3527c478bd9Sstevel@tonic-gate * say the one is first. 3537c478bd9Sstevel@tonic-gate * all else being equal, sort by names. 3547c478bd9Sstevel@tonic-gate */ 3557c478bd9Sstevel@tonic-gate int 35692ed1782Smike_s totalcmp(const void *arg1, const void *arg2) 3577c478bd9Sstevel@tonic-gate { 35892ed1782Smike_s nltype **npp1 = (nltype **)arg1; 35992ed1782Smike_s nltype **npp2 = (nltype **)arg2; 3607c478bd9Sstevel@tonic-gate nltype *np1 = *npp1; 3617c478bd9Sstevel@tonic-gate nltype *np2 = *npp2; 3627c478bd9Sstevel@tonic-gate double diff; 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate diff = (np1->propself + np1->propchild) - 3657c478bd9Sstevel@tonic-gate (np2->propself + np2->propchild); 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate if (diff < 0.0) 3687c478bd9Sstevel@tonic-gate return (1); 3697c478bd9Sstevel@tonic-gate if (diff > 0.0) 3707c478bd9Sstevel@tonic-gate return (-1); 3717c478bd9Sstevel@tonic-gate if (np1->name == 0 && np1->cycleno != 0) 3727c478bd9Sstevel@tonic-gate return (-1); 3737c478bd9Sstevel@tonic-gate if (np2->name == 0 && np2->cycleno != 0) 3747c478bd9Sstevel@tonic-gate return (1); 3757c478bd9Sstevel@tonic-gate if (np1->name == 0) 3767c478bd9Sstevel@tonic-gate return (-1); 3777c478bd9Sstevel@tonic-gate if (np2->name == 0) 3787c478bd9Sstevel@tonic-gate return (1); 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate if (*(np1->name) != '_' && *(np2->name) == '_') 3817c478bd9Sstevel@tonic-gate return (-1); 3827c478bd9Sstevel@tonic-gate if (*(np1->name) == '_' && *(np2->name) != '_') 3837c478bd9Sstevel@tonic-gate return (1); 3847c478bd9Sstevel@tonic-gate if (np1->ncall > np2->ncall) 3857c478bd9Sstevel@tonic-gate return (-1); 3867c478bd9Sstevel@tonic-gate if (np1->ncall < np2->ncall) 3877c478bd9Sstevel@tonic-gate return (1); 3887c478bd9Sstevel@tonic-gate return (strcmp(np1->name, np2->name)); 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate void 3927c478bd9Sstevel@tonic-gate printparents(nltype *childp) 3937c478bd9Sstevel@tonic-gate { 3947c478bd9Sstevel@tonic-gate nltype *parentp; 3957c478bd9Sstevel@tonic-gate arctype *arcp; 3967c478bd9Sstevel@tonic-gate nltype *cycleheadp; 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate if (childp->cyclehead != 0) 3997c478bd9Sstevel@tonic-gate cycleheadp = childp -> cyclehead; 4007c478bd9Sstevel@tonic-gate else 4017c478bd9Sstevel@tonic-gate cycleheadp = childp; 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate if (childp->parents == 0) { 40492ed1782Smike_s (void) printf("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s" 4057c478bd9Sstevel@tonic-gate " <spontaneous>\n", "", "", "", "", "", ""); 4067c478bd9Sstevel@tonic-gate return; 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate sortparents(childp); 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate for (arcp = childp->parents; arcp; arcp = arcp->arc_parentlist) { 4127c478bd9Sstevel@tonic-gate parentp = arcp -> arc_parentp; 4137c478bd9Sstevel@tonic-gate if (childp == parentp || (childp->cycleno != 0 && 4147c478bd9Sstevel@tonic-gate parentp->cycleno == childp->cycleno)) { 4157c478bd9Sstevel@tonic-gate /* 4167c478bd9Sstevel@tonic-gate * selfcall or call among siblings 4177c478bd9Sstevel@tonic-gate */ 41892ed1782Smike_s (void) printf( 41992ed1782Smike_s "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ", 4207c478bd9Sstevel@tonic-gate "", "", "", "", arcp->arc_count, ""); 4217c478bd9Sstevel@tonic-gate printname(parentp); 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate if (Cflag) 4247c478bd9Sstevel@tonic-gate print_demangled_name(54, parentp); 4257c478bd9Sstevel@tonic-gate 42692ed1782Smike_s (void) printf("\n"); 4277c478bd9Sstevel@tonic-gate } else { 4287c478bd9Sstevel@tonic-gate /* 4297c478bd9Sstevel@tonic-gate * regular parent of child 4307c478bd9Sstevel@tonic-gate */ 43192ed1782Smike_s (void) printf( 43292ed1782Smike_s "%6.6s %5.5s %7.2f %11.2f %7lld/%-7lld ", "", 4337c478bd9Sstevel@tonic-gate "", arcp->arc_time / hz, arcp->arc_childtime / hz, 4347c478bd9Sstevel@tonic-gate arcp->arc_count, cycleheadp->ncall); 4357c478bd9Sstevel@tonic-gate printname(parentp); 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate if (Cflag) 4387c478bd9Sstevel@tonic-gate print_demangled_name(54, parentp); 4397c478bd9Sstevel@tonic-gate 44092ed1782Smike_s (void) printf("\n"); 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate void 4467c478bd9Sstevel@tonic-gate printchildren(nltype *parentp) 4477c478bd9Sstevel@tonic-gate { 4487c478bd9Sstevel@tonic-gate nltype *childp; 4497c478bd9Sstevel@tonic-gate arctype *arcp; 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate sortchildren(parentp); 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate for (arcp = parentp->children; arcp; arcp = arcp->arc_childlist) { 4547c478bd9Sstevel@tonic-gate childp = arcp->arc_childp; 4557c478bd9Sstevel@tonic-gate if (childp == parentp || (childp->cycleno != 0 && 4567c478bd9Sstevel@tonic-gate childp->cycleno == parentp->cycleno)) { 4577c478bd9Sstevel@tonic-gate /* 4587c478bd9Sstevel@tonic-gate * self call or call to sibling 4597c478bd9Sstevel@tonic-gate */ 46092ed1782Smike_s (void) printf( 46192ed1782Smike_s "%6.6s %5.5s %7.7s %11.11s %7lld %7.7s ", 4627c478bd9Sstevel@tonic-gate "", "", "", "", arcp->arc_count, ""); 4637c478bd9Sstevel@tonic-gate printname(childp); 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate if (Cflag) 4667c478bd9Sstevel@tonic-gate print_demangled_name(54, childp); 4677c478bd9Sstevel@tonic-gate 46892ed1782Smike_s (void) printf("\n"); 4697c478bd9Sstevel@tonic-gate } else { 4707c478bd9Sstevel@tonic-gate /* 4717c478bd9Sstevel@tonic-gate * regular child of parent 4727c478bd9Sstevel@tonic-gate */ 4737c478bd9Sstevel@tonic-gate if (childp->cyclehead) 47492ed1782Smike_s (void) printf("%6.6s %5.5s %7.2f %11.2f " 4757c478bd9Sstevel@tonic-gate "%7lld/%-7lld ", "", "", 4767c478bd9Sstevel@tonic-gate arcp->arc_time / hz, 4777c478bd9Sstevel@tonic-gate arcp->arc_childtime / hz, arcp->arc_count, 4787c478bd9Sstevel@tonic-gate childp->cyclehead->ncall); 4797c478bd9Sstevel@tonic-gate else 48092ed1782Smike_s (void) printf("%6.6s %5.5s %7.2f %11.2f " 4817c478bd9Sstevel@tonic-gate "%7lld %7.7s ", 4827c478bd9Sstevel@tonic-gate "", "", arcp->arc_time / hz, 4837c478bd9Sstevel@tonic-gate arcp->arc_childtime / hz, arcp->arc_count, 4847c478bd9Sstevel@tonic-gate ""); 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate printname(childp); 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate if (Cflag) 4897c478bd9Sstevel@tonic-gate print_demangled_name(54, childp); 4907c478bd9Sstevel@tonic-gate 49192ed1782Smike_s (void) printf("\n"); 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate void 4977c478bd9Sstevel@tonic-gate printname(nltype *selfp) 4987c478bd9Sstevel@tonic-gate { 499*b9bd317cSab196087 const char *c; 5007c478bd9Sstevel@tonic-gate c = demangled_name(selfp); 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate if (selfp->name != 0) { 5037c478bd9Sstevel@tonic-gate if (!Cflag) 50492ed1782Smike_s (void) printf("%s", selfp->name); 5057c478bd9Sstevel@tonic-gate else 50692ed1782Smike_s (void) printf("%s", c); 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate #ifdef DEBUG 5097c478bd9Sstevel@tonic-gate if (debug & DFNDEBUG) 51092ed1782Smike_s (void) printf("{%d} ", selfp->toporder); 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate if (debug & PROPDEBUG) 51392ed1782Smike_s (void) printf("%5.2f%% ", selfp->propfraction); 51492ed1782Smike_s #endif /* DEBUG */ 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate if (selfp->cycleno != 0) 51892ed1782Smike_s (void) printf("\t<cycle %d>", selfp->cycleno); 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate if (selfp->index != 0) { 5217c478bd9Sstevel@tonic-gate if (selfp->printflag) 52292ed1782Smike_s (void) printf(" [%d]", selfp->index); 5237c478bd9Sstevel@tonic-gate else 52492ed1782Smike_s (void) printf(" (%d)", selfp->index); 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate void 5297c478bd9Sstevel@tonic-gate print_demangled_name(int n, nltype *selfp) 5307c478bd9Sstevel@tonic-gate { 5317c478bd9Sstevel@tonic-gate char *c; 5327c478bd9Sstevel@tonic-gate int i; 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate c = selfp->name; 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate if (strcmp(c, demangled_name(selfp)) == 0) 5377c478bd9Sstevel@tonic-gate return; 5387c478bd9Sstevel@tonic-gate else { 53992ed1782Smike_s (void) printf("\n"); 5407c478bd9Sstevel@tonic-gate for (i = 1; i < n; i++) 54192ed1782Smike_s (void) printf(" "); 54292ed1782Smike_s (void) printf("[%s]", selfp->name); 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate void 5477c478bd9Sstevel@tonic-gate sortchildren(nltype *parentp) 5487c478bd9Sstevel@tonic-gate { 5497c478bd9Sstevel@tonic-gate arctype *arcp; 5507c478bd9Sstevel@tonic-gate arctype *detachedp; 5517c478bd9Sstevel@tonic-gate arctype sorted; 5527c478bd9Sstevel@tonic-gate arctype *prevp; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate /* 5557c478bd9Sstevel@tonic-gate * unlink children from parent, 5567c478bd9Sstevel@tonic-gate * then insertion sort back on to sorted's children. 5577c478bd9Sstevel@tonic-gate * *arcp the arc you have detached and are inserting. 5587c478bd9Sstevel@tonic-gate * *detachedp the rest of the arcs to be sorted. 5597c478bd9Sstevel@tonic-gate * sorted arc list onto which you insertion sort. 5607c478bd9Sstevel@tonic-gate * *prevp arc before the arc you are comparing. 5617c478bd9Sstevel@tonic-gate */ 5627c478bd9Sstevel@tonic-gate sorted.arc_childlist = 0; 5637c478bd9Sstevel@tonic-gate 56492ed1782Smike_s /* LINTED: warning: assignment operator */ 5657c478bd9Sstevel@tonic-gate for ((arcp = parentp->children) && (detachedp = arcp->arc_childlist); 5667c478bd9Sstevel@tonic-gate arcp; 56792ed1782Smike_s /* LINTED: warning: assignment operator */ 5687c478bd9Sstevel@tonic-gate (arcp = detachedp) && (detachedp = detachedp->arc_childlist)) { 5697c478bd9Sstevel@tonic-gate /* 5707c478bd9Sstevel@tonic-gate * consider *arcp as disconnected 5717c478bd9Sstevel@tonic-gate * insert it into sorted 5727c478bd9Sstevel@tonic-gate */ 5737c478bd9Sstevel@tonic-gate for (prevp = &sorted; prevp->arc_childlist; 5747c478bd9Sstevel@tonic-gate prevp = prevp->arc_childlist) { 5757c478bd9Sstevel@tonic-gate if (arccmp(arcp, prevp->arc_childlist) != LESSTHAN) 5767c478bd9Sstevel@tonic-gate break; 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate arcp->arc_childlist = prevp->arc_childlist; 5807c478bd9Sstevel@tonic-gate prevp->arc_childlist = arcp; 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate /* 5847c478bd9Sstevel@tonic-gate * reattach sorted children to parent 5857c478bd9Sstevel@tonic-gate */ 5867c478bd9Sstevel@tonic-gate parentp->children = sorted.arc_childlist; 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate void 5907c478bd9Sstevel@tonic-gate sortparents(nltype *childp) 5917c478bd9Sstevel@tonic-gate { 5927c478bd9Sstevel@tonic-gate arctype *arcp; 5937c478bd9Sstevel@tonic-gate arctype *detachedp; 5947c478bd9Sstevel@tonic-gate arctype sorted; 5957c478bd9Sstevel@tonic-gate arctype *prevp; 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate /* 5987c478bd9Sstevel@tonic-gate * unlink parents from child, 5997c478bd9Sstevel@tonic-gate * then insertion sort back on to sorted's parents. 6007c478bd9Sstevel@tonic-gate * *arcp the arc you have detached and are inserting. 6017c478bd9Sstevel@tonic-gate * *detachedp the rest of the arcs to be sorted. 6027c478bd9Sstevel@tonic-gate * sorted arc list onto which you insertion sort. 6037c478bd9Sstevel@tonic-gate * *prevp arc before the arc you are comparing. 6047c478bd9Sstevel@tonic-gate */ 6057c478bd9Sstevel@tonic-gate sorted.arc_parentlist = 0; 6067c478bd9Sstevel@tonic-gate 60792ed1782Smike_s /* LINTED: warning: assignment operator */ 6087c478bd9Sstevel@tonic-gate for ((arcp = childp->parents) && (detachedp = arcp->arc_parentlist); 6097c478bd9Sstevel@tonic-gate arcp; 61092ed1782Smike_s /* LINTED: warning: assignment operator */ 6117c478bd9Sstevel@tonic-gate (arcp = detachedp) && (detachedp = detachedp->arc_parentlist)) { 6127c478bd9Sstevel@tonic-gate /* 6137c478bd9Sstevel@tonic-gate * consider *arcp as disconnected 6147c478bd9Sstevel@tonic-gate * insert it into sorted 6157c478bd9Sstevel@tonic-gate */ 6167c478bd9Sstevel@tonic-gate for (prevp = &sorted; prevp->arc_parentlist; 6177c478bd9Sstevel@tonic-gate prevp = prevp->arc_parentlist) { 6187c478bd9Sstevel@tonic-gate if (arccmp(arcp, prevp->arc_parentlist) != GREATERTHAN) 6197c478bd9Sstevel@tonic-gate break; 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate arcp->arc_parentlist = prevp->arc_parentlist; 6227c478bd9Sstevel@tonic-gate prevp->arc_parentlist = arcp; 6237c478bd9Sstevel@tonic-gate } 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate /* 6267c478bd9Sstevel@tonic-gate * reattach sorted arcs to child 6277c478bd9Sstevel@tonic-gate */ 6287c478bd9Sstevel@tonic-gate childp->parents = sorted.arc_parentlist; 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate void 6327c478bd9Sstevel@tonic-gate printcycle(nltype *cyclep) 6337c478bd9Sstevel@tonic-gate { 6347c478bd9Sstevel@tonic-gate char kirkbuffer[BUFSIZ]; 6357c478bd9Sstevel@tonic-gate 63692ed1782Smike_s (void) sprintf(kirkbuffer, "[%d]", cyclep->index); 63792ed1782Smike_s (void) printf("%-6.6s %5.1f %7.2f %11.2f %7lld", kirkbuffer, 6387c478bd9Sstevel@tonic-gate 100 * (cyclep->propself + cyclep->propchild) / printtime, 6397c478bd9Sstevel@tonic-gate cyclep -> propself / hz, cyclep -> propchild / hz, 6407c478bd9Sstevel@tonic-gate cyclep -> ncall); 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate if (cyclep->selfcalls != 0) 64392ed1782Smike_s (void) printf("+%-7lld", cyclep->selfcalls); 6447c478bd9Sstevel@tonic-gate else 64592ed1782Smike_s (void) printf(" %7.7s", ""); 6467c478bd9Sstevel@tonic-gate 64792ed1782Smike_s (void) printf(" <cycle %d as a whole>\t[%d]\n", cyclep->cycleno, 6487c478bd9Sstevel@tonic-gate cyclep->index); 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate /* 6527c478bd9Sstevel@tonic-gate * print the members of a cycle 6537c478bd9Sstevel@tonic-gate */ 6547c478bd9Sstevel@tonic-gate void 6557c478bd9Sstevel@tonic-gate printmembers(nltype *cyclep) 6567c478bd9Sstevel@tonic-gate { 6577c478bd9Sstevel@tonic-gate nltype *memberp; 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate sortmembers(cyclep); 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate for (memberp = cyclep->cnext; memberp; memberp = memberp->cnext) { 66292ed1782Smike_s (void) printf("%6.6s %5.5s %7.2f %11.2f %7lld", "", "", 6637c478bd9Sstevel@tonic-gate memberp->propself / hz, memberp->propchild / hz, 6647c478bd9Sstevel@tonic-gate memberp->ncall); 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate if (memberp->selfcalls != 0) 66792ed1782Smike_s (void) printf("+%-7lld", memberp->selfcalls); 6687c478bd9Sstevel@tonic-gate else 66992ed1782Smike_s (void) printf(" %7.7s", ""); 6707c478bd9Sstevel@tonic-gate 67192ed1782Smike_s (void) printf(" "); 6727c478bd9Sstevel@tonic-gate printname(memberp); 6737c478bd9Sstevel@tonic-gate if (Cflag) 6747c478bd9Sstevel@tonic-gate print_demangled_name(54, memberp); 67592ed1782Smike_s (void) printf("\n"); 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate /* 6807c478bd9Sstevel@tonic-gate * sort members of a cycle 6817c478bd9Sstevel@tonic-gate */ 6827c478bd9Sstevel@tonic-gate void 6837c478bd9Sstevel@tonic-gate sortmembers(nltype *cyclep) 6847c478bd9Sstevel@tonic-gate { 6857c478bd9Sstevel@tonic-gate nltype *todo; 6867c478bd9Sstevel@tonic-gate nltype *doing; 6877c478bd9Sstevel@tonic-gate nltype *prev; 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate /* 6907c478bd9Sstevel@tonic-gate * detach cycle members from cyclehead, 6917c478bd9Sstevel@tonic-gate * and insertion sort them back on. 6927c478bd9Sstevel@tonic-gate */ 6937c478bd9Sstevel@tonic-gate todo = cyclep->cnext; 6947c478bd9Sstevel@tonic-gate cyclep->cnext = 0; 6957c478bd9Sstevel@tonic-gate 69692ed1782Smike_s /* LINTED: warning: assignment operator */ 6977c478bd9Sstevel@tonic-gate for ((doing = todo) && (todo = doing->cnext); 69892ed1782Smike_s doing; 69992ed1782Smike_s /* LINTED: warning: assignment operator */ 70092ed1782Smike_s (doing = todo) && (todo = doing->cnext)) { 7017c478bd9Sstevel@tonic-gate for (prev = cyclep; prev->cnext; prev = prev->cnext) { 7027c478bd9Sstevel@tonic-gate if (membercmp(doing, prev->cnext) == GREATERTHAN) 7037c478bd9Sstevel@tonic-gate break; 7047c478bd9Sstevel@tonic-gate } 7057c478bd9Sstevel@tonic-gate doing->cnext = prev->cnext; 7067c478bd9Sstevel@tonic-gate prev->cnext = doing; 7077c478bd9Sstevel@tonic-gate } 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate /* 7117c478bd9Sstevel@tonic-gate * major sort is on propself + propchild, 7127c478bd9Sstevel@tonic-gate * next is sort on ncalls + selfcalls. 7137c478bd9Sstevel@tonic-gate */ 7147c478bd9Sstevel@tonic-gate int 7157c478bd9Sstevel@tonic-gate membercmp(nltype *this, nltype *that) 7167c478bd9Sstevel@tonic-gate { 7177c478bd9Sstevel@tonic-gate double thistime = this->propself + this->propchild; 7187c478bd9Sstevel@tonic-gate double thattime = that->propself + that->propchild; 7197c478bd9Sstevel@tonic-gate actype thiscalls = this->ncall + this->selfcalls; 7207c478bd9Sstevel@tonic-gate actype thatcalls = that->ncall + that->selfcalls; 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate if (thistime > thattime) 7237c478bd9Sstevel@tonic-gate return (GREATERTHAN); 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate if (thistime < thattime) 7267c478bd9Sstevel@tonic-gate return (LESSTHAN); 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate if (thiscalls > thatcalls) 7297c478bd9Sstevel@tonic-gate return (GREATERTHAN); 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate if (thiscalls < thatcalls) 7327c478bd9Sstevel@tonic-gate return (LESSTHAN); 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate return (EQUALTO); 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate /* 7387c478bd9Sstevel@tonic-gate * compare two arcs to/from the same child/parent. 7397c478bd9Sstevel@tonic-gate * - if one arc is a self arc, it's least. 7407c478bd9Sstevel@tonic-gate * - if one arc is within a cycle, it's less than. 7417c478bd9Sstevel@tonic-gate * - if both arcs are within a cycle, compare arc counts. 7427c478bd9Sstevel@tonic-gate * - if neither arc is within a cycle, compare with 7437c478bd9Sstevel@tonic-gate * arc_time + arc_childtime as major key 7447c478bd9Sstevel@tonic-gate * arc count as minor key 7457c478bd9Sstevel@tonic-gate */ 7467c478bd9Sstevel@tonic-gate int 7477c478bd9Sstevel@tonic-gate arccmp(arctype *thisp, arctype *thatp) 7487c478bd9Sstevel@tonic-gate { 7497c478bd9Sstevel@tonic-gate nltype *thisparentp = thisp->arc_parentp; 7507c478bd9Sstevel@tonic-gate nltype *thischildp = thisp->arc_childp; 7517c478bd9Sstevel@tonic-gate nltype *thatparentp = thatp->arc_parentp; 7527c478bd9Sstevel@tonic-gate nltype *thatchildp = thatp->arc_childp; 7537c478bd9Sstevel@tonic-gate double thistime; 7547c478bd9Sstevel@tonic-gate double thattime; 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate #ifdef DEBUG 7577c478bd9Sstevel@tonic-gate if (debug & TIMEDEBUG) { 75892ed1782Smike_s (void) printf("[arccmp] "); 7597c478bd9Sstevel@tonic-gate printname(thisparentp); 76092ed1782Smike_s (void) printf(" calls "); 7617c478bd9Sstevel@tonic-gate printname(thischildp); 76292ed1782Smike_s (void) printf(" %f + %f %lld/%lld\n", thisp->arc_time, 7637c478bd9Sstevel@tonic-gate thisp->arc_childtime, thisp->arc_count, 7647c478bd9Sstevel@tonic-gate thischildp->ncall); 76592ed1782Smike_s (void) printf("[arccmp] "); 7667c478bd9Sstevel@tonic-gate printname(thatparentp); 76792ed1782Smike_s (void) printf(" calls "); 7687c478bd9Sstevel@tonic-gate printname(thatchildp); 76992ed1782Smike_s (void) printf(" %f + %f %lld/%lld\n", thatp->arc_time, 7707c478bd9Sstevel@tonic-gate thatp->arc_childtime, thatp->arc_count, 7717c478bd9Sstevel@tonic-gate thatchildp->ncall); 77292ed1782Smike_s (void) printf("\n"); 7737c478bd9Sstevel@tonic-gate } 77492ed1782Smike_s #endif /* DEBUG */ 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate if (thisparentp == thischildp) { 7777c478bd9Sstevel@tonic-gate /* 7787c478bd9Sstevel@tonic-gate * this is a self call 7797c478bd9Sstevel@tonic-gate */ 7807c478bd9Sstevel@tonic-gate return (LESSTHAN); 7817c478bd9Sstevel@tonic-gate } 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate if (thatparentp == thatchildp) { 7847c478bd9Sstevel@tonic-gate /* 7857c478bd9Sstevel@tonic-gate * that is a self call 7867c478bd9Sstevel@tonic-gate */ 7877c478bd9Sstevel@tonic-gate return (GREATERTHAN); 7887c478bd9Sstevel@tonic-gate } 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate if (thisparentp->cycleno != 0 && thischildp->cycleno != 0 && 7917c478bd9Sstevel@tonic-gate thisparentp->cycleno == thischildp->cycleno) { 7927c478bd9Sstevel@tonic-gate /* 7937c478bd9Sstevel@tonic-gate * this is a call within a cycle 7947c478bd9Sstevel@tonic-gate */ 7957c478bd9Sstevel@tonic-gate if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 && 7967c478bd9Sstevel@tonic-gate thatparentp->cycleno == thatchildp->cycleno) { 7977c478bd9Sstevel@tonic-gate /* 7987c478bd9Sstevel@tonic-gate * that is a call within the cycle, too 7997c478bd9Sstevel@tonic-gate */ 8007c478bd9Sstevel@tonic-gate if (thisp->arc_count < thatp->arc_count) 8017c478bd9Sstevel@tonic-gate return (LESSTHAN); 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate if (thisp->arc_count > thatp->arc_count) 8047c478bd9Sstevel@tonic-gate return (GREATERTHAN); 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate return (EQUALTO); 8077c478bd9Sstevel@tonic-gate } else { 8087c478bd9Sstevel@tonic-gate /* 8097c478bd9Sstevel@tonic-gate * that isn't a call within the cycle 8107c478bd9Sstevel@tonic-gate */ 8117c478bd9Sstevel@tonic-gate return (LESSTHAN); 8127c478bd9Sstevel@tonic-gate } 8137c478bd9Sstevel@tonic-gate } else { 8147c478bd9Sstevel@tonic-gate /* 8157c478bd9Sstevel@tonic-gate * this isn't a call within a cycle 8167c478bd9Sstevel@tonic-gate */ 8177c478bd9Sstevel@tonic-gate if (thatparentp->cycleno != 0 && thatchildp->cycleno != 0 && 8187c478bd9Sstevel@tonic-gate thatparentp->cycleno == thatchildp->cycleno) { 8197c478bd9Sstevel@tonic-gate /* 8207c478bd9Sstevel@tonic-gate * that is a call within a cycle 8217c478bd9Sstevel@tonic-gate */ 8227c478bd9Sstevel@tonic-gate return (GREATERTHAN); 8237c478bd9Sstevel@tonic-gate } else { 8247c478bd9Sstevel@tonic-gate /* 8257c478bd9Sstevel@tonic-gate * neither is a call within a cycle 8267c478bd9Sstevel@tonic-gate */ 8277c478bd9Sstevel@tonic-gate thistime = thisp->arc_time + thisp->arc_childtime; 8287c478bd9Sstevel@tonic-gate thattime = thatp->arc_time + thatp->arc_childtime; 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate if (thistime < thattime) 8317c478bd9Sstevel@tonic-gate return (LESSTHAN); 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate if (thistime > thattime) 8347c478bd9Sstevel@tonic-gate return (GREATERTHAN); 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate if (thisp->arc_count < thatp->arc_count) 8377c478bd9Sstevel@tonic-gate return (LESSTHAN); 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate if (thisp->arc_count > thatp->arc_count) 8407c478bd9Sstevel@tonic-gate return (GREATERTHAN); 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate return (EQUALTO); 8437c478bd9Sstevel@tonic-gate } 8447c478bd9Sstevel@tonic-gate } 8457c478bd9Sstevel@tonic-gate } 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate void 8487c478bd9Sstevel@tonic-gate printblurb(char *blurbname) 8497c478bd9Sstevel@tonic-gate { 8507c478bd9Sstevel@tonic-gate FILE *blurbfile; 8517c478bd9Sstevel@tonic-gate int input; 8527c478bd9Sstevel@tonic-gate 85367298654Sdamico blurbfile = fopen(blurbname, "r"); 8547c478bd9Sstevel@tonic-gate if (blurbfile == NULL) { 85567298654Sdamico perror(blurbname); 8567c478bd9Sstevel@tonic-gate return; 8577c478bd9Sstevel@tonic-gate } 8587c478bd9Sstevel@tonic-gate 8597c478bd9Sstevel@tonic-gate while ((input = getc(blurbfile)) != EOF) 86092ed1782Smike_s (void) putchar(input); 8617c478bd9Sstevel@tonic-gate 86292ed1782Smike_s (void) fclose(blurbfile); 8637c478bd9Sstevel@tonic-gate } 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate char *s1, *s2; 8667c478bd9Sstevel@tonic-gate 86792ed1782Smike_s static int 86892ed1782Smike_s namecmp(const void *arg1, const void *arg2) 8697c478bd9Sstevel@tonic-gate { 87092ed1782Smike_s nltype **npp1 = (nltype **)arg1; 87192ed1782Smike_s nltype **npp2 = (nltype **)arg2; 87292ed1782Smike_s 8737c478bd9Sstevel@tonic-gate if (!Cflag) 8747c478bd9Sstevel@tonic-gate return (strcmp((*npp1)->name, (*npp2)->name)); 8757c478bd9Sstevel@tonic-gate else { 8767c478bd9Sstevel@tonic-gate striped_name(s1, npp1); 8777c478bd9Sstevel@tonic-gate striped_name(s2, npp2); 8787c478bd9Sstevel@tonic-gate return (strcmp(s1, s2)); 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate } 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate void 8837c478bd9Sstevel@tonic-gate striped_name(char *s, nltype **npp) 8847c478bd9Sstevel@tonic-gate { 885*b9bd317cSab196087 const char *d; 886*b9bd317cSab196087 char *c; 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate c = (char *)s; 8897c478bd9Sstevel@tonic-gate d = demangled_name(*npp); 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate while ((*d != '(') && (*d != '\0')) { 8927c478bd9Sstevel@tonic-gate if (*d != ':') 8937c478bd9Sstevel@tonic-gate *c++ = *d++; 8947c478bd9Sstevel@tonic-gate else 8957c478bd9Sstevel@tonic-gate d++; 8967c478bd9Sstevel@tonic-gate } 8977c478bd9Sstevel@tonic-gate *c = '\0'; 8987c478bd9Sstevel@tonic-gate } 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate /* 9017c478bd9Sstevel@tonic-gate * Checks if the current symbol name is the same as its neighbour and 9027c478bd9Sstevel@tonic-gate * returns TRUE if it is. 9037c478bd9Sstevel@tonic-gate */ 9047c478bd9Sstevel@tonic-gate static bool 9057c478bd9Sstevel@tonic-gate does_clash(nltype **nlp, int ndx, int nnames) 9067c478bd9Sstevel@tonic-gate { 9077c478bd9Sstevel@tonic-gate /* 9087c478bd9Sstevel@tonic-gate * same as previous (if there's one) ? 9097c478bd9Sstevel@tonic-gate */ 9107c478bd9Sstevel@tonic-gate if (ndx && (strcmp(nlp[ndx]->name, nlp[ndx-1]->name) == 0)) 9117c478bd9Sstevel@tonic-gate return (TRUE); 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate /* 9147c478bd9Sstevel@tonic-gate * same as next (if there's one) ? 9157c478bd9Sstevel@tonic-gate */ 9167c478bd9Sstevel@tonic-gate if ((ndx < (nnames - 1)) && 9177c478bd9Sstevel@tonic-gate (strcmp(nlp[ndx]->name, nlp[ndx+1]->name) == 0)) { 9187c478bd9Sstevel@tonic-gate return (TRUE); 9197c478bd9Sstevel@tonic-gate } 9207c478bd9Sstevel@tonic-gate 9217c478bd9Sstevel@tonic-gate return (FALSE); 9227c478bd9Sstevel@tonic-gate } 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate void 9257c478bd9Sstevel@tonic-gate printmodules() 9267c478bd9Sstevel@tonic-gate { 9277c478bd9Sstevel@tonic-gate mod_info_t *mi; 9287c478bd9Sstevel@tonic-gate 92992ed1782Smike_s (void) printf("\f\nObject modules\n\n"); 9307c478bd9Sstevel@tonic-gate for (mi = &modules; mi; mi = mi->next) 93192ed1782Smike_s (void) printf(" %d: %s\n", mi->id, mi->name); 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate #define IDFMT(id) ((id) < 10 ? 1 : 2) 9357c478bd9Sstevel@tonic-gate #define NMFMT(id) ((id) < 10 ? 17 : 16) 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate void 9387c478bd9Sstevel@tonic-gate printindex() 9397c478bd9Sstevel@tonic-gate { 9407c478bd9Sstevel@tonic-gate nltype **namesortnlp; 9417c478bd9Sstevel@tonic-gate nltype *nlp; 9427c478bd9Sstevel@tonic-gate int index, nnames, todo, i, j; 9437c478bd9Sstevel@tonic-gate char peterbuffer[BUFSIZ]; 9447c478bd9Sstevel@tonic-gate mod_info_t *mi; 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate /* 9477c478bd9Sstevel@tonic-gate * Now, sort regular function name alphabetically 9487c478bd9Sstevel@tonic-gate * to create an index. 9497c478bd9Sstevel@tonic-gate */ 9507c478bd9Sstevel@tonic-gate namesortnlp = calloc(total_names + ncycle, sizeof (nltype *)); 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate if (namesortnlp == NULL) 95392ed1782Smike_s (void) fprintf(stderr, "%s: ran out of memory for sorting\n", 95492ed1782Smike_s whoami); 9557c478bd9Sstevel@tonic-gate 9567c478bd9Sstevel@tonic-gate nnames = 0; 9577c478bd9Sstevel@tonic-gate for (mi = &modules; mi; mi = mi->next) { 9587c478bd9Sstevel@tonic-gate for (index = 0; index < mi->nname; index++) { 9597c478bd9Sstevel@tonic-gate if (zflag == 0 && (mi->nl[index]).ncall == 0 && 9607c478bd9Sstevel@tonic-gate (mi->nl[index]).time == 0) { 9617c478bd9Sstevel@tonic-gate continue; 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate /* 9657c478bd9Sstevel@tonic-gate * Do not print certain special symbols, like 9667c478bd9Sstevel@tonic-gate * PRF_EXTSYM, etc. even if zflag was on. 9677c478bd9Sstevel@tonic-gate */ 9687c478bd9Sstevel@tonic-gate if (is_special_sym(&(mi->nl[index]))) 9697c478bd9Sstevel@tonic-gate continue; 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate namesortnlp[nnames++] = &(mi->nl[index]); 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate if (Cflag) { 9767c478bd9Sstevel@tonic-gate s1 = malloc(500 * sizeof (char)); 9777c478bd9Sstevel@tonic-gate s2 = malloc(500 * sizeof (char)); 9787c478bd9Sstevel@tonic-gate } 9797c478bd9Sstevel@tonic-gate 98092ed1782Smike_s qsort(namesortnlp, nnames, sizeof (nltype *), namecmp); 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate for (index = 1, todo = nnames; index <= ncycle; index++) 9837c478bd9Sstevel@tonic-gate namesortnlp[todo++] = &cyclenl[index]; 9847c478bd9Sstevel@tonic-gate 98592ed1782Smike_s (void) printf("\f\nIndex by function name\n\n"); 9867c478bd9Sstevel@tonic-gate 9877c478bd9Sstevel@tonic-gate if (!Cflag) 9887c478bd9Sstevel@tonic-gate index = (todo + 2) / 3; 9897c478bd9Sstevel@tonic-gate else 9907c478bd9Sstevel@tonic-gate index = todo; 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate for (i = 0; i < index; i++) { 9937c478bd9Sstevel@tonic-gate if (!Cflag) { 9947c478bd9Sstevel@tonic-gate for (j = i; j < todo; j += index) { 9957c478bd9Sstevel@tonic-gate nlp = namesortnlp[j]; 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate if (nlp->printflag) { 99892ed1782Smike_s (void) sprintf(peterbuffer, 9997c478bd9Sstevel@tonic-gate "[%d]", nlp->index); 10007c478bd9Sstevel@tonic-gate } else { 100192ed1782Smike_s (void) sprintf(peterbuffer, 10027c478bd9Sstevel@tonic-gate "(%d)", nlp->index); 10037c478bd9Sstevel@tonic-gate } 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate if (j < nnames) { 10067c478bd9Sstevel@tonic-gate if (does_clash(namesortnlp, 10077c478bd9Sstevel@tonic-gate j, nnames)) { 100892ed1782Smike_s (void) printf( 100992ed1782Smike_s "%6.6s %*d:%-*.*s", 10107c478bd9Sstevel@tonic-gate peterbuffer, 10117c478bd9Sstevel@tonic-gate IDFMT(nlp->module->id), 10127c478bd9Sstevel@tonic-gate nlp->module->id, 10137c478bd9Sstevel@tonic-gate NMFMT(nlp->module->id), 10147c478bd9Sstevel@tonic-gate NMFMT(nlp->module->id), 10157c478bd9Sstevel@tonic-gate nlp->name); 10167c478bd9Sstevel@tonic-gate } else { 101792ed1782Smike_s (void) printf("%6.6s %-19.19s", 10187c478bd9Sstevel@tonic-gate peterbuffer, nlp->name); 10197c478bd9Sstevel@tonic-gate } 10207c478bd9Sstevel@tonic-gate } else { 102192ed1782Smike_s (void) printf("%6.6s ", peterbuffer); 102292ed1782Smike_s (void) sprintf(peterbuffer, 10237c478bd9Sstevel@tonic-gate "<cycle %d>", nlp->cycleno); 102492ed1782Smike_s (void) printf("%-19.19s", peterbuffer); 10257c478bd9Sstevel@tonic-gate } 10267c478bd9Sstevel@tonic-gate } 10277c478bd9Sstevel@tonic-gate } else { 10287c478bd9Sstevel@tonic-gate nlp = namesortnlp[i]; 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate if (nlp->printflag) 103192ed1782Smike_s (void) sprintf(peterbuffer, "[%d]", nlp->index); 10327c478bd9Sstevel@tonic-gate else 103392ed1782Smike_s (void) sprintf(peterbuffer, "(%d)", nlp->index); 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate if (i < nnames) { 1036*b9bd317cSab196087 const char *d = demangled_name(nlp); 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate if (does_clash(namesortnlp, i, nnames)) { 103992ed1782Smike_s (void) printf("%6.6s %d:%s\n", 104092ed1782Smike_s peterbuffer, nlp->module->id, d); 10417c478bd9Sstevel@tonic-gate } else 104292ed1782Smike_s (void) printf("%6.6s %s\n", peterbuffer, 104392ed1782Smike_s d); 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate if (d != nlp->name) 104692ed1782Smike_s (void) printf("%6.6s [%s]", "", 104792ed1782Smike_s nlp->name); 10487c478bd9Sstevel@tonic-gate } else { 104992ed1782Smike_s (void) printf("%6.6s ", peterbuffer); 105092ed1782Smike_s (void) sprintf(peterbuffer, "<cycle %d>", 10517c478bd9Sstevel@tonic-gate nlp->cycleno); 105292ed1782Smike_s (void) printf("%-33.33s", peterbuffer); 10537c478bd9Sstevel@tonic-gate } 10547c478bd9Sstevel@tonic-gate } 105592ed1782Smike_s (void) printf("\n"); 10567c478bd9Sstevel@tonic-gate } 10577c478bd9Sstevel@tonic-gate free(namesortnlp); 10587c478bd9Sstevel@tonic-gate } 1059