1331722Seadler/* 21590Srgrimes * Copyright (c) 1983, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 30105243Scharnier#if 0 311590Srgrimes#ifndef lint 321590Srgrimesstatic char sccsid[] = "@(#)printgprof.c 8.1 (Berkeley) 6/6/93"; 33105243Scharnier#endif /* not lint */ 3427313Scharnier#endif 35105243Scharnier 3699112Sobrien#include <sys/cdefs.h> 3799112Sobrien__FBSDID("$FreeBSD$"); 381590Srgrimes 3927313Scharnier#include <err.h> 40129657Sstefanf#include <string.h> 41129657Sstefanf 421590Srgrimes#include "gprof.h" 431590Srgrimes#include "pathnames.h" 441590Srgrimes 45246783Scharnierint namecmp(const void *, const void *); 46246783Scharnierint timecmp(const void *, const void *); 47246783Scharnier 48105243Scharniervoid 49246783Scharnierprintprof(void) 501590Srgrimes{ 511590Srgrimes register nltype *np; 521590Srgrimes nltype **sortednlp; 53246783Scharnier int idx; 541590Srgrimes 551590Srgrimes actime = 0.0; 561590Srgrimes printf( "\f\n" ); 571590Srgrimes flatprofheader(); 581590Srgrimes /* 591590Srgrimes * Sort the symbol table in by time 601590Srgrimes */ 611590Srgrimes sortednlp = (nltype **) calloc( nname , sizeof(nltype *) ); 62105243Scharnier if ( sortednlp == (nltype **) 0 ) 63105243Scharnier errx( 1 , "[printprof] ran out of memory for time sorting" ); 64246783Scharnier for ( idx = 0 ; idx < nname ; idx += 1 ) { 65246783Scharnier sortednlp[ idx ] = &nl[ idx ]; 661590Srgrimes } 671590Srgrimes qsort( sortednlp , nname , sizeof(nltype *) , timecmp ); 68246783Scharnier for ( idx = 0 ; idx < nname ; idx += 1 ) { 69246783Scharnier np = sortednlp[ idx ]; 701590Srgrimes flatprofline( np ); 711590Srgrimes } 721590Srgrimes actime = 0.0; 731590Srgrimes free( sortednlp ); 741590Srgrimes} 751590Srgrimes 76105243Scharnierint 77246783Scharniertimecmp(const void *v1, const void *v2) 781590Srgrimes{ 79246783Scharnier const nltype **npp1 = (const nltype **)v1; 80246783Scharnier const nltype **npp2 = (const nltype **)v2; 811590Srgrimes double timediff; 821590Srgrimes long calldiff; 831590Srgrimes 841590Srgrimes timediff = (*npp2) -> time - (*npp1) -> time; 851590Srgrimes if ( timediff > 0.0 ) 861590Srgrimes return 1 ; 871590Srgrimes if ( timediff < 0.0 ) 881590Srgrimes return -1; 891590Srgrimes calldiff = (*npp2) -> ncall - (*npp1) -> ncall; 901590Srgrimes if ( calldiff > 0 ) 911590Srgrimes return 1; 921590Srgrimes if ( calldiff < 0 ) 931590Srgrimes return -1; 941590Srgrimes return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); 951590Srgrimes} 961590Srgrimes 971590Srgrimes /* 981590Srgrimes * header for flatprofline 991590Srgrimes */ 100105243Scharniervoid 101246783Scharnierflatprofheader(void) 1021590Srgrimes{ 1038874Srgrimes 1041590Srgrimes if ( bflag ) { 1051590Srgrimes printblurb( _PATH_FLAT_BLURB ); 1061590Srgrimes } 10791018Sbde printf( "\ngranularity: each sample hit covers %g byte(s)" , 10891735Sbde scale * HISTORICAL_SCALE_2 ); 1091590Srgrimes if ( totime > 0.0 ) { 1101590Srgrimes printf( " for %.2f%% of %.2f seconds\n\n" , 1111590Srgrimes 100.0/totime , totime / hz ); 1121590Srgrimes } else { 1131590Srgrimes printf( " no time accumulated\n\n" ); 1141590Srgrimes /* 115105243Scharnier * this doesn't hurt since all the numerators will be zero. 1161590Srgrimes */ 1171590Srgrimes totime = 1.0; 1181590Srgrimes } 1191590Srgrimes printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" , 1201590Srgrimes "% " , "cumulative" , "self " , "" , "self " , "total " , "" ); 1211590Srgrimes printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" , 1221590Srgrimes "time" , "seconds " , "seconds" , "calls" , 12316227Sbde hz >= 10000000 ? "ns/call" : hz >= 10000 ? "us/call" : "ms/call" , 12416227Sbde hz >= 10000000 ? "ns/call" : hz >= 10000 ? "us/call" : "ms/call" , 12516227Sbde "name" ); 1261590Srgrimes} 1271590Srgrimes 128105243Scharniervoid 129246783Scharnierflatprofline(register nltype *np) 1301590Srgrimes{ 1311590Srgrimes 132151055Sbde if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 && 133151055Sbde np -> childtime == 0 ) { 1341590Srgrimes return; 1351590Srgrimes } 1361590Srgrimes actime += np -> time; 1372513Sbde if (hz >= 10000) 1382513Sbde printf( "%5.1f %10.3f %8.3f" , 1392513Sbde 100 * np -> time / totime , actime / hz , np -> time / hz ); 1402513Sbde else 1412513Sbde printf( "%5.1f %10.2f %8.2f" , 1422513Sbde 100 * np -> time / totime , actime / hz , np -> time / hz ); 1431590Srgrimes if ( np -> ncall != 0 ) { 14416227Sbde if (hz >= 10000000) 14591018Sbde printf( " %8ld %8.0f %8.0f " , np -> ncall , 14616227Sbde 1e9 * np -> time / hz / np -> ncall , 14716227Sbde 1e9 * ( np -> time + np -> childtime ) / hz / np -> ncall ); 14816227Sbde else if (hz >= 10000) 14991018Sbde printf( " %8ld %8.0f %8.0f " , np -> ncall , 1502513Sbde 1e6 * np -> time / hz / np -> ncall , 1512513Sbde 1e6 * ( np -> time + np -> childtime ) / hz / np -> ncall ); 1522513Sbde else 15391018Sbde printf( " %8ld %8.2f %8.2f " , np -> ncall , 1542513Sbde 1000 * np -> time / hz / np -> ncall , 1552513Sbde 1000 * ( np -> time + np -> childtime ) / hz / np -> ncall ); 156151055Sbde } else if ( np -> time != 0 || np -> childtime != 0 ) { 157151055Sbde printf( " %8ld %7.2f%% %8.8s " , np -> ncall , 158151055Sbde 100 * np -> time / ( np -> time + np -> childtime ) , "" ); 1591590Srgrimes } else { 1601590Srgrimes printf( " %8.8s %8.8s %8.8s " , "" , "" , "" ); 1611590Srgrimes } 1621590Srgrimes printname( np ); 1631590Srgrimes printf( "\n" ); 1641590Srgrimes} 1651590Srgrimes 166105243Scharniervoid 167246783Scharniergprofheader(void) 1681590Srgrimes{ 1691590Srgrimes 1701590Srgrimes if ( bflag ) { 1711590Srgrimes printblurb( _PATH_CALLG_BLURB ); 1721590Srgrimes } 17391018Sbde printf( "\ngranularity: each sample hit covers %g byte(s)" , 17491735Sbde scale * HISTORICAL_SCALE_2 ); 1751590Srgrimes if ( printtime > 0.0 ) { 1761590Srgrimes printf( " for %.2f%% of %.2f seconds\n\n" , 1771590Srgrimes 100.0/printtime , printtime / hz ); 1781590Srgrimes } else { 1791590Srgrimes printf( " no time propagated\n\n" ); 1801590Srgrimes /* 1811590Srgrimes * this doesn't hurt, since all the numerators will be 0.0 1821590Srgrimes */ 1831590Srgrimes printtime = 1.0; 1841590Srgrimes } 1851590Srgrimes printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , 1861590Srgrimes "" , "" , "" , "" , "called" , "total" , "parents"); 1871590Srgrimes printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" , 1881590Srgrimes "index" , "%time" , "self" , "descendents" , 1891590Srgrimes "called" , "self" , "name" , "index" ); 1901590Srgrimes printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , 1911590Srgrimes "" , "" , "" , "" , "called" , "total" , "children"); 1921590Srgrimes printf( "\n" ); 1931590Srgrimes} 1941590Srgrimes 195105243Scharniervoid 196246783Scharniergprofline(register nltype *np) 1971590Srgrimes{ 1981590Srgrimes char kirkbuffer[ BUFSIZ ]; 1991590Srgrimes 2001590Srgrimes sprintf( kirkbuffer , "[%d]" , np -> index ); 2011590Srgrimes printf( "%-6.6s %5.1f %7.2f %11.2f" , 2021590Srgrimes kirkbuffer , 2031590Srgrimes 100 * ( np -> propself + np -> propchild ) / printtime , 2041590Srgrimes np -> propself / hz , 2051590Srgrimes np -> propchild / hz ); 2061590Srgrimes if ( ( np -> ncall + np -> selfcalls ) != 0 ) { 20791018Sbde printf( " %7ld" , np -> npropcall ); 2081590Srgrimes if ( np -> selfcalls != 0 ) { 20991018Sbde printf( "+%-7ld " , np -> selfcalls ); 2101590Srgrimes } else { 2111590Srgrimes printf( " %7.7s " , "" ); 2121590Srgrimes } 2131590Srgrimes } else { 2141590Srgrimes printf( " %7.7s %7.7s " , "" , "" ); 2151590Srgrimes } 2161590Srgrimes printname( np ); 2171590Srgrimes printf( "\n" ); 2181590Srgrimes} 2191590Srgrimes 220105243Scharniervoid 221246783Scharnierprintgprof(nltype **timesortnlp) 2221590Srgrimes{ 223246783Scharnier int idx; 2241590Srgrimes nltype *parentp; 2251590Srgrimes 2261590Srgrimes /* 2271590Srgrimes * Print out the structured profiling list 2281590Srgrimes */ 2291590Srgrimes gprofheader(); 230246783Scharnier for ( idx = 0 ; idx < nname + ncycle ; idx ++ ) { 231246783Scharnier parentp = timesortnlp[ idx ]; 2321590Srgrimes if ( zflag == 0 && 2331590Srgrimes parentp -> ncall == 0 && 2341590Srgrimes parentp -> selfcalls == 0 && 2351590Srgrimes parentp -> propself == 0 && 2361590Srgrimes parentp -> propchild == 0 ) { 2371590Srgrimes continue; 2381590Srgrimes } 2391590Srgrimes if ( ! parentp -> printflag ) { 2401590Srgrimes continue; 2411590Srgrimes } 2421590Srgrimes if ( parentp -> name == 0 && parentp -> cycleno != 0 ) { 2431590Srgrimes /* 2441590Srgrimes * cycle header 2451590Srgrimes */ 2461590Srgrimes printcycle( parentp ); 2471590Srgrimes printmembers( parentp ); 2481590Srgrimes } else { 2491590Srgrimes printparents( parentp ); 2501590Srgrimes gprofline( parentp ); 2511590Srgrimes printchildren( parentp ); 2521590Srgrimes } 2531590Srgrimes printf( "\n" ); 2541590Srgrimes printf( "-----------------------------------------------\n" ); 2551590Srgrimes printf( "\n" ); 2561590Srgrimes } 2571590Srgrimes free( timesortnlp ); 2581590Srgrimes} 2591590Srgrimes 2601590Srgrimes /* 2611590Srgrimes * sort by decreasing propagated time 2621590Srgrimes * if times are equal, but one is a cycle header, 2631590Srgrimes * say that's first (e.g. less, i.e. -1). 2641590Srgrimes * if one's name doesn't have an underscore and the other does, 2651590Srgrimes * say the one is first. 2661590Srgrimes * all else being equal, sort by names. 2671590Srgrimes */ 2681590Srgrimesint 269246783Scharniertotalcmp(const void *v1, const void *v2) 2701590Srgrimes{ 271246783Scharnier const nltype **npp1 = (const nltype **)v1; 272246783Scharnier const nltype **npp2 = (const nltype **)v2; 273246783Scharnier register const nltype *np1 = *npp1; 274246783Scharnier register const nltype *np2 = *npp2; 2751590Srgrimes double diff; 2761590Srgrimes 2771590Srgrimes diff = ( np1 -> propself + np1 -> propchild ) 2781590Srgrimes - ( np2 -> propself + np2 -> propchild ); 2791590Srgrimes if ( diff < 0.0 ) 2801590Srgrimes return 1; 2811590Srgrimes if ( diff > 0.0 ) 2821590Srgrimes return -1; 2838874Srgrimes if ( np1 -> name == 0 && np1 -> cycleno != 0 ) 2841590Srgrimes return -1; 2851590Srgrimes if ( np2 -> name == 0 && np2 -> cycleno != 0 ) 2861590Srgrimes return 1; 2871590Srgrimes if ( np1 -> name == 0 ) 2881590Srgrimes return -1; 2891590Srgrimes if ( np2 -> name == 0 ) 2901590Srgrimes return 1; 2911590Srgrimes if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' ) 2921590Srgrimes return -1; 2931590Srgrimes if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' ) 2941590Srgrimes return 1; 2951590Srgrimes if ( np1 -> ncall > np2 -> ncall ) 2961590Srgrimes return -1; 2978874Srgrimes if ( np1 -> ncall < np2 -> ncall ) 2981590Srgrimes return 1; 2991590Srgrimes return strcmp( np1 -> name , np2 -> name ); 3001590Srgrimes} 3011590Srgrimes 302105243Scharniervoid 303246783Scharnierprintparents(nltype *childp) 3041590Srgrimes{ 3051590Srgrimes nltype *parentp; 3061590Srgrimes arctype *arcp; 3071590Srgrimes nltype *cycleheadp; 3081590Srgrimes 3091590Srgrimes if ( childp -> cyclehead != 0 ) { 3101590Srgrimes cycleheadp = childp -> cyclehead; 3111590Srgrimes } else { 3121590Srgrimes cycleheadp = childp; 3131590Srgrimes } 3141590Srgrimes if ( childp -> parents == 0 ) { 3151590Srgrimes printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n" , 3161590Srgrimes "" , "" , "" , "" , "" , "" ); 3171590Srgrimes return; 3181590Srgrimes } 3191590Srgrimes sortparents( childp ); 3201590Srgrimes for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) { 3211590Srgrimes parentp = arcp -> arc_parentp; 3221590Srgrimes if ( childp == parentp || ( arcp -> arc_flags & DEADARC ) || 3231590Srgrimes ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) { 3241590Srgrimes /* 3251590Srgrimes * selfcall or call among siblings 3261590Srgrimes */ 32791018Sbde printf( "%6.6s %5.5s %7.7s %11.11s %7ld %7.7s " , 3281590Srgrimes "" , "" , "" , "" , 3291590Srgrimes arcp -> arc_count , "" ); 3301590Srgrimes printname( parentp ); 3311590Srgrimes printf( "\n" ); 3321590Srgrimes } else { 3331590Srgrimes /* 3341590Srgrimes * regular parent of child 3351590Srgrimes */ 33691018Sbde printf( "%6.6s %5.5s %7.2f %11.2f %7ld/%-7ld " , 3371590Srgrimes "" , "" , 3381590Srgrimes arcp -> arc_time / hz , arcp -> arc_childtime / hz , 3391590Srgrimes arcp -> arc_count , cycleheadp -> npropcall ); 3401590Srgrimes printname( parentp ); 3411590Srgrimes printf( "\n" ); 3421590Srgrimes } 3431590Srgrimes } 3441590Srgrimes} 3451590Srgrimes 346105243Scharniervoid 347246783Scharnierprintchildren(nltype *parentp) 3481590Srgrimes{ 3491590Srgrimes nltype *childp; 3501590Srgrimes arctype *arcp; 3511590Srgrimes 3521590Srgrimes sortchildren( parentp ); 3531590Srgrimes arcp = parentp -> children; 3541590Srgrimes for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 3551590Srgrimes childp = arcp -> arc_childp; 3561590Srgrimes if ( childp == parentp || ( arcp -> arc_flags & DEADARC ) || 3571590Srgrimes ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) { 3581590Srgrimes /* 3591590Srgrimes * self call or call to sibling 3601590Srgrimes */ 36191018Sbde printf( "%6.6s %5.5s %7.7s %11.11s %7ld %7.7s " , 3621590Srgrimes "" , "" , "" , "" , arcp -> arc_count , "" ); 3631590Srgrimes printname( childp ); 3641590Srgrimes printf( "\n" ); 3651590Srgrimes } else { 3661590Srgrimes /* 3671590Srgrimes * regular child of parent 3681590Srgrimes */ 36991018Sbde printf( "%6.6s %5.5s %7.2f %11.2f %7ld/%-7ld " , 3701590Srgrimes "" , "" , 3711590Srgrimes arcp -> arc_time / hz , arcp -> arc_childtime / hz , 3721590Srgrimes arcp -> arc_count , childp -> cyclehead -> npropcall ); 3731590Srgrimes printname( childp ); 3741590Srgrimes printf( "\n" ); 3751590Srgrimes } 3761590Srgrimes } 3771590Srgrimes} 3781590Srgrimes 379105243Scharniervoid 380246783Scharnierprintname(nltype *selfp) 3811590Srgrimes{ 3821590Srgrimes 3831590Srgrimes if ( selfp -> name != 0 ) { 3841590Srgrimes printf( "%s" , selfp -> name ); 3851590Srgrimes# ifdef DEBUG 3861590Srgrimes if ( debug & DFNDEBUG ) { 3871590Srgrimes printf( "{%d} " , selfp -> toporder ); 3881590Srgrimes } 3891590Srgrimes if ( debug & PROPDEBUG ) { 3901590Srgrimes printf( "%5.2f%% " , selfp -> propfraction ); 3911590Srgrimes } 39297631Swollman# endif /* DEBUG */ 3931590Srgrimes } 3941590Srgrimes if ( selfp -> cycleno != 0 ) { 3951590Srgrimes printf( " <cycle %d>" , selfp -> cycleno ); 3961590Srgrimes } 3971590Srgrimes if ( selfp -> index != 0 ) { 3981590Srgrimes if ( selfp -> printflag ) { 3991590Srgrimes printf( " [%d]" , selfp -> index ); 4001590Srgrimes } else { 4011590Srgrimes printf( " (%d)" , selfp -> index ); 4021590Srgrimes } 4031590Srgrimes } 4041590Srgrimes} 4051590Srgrimes 406105243Scharniervoid 407246783Scharniersortchildren(nltype *parentp) 4081590Srgrimes{ 4091590Srgrimes arctype *arcp; 4101590Srgrimes arctype *detachedp; 4111590Srgrimes arctype sorted; 4121590Srgrimes arctype *prevp; 4131590Srgrimes 4141590Srgrimes /* 4151590Srgrimes * unlink children from parent, 4161590Srgrimes * then insertion sort back on to sorted's children. 4171590Srgrimes * *arcp the arc you have detached and are inserting. 4181590Srgrimes * *detachedp the rest of the arcs to be sorted. 4191590Srgrimes * sorted arc list onto which you insertion sort. 4201590Srgrimes * *prevp arc before the arc you are comparing. 4211590Srgrimes */ 4221590Srgrimes sorted.arc_childlist = 0; 4231590Srgrimes for ( (arcp = parentp -> children)&&(detachedp = arcp -> arc_childlist); 4241590Srgrimes arcp ; 4251590Srgrimes (arcp = detachedp)&&(detachedp = detachedp -> arc_childlist)) { 4261590Srgrimes /* 4271590Srgrimes * consider *arcp as disconnected 4281590Srgrimes * insert it into sorted 4291590Srgrimes */ 4301590Srgrimes for ( prevp = &sorted ; 4311590Srgrimes prevp -> arc_childlist ; 4321590Srgrimes prevp = prevp -> arc_childlist ) { 4331590Srgrimes if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) { 4341590Srgrimes break; 4351590Srgrimes } 4361590Srgrimes } 4371590Srgrimes arcp -> arc_childlist = prevp -> arc_childlist; 4381590Srgrimes prevp -> arc_childlist = arcp; 4391590Srgrimes } 4401590Srgrimes /* 4411590Srgrimes * reattach sorted children to parent 4421590Srgrimes */ 4431590Srgrimes parentp -> children = sorted.arc_childlist; 4441590Srgrimes} 4451590Srgrimes 446105243Scharniervoid 447246783Scharniersortparents(nltype *childp) 4481590Srgrimes{ 4491590Srgrimes arctype *arcp; 4501590Srgrimes arctype *detachedp; 4511590Srgrimes arctype sorted; 4521590Srgrimes arctype *prevp; 4531590Srgrimes 4541590Srgrimes /* 4551590Srgrimes * unlink parents from child, 4561590Srgrimes * then insertion sort back on to sorted's parents. 4571590Srgrimes * *arcp the arc you have detached and are inserting. 4581590Srgrimes * *detachedp the rest of the arcs to be sorted. 4591590Srgrimes * sorted arc list onto which you insertion sort. 4601590Srgrimes * *prevp arc before the arc you are comparing. 4611590Srgrimes */ 4621590Srgrimes sorted.arc_parentlist = 0; 4631590Srgrimes for ( (arcp = childp -> parents)&&(detachedp = arcp -> arc_parentlist); 4641590Srgrimes arcp ; 4651590Srgrimes (arcp = detachedp)&&(detachedp = detachedp -> arc_parentlist)) { 4661590Srgrimes /* 4671590Srgrimes * consider *arcp as disconnected 4681590Srgrimes * insert it into sorted 4691590Srgrimes */ 4701590Srgrimes for ( prevp = &sorted ; 4711590Srgrimes prevp -> arc_parentlist ; 4721590Srgrimes prevp = prevp -> arc_parentlist ) { 4731590Srgrimes if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) { 4741590Srgrimes break; 4751590Srgrimes } 4761590Srgrimes } 4771590Srgrimes arcp -> arc_parentlist = prevp -> arc_parentlist; 4781590Srgrimes prevp -> arc_parentlist = arcp; 4791590Srgrimes } 4801590Srgrimes /* 4811590Srgrimes * reattach sorted arcs to child 4821590Srgrimes */ 4831590Srgrimes childp -> parents = sorted.arc_parentlist; 4841590Srgrimes} 4851590Srgrimes 4861590Srgrimes /* 4871590Srgrimes * print a cycle header 4881590Srgrimes */ 489105243Scharniervoid 490246783Scharnierprintcycle(nltype *cyclep) 4911590Srgrimes{ 4921590Srgrimes char kirkbuffer[ BUFSIZ ]; 4931590Srgrimes 4941590Srgrimes sprintf( kirkbuffer , "[%d]" , cyclep -> index ); 49591018Sbde printf( "%-6.6s %5.1f %7.2f %11.2f %7ld" , 4961590Srgrimes kirkbuffer , 4971590Srgrimes 100 * ( cyclep -> propself + cyclep -> propchild ) / printtime , 4981590Srgrimes cyclep -> propself / hz , 4991590Srgrimes cyclep -> propchild / hz , 5001590Srgrimes cyclep -> npropcall ); 5011590Srgrimes if ( cyclep -> selfcalls != 0 ) { 50291018Sbde printf( "+%-7ld" , cyclep -> selfcalls ); 5031590Srgrimes } else { 5041590Srgrimes printf( " %7.7s" , "" ); 5051590Srgrimes } 5061590Srgrimes printf( " <cycle %d as a whole>\t[%d]\n" , 5071590Srgrimes cyclep -> cycleno , cyclep -> index ); 5081590Srgrimes} 5091590Srgrimes 5101590Srgrimes /* 5111590Srgrimes * print the members of a cycle 5121590Srgrimes */ 513105243Scharniervoid 514246783Scharnierprintmembers(nltype *cyclep) 5151590Srgrimes{ 5161590Srgrimes nltype *memberp; 5171590Srgrimes 5181590Srgrimes sortmembers( cyclep ); 5191590Srgrimes for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) { 52091018Sbde printf( "%6.6s %5.5s %7.2f %11.2f %7ld" , 5211590Srgrimes "" , "" , memberp -> propself / hz , memberp -> propchild / hz , 5221590Srgrimes memberp -> npropcall ); 5231590Srgrimes if ( memberp -> selfcalls != 0 ) { 52491018Sbde printf( "+%-7ld" , memberp -> selfcalls ); 5251590Srgrimes } else { 5261590Srgrimes printf( " %7.7s" , "" ); 5271590Srgrimes } 5281590Srgrimes printf( " " ); 5291590Srgrimes printname( memberp ); 5301590Srgrimes printf( "\n" ); 5311590Srgrimes } 5321590Srgrimes} 5331590Srgrimes 5341590Srgrimes /* 5351590Srgrimes * sort members of a cycle 5361590Srgrimes */ 537105243Scharniervoid 538246783Scharniersortmembers(nltype *cyclep) 5391590Srgrimes{ 5401590Srgrimes nltype *todo; 5411590Srgrimes nltype *doing; 5421590Srgrimes nltype *prev; 5431590Srgrimes 5441590Srgrimes /* 5451590Srgrimes * detach cycle members from cyclehead, 5461590Srgrimes * and insertion sort them back on. 5471590Srgrimes */ 5481590Srgrimes todo = cyclep -> cnext; 5491590Srgrimes cyclep -> cnext = 0; 5501590Srgrimes for ( (doing = todo)&&(todo = doing -> cnext); 5511590Srgrimes doing ; 5521590Srgrimes (doing = todo )&&(todo = doing -> cnext )){ 5531590Srgrimes for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) { 5541590Srgrimes if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) { 5551590Srgrimes break; 5561590Srgrimes } 5571590Srgrimes } 5581590Srgrimes doing -> cnext = prev -> cnext; 5591590Srgrimes prev -> cnext = doing; 5601590Srgrimes } 5611590Srgrimes} 5621590Srgrimes 5631590Srgrimes /* 5641590Srgrimes * major sort is on propself + propchild, 5651590Srgrimes * next is sort on ncalls + selfcalls. 5661590Srgrimes */ 5671590Srgrimesint 568246783Scharniermembercmp(nltype *this, nltype *that) 5691590Srgrimes{ 5701590Srgrimes double thistime = this -> propself + this -> propchild; 5711590Srgrimes double thattime = that -> propself + that -> propchild; 5721590Srgrimes long thiscalls = this -> ncall + this -> selfcalls; 5731590Srgrimes long thatcalls = that -> ncall + that -> selfcalls; 5741590Srgrimes 5751590Srgrimes if ( thistime > thattime ) { 5761590Srgrimes return GREATERTHAN; 5771590Srgrimes } 5781590Srgrimes if ( thistime < thattime ) { 5791590Srgrimes return LESSTHAN; 5801590Srgrimes } 5811590Srgrimes if ( thiscalls > thatcalls ) { 5821590Srgrimes return GREATERTHAN; 5831590Srgrimes } 5841590Srgrimes if ( thiscalls < thatcalls ) { 5851590Srgrimes return LESSTHAN; 5861590Srgrimes } 5871590Srgrimes return EQUALTO; 5881590Srgrimes} 5891590Srgrimes /* 5901590Srgrimes * compare two arcs to/from the same child/parent. 5911590Srgrimes * - if one arc is a self arc, it's least. 5921590Srgrimes * - if one arc is within a cycle, it's less than. 5931590Srgrimes * - if both arcs are within a cycle, compare arc counts. 5941590Srgrimes * - if neither arc is within a cycle, compare with 5951590Srgrimes * arc_time + arc_childtime as major key 5961590Srgrimes * arc count as minor key 5971590Srgrimes */ 5981590Srgrimesint 599246783Scharnierarccmp(arctype *thisp, arctype *thatp) 6001590Srgrimes{ 6011590Srgrimes nltype *thisparentp = thisp -> arc_parentp; 6021590Srgrimes nltype *thischildp = thisp -> arc_childp; 6031590Srgrimes nltype *thatparentp = thatp -> arc_parentp; 6041590Srgrimes nltype *thatchildp = thatp -> arc_childp; 6051590Srgrimes double thistime; 6061590Srgrimes double thattime; 6071590Srgrimes 6081590Srgrimes# ifdef DEBUG 6091590Srgrimes if ( debug & TIMEDEBUG ) { 6101590Srgrimes printf( "[arccmp] " ); 6111590Srgrimes printname( thisparentp ); 6121590Srgrimes printf( " calls " ); 6131590Srgrimes printname ( thischildp ); 61491018Sbde printf( " %f + %f %ld/%ld\n" , 6151590Srgrimes thisp -> arc_time , thisp -> arc_childtime , 6161590Srgrimes thisp -> arc_count , thischildp -> ncall ); 6171590Srgrimes printf( "[arccmp] " ); 6181590Srgrimes printname( thatparentp ); 6191590Srgrimes printf( " calls " ); 6201590Srgrimes printname( thatchildp ); 62191018Sbde printf( " %f + %f %ld/%ld\n" , 6221590Srgrimes thatp -> arc_time , thatp -> arc_childtime , 6231590Srgrimes thatp -> arc_count , thatchildp -> ncall ); 6241590Srgrimes printf( "\n" ); 6251590Srgrimes } 62697631Swollman# endif /* DEBUG */ 6271590Srgrimes if ( thisparentp == thischildp ) { 6281590Srgrimes /* this is a self call */ 6291590Srgrimes return LESSTHAN; 6301590Srgrimes } 6311590Srgrimes if ( thatparentp == thatchildp ) { 6321590Srgrimes /* that is a self call */ 6331590Srgrimes return GREATERTHAN; 6341590Srgrimes } 6351590Srgrimes if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 && 6361590Srgrimes thisparentp -> cycleno == thischildp -> cycleno ) { 6371590Srgrimes /* this is a call within a cycle */ 6381590Srgrimes if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && 6391590Srgrimes thatparentp -> cycleno == thatchildp -> cycleno ) { 6401590Srgrimes /* that is a call within the cycle, too */ 6411590Srgrimes if ( thisp -> arc_count < thatp -> arc_count ) { 6421590Srgrimes return LESSTHAN; 6431590Srgrimes } 6441590Srgrimes if ( thisp -> arc_count > thatp -> arc_count ) { 6451590Srgrimes return GREATERTHAN; 6461590Srgrimes } 6471590Srgrimes return EQUALTO; 6481590Srgrimes } else { 6491590Srgrimes /* that isn't a call within the cycle */ 6501590Srgrimes return LESSTHAN; 6511590Srgrimes } 6521590Srgrimes } else { 6531590Srgrimes /* this isn't a call within a cycle */ 6541590Srgrimes if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && 6551590Srgrimes thatparentp -> cycleno == thatchildp -> cycleno ) { 6561590Srgrimes /* that is a call within a cycle */ 6571590Srgrimes return GREATERTHAN; 6581590Srgrimes } else { 6591590Srgrimes /* neither is a call within a cycle */ 6601590Srgrimes thistime = thisp -> arc_time + thisp -> arc_childtime; 6611590Srgrimes thattime = thatp -> arc_time + thatp -> arc_childtime; 6621590Srgrimes if ( thistime < thattime ) 6631590Srgrimes return LESSTHAN; 6641590Srgrimes if ( thistime > thattime ) 6651590Srgrimes return GREATERTHAN; 6661590Srgrimes if ( thisp -> arc_count < thatp -> arc_count ) 6671590Srgrimes return LESSTHAN; 6681590Srgrimes if ( thisp -> arc_count > thatp -> arc_count ) 6691590Srgrimes return GREATERTHAN; 6701590Srgrimes return EQUALTO; 6711590Srgrimes } 6721590Srgrimes } 6731590Srgrimes} 6741590Srgrimes 675105243Scharniervoid 676246783Scharnierprintblurb(const char *blurbname) 6771590Srgrimes{ 6781590Srgrimes FILE *blurbfile; 6791590Srgrimes int input; 6801590Srgrimes 6811590Srgrimes blurbfile = fopen( blurbname , "r" ); 6821590Srgrimes if ( blurbfile == NULL ) { 683105243Scharnier warn( "%s" , blurbname ); 6841590Srgrimes return; 6851590Srgrimes } 6861590Srgrimes while ( ( input = getc( blurbfile ) ) != EOF ) { 6871590Srgrimes putchar( input ); 6881590Srgrimes } 6891590Srgrimes fclose( blurbfile ); 6901590Srgrimes} 6911590Srgrimes 6921590Srgrimesint 693246783Scharniernamecmp(const void *v1, const void *v2) 6941590Srgrimes{ 695246783Scharnier const nltype **npp1 = (const nltype **)v1; 696246783Scharnier const nltype **npp2 = (const nltype **)v2; 697246783Scharnier 6981590Srgrimes return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); 6991590Srgrimes} 7001590Srgrimes 701105243Scharniervoid 702246783Scharnierprintindex(void) 7031590Srgrimes{ 7041590Srgrimes nltype **namesortnlp; 7051590Srgrimes register nltype *nlp; 706246783Scharnier int idx, nnames, todo, i, j; 7071590Srgrimes char peterbuffer[ BUFSIZ ]; 7081590Srgrimes 7091590Srgrimes /* 710105243Scharnier * Now, sort regular function name alphabetically 7111590Srgrimes * to create an index. 7121590Srgrimes */ 7131590Srgrimes namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); 714105243Scharnier if ( namesortnlp == (nltype **) 0 ) 715105243Scharnier errx( 1 , "ran out of memory for sorting"); 716246783Scharnier for ( idx = 0 , nnames = 0 ; idx < nname ; idx++ ) { 717246783Scharnier if ( zflag == 0 && nl[idx].ncall == 0 && nl[idx].time == 0 ) 7181590Srgrimes continue; 719246783Scharnier namesortnlp[nnames++] = &nl[idx]; 7201590Srgrimes } 7211590Srgrimes qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp ); 722246783Scharnier for ( idx = 1 , todo = nnames ; idx <= ncycle ; idx++ ) { 723246783Scharnier namesortnlp[todo++] = &cyclenl[idx]; 7241590Srgrimes } 7251590Srgrimes printf( "\f\nIndex by function name\n\n" ); 726246783Scharnier idx = ( todo + 2 ) / 3; 727246783Scharnier for ( i = 0; i < idx ; i++ ) { 728246783Scharnier for ( j = i; j < todo ; j += idx ) { 7291590Srgrimes nlp = namesortnlp[ j ]; 7301590Srgrimes if ( nlp -> printflag ) { 7311590Srgrimes sprintf( peterbuffer , "[%d]" , nlp -> index ); 7321590Srgrimes } else { 7331590Srgrimes sprintf( peterbuffer , "(%d)" , nlp -> index ); 7341590Srgrimes } 7351590Srgrimes if ( j < nnames ) { 7361590Srgrimes printf( "%6.6s %-19.19s" , peterbuffer , nlp -> name ); 7371590Srgrimes } else { 7381590Srgrimes printf( "%6.6s " , peterbuffer ); 7391590Srgrimes sprintf( peterbuffer , "<cycle %d>" , nlp -> cycleno ); 7401590Srgrimes printf( "%-19.19s" , peterbuffer ); 7411590Srgrimes } 7421590Srgrimes } 7431590Srgrimes printf( "\n" ); 7441590Srgrimes } 7451590Srgrimes free( namesortnlp ); 7461590Srgrimes} 747