printgprof.c revision 129657
1265555Sambrisko/* 2282531Skadesai * Copyright (c) 1983, 1993 3272744Skadesai * The Regents of the University of California. All rights reserved. 4282531Skadesai * 5265555Sambrisko * Redistribution and use in source and binary forms, with or without 6265555Sambrisko * modification, are permitted provided that the following conditions 7272744Skadesai * are met: 8272744Skadesai * 1. Redistributions of source code must retain the above copyright 9265555Sambrisko * notice, this list of conditions and the following disclaimer. 10272744Skadesai * 2. Redistributions in binary form must reproduce the above copyright 11272744Skadesai * notice, this list of conditions and the following disclaimer in the 12272744Skadesai * documentation and/or other materials provided with the distribution. 13272744Skadesai * 3. All advertising materials mentioning features or use of this software 14272744Skadesai * must display the following acknowledgement: 15272744Skadesai * This product includes software developed by the University of 16272744Skadesai * California, Berkeley and its contributors. 17272744Skadesai * 4. Neither the name of the University nor the names of its contributors 18265555Sambrisko * may be used to endorse or promote products derived from this software 19272744Skadesai * without specific prior written permission. 20272744Skadesai * 21272744Skadesai * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22272744Skadesai * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23272744Skadesai * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24272744Skadesai * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25272744Skadesai * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26272744Skadesai * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27272744Skadesai * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28272744Skadesai * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29265555Sambrisko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30265555Sambrisko * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31272744Skadesai * SUCH DAMAGE. 32265555Sambrisko */ 33265555Sambrisko 34265555Sambrisko#if 0 35265555Sambrisko#ifndef lint 36272744Skadesaistatic char sccsid[] = "@(#)printgprof.c 8.1 (Berkeley) 6/6/93"; 37265555Sambrisko#endif /* not lint */ 38265555Sambrisko#endif 39265555Sambrisko 40265555Sambrisko#include <sys/cdefs.h> 41265555Sambrisko__FBSDID("$FreeBSD: head/usr.bin/gprof/printgprof.c 129657 2004-05-24 12:44:00Z stefanf $"); 42265555Sambrisko 43265555Sambrisko#include <err.h> 44265555Sambrisko#include <string.h> 45265555Sambrisko 46265555Sambrisko#include "gprof.h" 47265555Sambrisko#include "pathnames.h" 48265555Sambrisko 49272739Skadesaivoid 50265555Sambriskoprintprof() 51265555Sambrisko{ 52272744Skadesai register nltype *np; 53272744Skadesai nltype **sortednlp; 54272739Skadesai int index, timecmp(); 55272744Skadesai 56272739Skadesai actime = 0.0; 57265555Sambrisko printf( "\f\n" ); 58265555Sambrisko flatprofheader(); 59265555Sambrisko /* 60272744Skadesai * Sort the symbol table in by time 61282533Skadesai */ 62272744Skadesai sortednlp = (nltype **) calloc( nname , sizeof(nltype *) ); 63272744Skadesai if ( sortednlp == (nltype **) 0 ) 64272744Skadesai errx( 1 , "[printprof] ran out of memory for time sorting" ); 65282533Skadesai for ( index = 0 ; index < nname ; index += 1 ) { 66282533Skadesai sortednlp[ index ] = &nl[ index ]; 67282533Skadesai } 68299667Skadesai qsort( sortednlp , nname , sizeof(nltype *) , timecmp ); 69272744Skadesai for ( index = 0 ; index < nname ; index += 1 ) { 70282533Skadesai np = sortednlp[ index ]; 71299667Skadesai flatprofline( np ); 72299667Skadesai } 73282533Skadesai actime = 0.0; 74299667Skadesai free( sortednlp ); 75299667Skadesai} 76299667Skadesai 77272744Skadesaiint 78272744Skadesaitimecmp( npp1 , npp2 ) 79272744Skadesai nltype **npp1, **npp2; 80272744Skadesai{ 81272744Skadesai double timediff; 82272744Skadesai long calldiff; 83272744Skadesai 84272744Skadesai timediff = (*npp2) -> time - (*npp1) -> time; 85272744Skadesai if ( timediff > 0.0 ) 86282533Skadesai return 1 ; 87272744Skadesai if ( timediff < 0.0 ) 88272744Skadesai return -1; 89282533Skadesai calldiff = (*npp2) -> ncall - (*npp1) -> ncall; 90272744Skadesai if ( calldiff > 0 ) 91272744Skadesai return 1; 92272744Skadesai if ( calldiff < 0 ) 93272744Skadesai return -1; 94265555Sambrisko return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); 95272741Skadesai} 96265555Sambrisko 97265555Sambrisko /* 98282533Skadesai * header for flatprofline 99272744Skadesai */ 100272744Skadesaivoid 101282533Skadesaiflatprofheader() 102272744Skadesai{ 103272744Skadesai 104272744Skadesai if ( bflag ) { 105272744Skadesai printblurb( _PATH_FLAT_BLURB ); 106272744Skadesai } 107265555Sambrisko printf( "\ngranularity: each sample hit covers %g byte(s)" , 108272744Skadesai scale * HISTORICAL_SCALE_2 ); 109272744Skadesai if ( totime > 0.0 ) { 110272744Skadesai printf( " for %.2f%% of %.2f seconds\n\n" , 111265555Sambrisko 100.0/totime , totime / hz ); 112265555Sambrisko } else { 113265555Sambrisko printf( " no time accumulated\n\n" ); 114272744Skadesai /* 115272744Skadesai * this doesn't hurt since all the numerators will be zero. 116272744Skadesai */ 117272744Skadesai totime = 1.0; 118272744Skadesai } 119272744Skadesai printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" , 120272744Skadesai "% " , "cumulative" , "self " , "" , "self " , "total " , "" ); 121282533Skadesai printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" , 122282533Skadesai "time" , "seconds " , "seconds" , "calls" , 123282533Skadesai hz >= 10000000 ? "ns/call" : hz >= 10000 ? "us/call" : "ms/call" , 124272744Skadesai hz >= 10000000 ? "ns/call" : hz >= 10000 ? "us/call" : "ms/call" , 125272744Skadesai "name" ); 126272744Skadesai} 127299671Skadesai 128265555Sambriskovoid 129265555Sambriskoflatprofline( np ) 130272744Skadesai register nltype *np; 131272744Skadesai{ 132272744Skadesai 133265555Sambrisko if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) { 134272744Skadesai return; 135272744Skadesai } 136272744Skadesai actime += np -> time; 137265555Sambrisko if (hz >= 10000) 138272744Skadesai printf( "%5.1f %10.3f %8.3f" , 139272744Skadesai 100 * np -> time / totime , actime / hz , np -> time / hz ); 140265555Sambrisko else 141272744Skadesai printf( "%5.1f %10.2f %8.2f" , 142272744Skadesai 100 * np -> time / totime , actime / hz , np -> time / hz ); 143265555Sambrisko if ( np -> ncall != 0 ) { 144272744Skadesai if (hz >= 10000000) 145265555Sambrisko printf( " %8ld %8.0f %8.0f " , np -> ncall , 146272744Skadesai 1e9 * np -> time / hz / np -> ncall , 147272744Skadesai 1e9 * ( np -> time + np -> childtime ) / hz / np -> ncall ); 148272744Skadesai else if (hz >= 10000) 149272744Skadesai printf( " %8ld %8.0f %8.0f " , np -> ncall , 150272744Skadesai 1e6 * np -> time / hz / np -> ncall , 151272744Skadesai 1e6 * ( np -> time + np -> childtime ) / hz / np -> ncall ); 152272744Skadesai else 153272744Skadesai printf( " %8ld %8.2f %8.2f " , np -> ncall , 154272744Skadesai 1000 * np -> time / hz / np -> ncall , 155272744Skadesai 1000 * ( np -> time + np -> childtime ) / hz / np -> ncall ); 156272744Skadesai } else { 157272744Skadesai printf( " %8.8s %8.8s %8.8s " , "" , "" , "" ); 158272744Skadesai } 159272744Skadesai printname( np ); 160272744Skadesai printf( "\n" ); 161272744Skadesai} 162272744Skadesai 163272744Skadesaivoid 164272744Skadesaigprofheader() 165265555Sambrisko{ 166272744Skadesai 167272744Skadesai if ( bflag ) { 168272744Skadesai printblurb( _PATH_CALLG_BLURB ); 169272744Skadesai } 170272744Skadesai printf( "\ngranularity: each sample hit covers %g byte(s)" , 171272744Skadesai scale * HISTORICAL_SCALE_2 ); 172272744Skadesai if ( printtime > 0.0 ) { 173272744Skadesai printf( " for %.2f%% of %.2f seconds\n\n" , 174272744Skadesai 100.0/printtime , printtime / hz ); 175272744Skadesai } else { 176272744Skadesai printf( " no time propagated\n\n" ); 177272744Skadesai /* 178272744Skadesai * this doesn't hurt, since all the numerators will be 0.0 179272744Skadesai */ 180272744Skadesai printtime = 1.0; 181272744Skadesai } 182272744Skadesai printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , 183272744Skadesai "" , "" , "" , "" , "called" , "total" , "parents"); 184265555Sambrisko printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" , 185272744Skadesai "index" , "%time" , "self" , "descendents" , 186272744Skadesai "called" , "self" , "name" , "index" ); 187272744Skadesai printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , 188272744Skadesai "" , "" , "" , "" , "called" , "total" , "children"); 189272744Skadesai printf( "\n" ); 190272744Skadesai} 191272744Skadesai 192272744Skadesaivoid 193272744Skadesaigprofline( np ) 194272744Skadesai register nltype *np; 195272744Skadesai{ 196272744Skadesai char kirkbuffer[ BUFSIZ ]; 197272744Skadesai 198272744Skadesai sprintf( kirkbuffer , "[%d]" , np -> index ); 199272744Skadesai printf( "%-6.6s %5.1f %7.2f %11.2f" , 200272744Skadesai kirkbuffer , 201272744Skadesai 100 * ( np -> propself + np -> propchild ) / printtime , 202272744Skadesai np -> propself / hz , 203272744Skadesai np -> propchild / hz ); 204272744Skadesai if ( ( np -> ncall + np -> selfcalls ) != 0 ) { 205272744Skadesai printf( " %7ld" , np -> npropcall ); 206272744Skadesai if ( np -> selfcalls != 0 ) { 207272744Skadesai printf( "+%-7ld " , np -> selfcalls ); 208272744Skadesai } else { 209272744Skadesai printf( " %7.7s " , "" ); 210272744Skadesai } 211265555Sambrisko } else { 212265555Sambrisko printf( " %7.7s %7.7s " , "" , "" ); 213272744Skadesai } 214272744Skadesai printname( np ); 215272744Skadesai printf( "\n" ); 216272744Skadesai} 217265555Sambrisko 218272744Skadesaivoid 219265555Sambriskoprintgprof(timesortnlp) 220265555Sambrisko nltype **timesortnlp; 221272744Skadesai{ 222272744Skadesai int index; 223272744Skadesai nltype *parentp; 224265555Sambrisko 225272744Skadesai /* 226265555Sambrisko * Print out the structured profiling list 227272744Skadesai */ 228272744Skadesai gprofheader(); 229265555Sambrisko for ( index = 0 ; index < nname + ncycle ; index ++ ) { 230265555Sambrisko parentp = timesortnlp[ index ]; 231272744Skadesai if ( zflag == 0 && 232272744Skadesai parentp -> ncall == 0 && 233272744Skadesai parentp -> selfcalls == 0 && 234272744Skadesai parentp -> propself == 0 && 235272744Skadesai parentp -> propchild == 0 ) { 236272744Skadesai continue; 237272744Skadesai } 238272744Skadesai if ( ! parentp -> printflag ) { 239272744Skadesai continue; 240272744Skadesai } 241272744Skadesai if ( parentp -> name == 0 && parentp -> cycleno != 0 ) { 242272744Skadesai /* 243272744Skadesai * cycle header 244272744Skadesai */ 245272744Skadesai printcycle( parentp ); 246265555Sambrisko printmembers( parentp ); 247265555Sambrisko } else { 248272744Skadesai printparents( parentp ); 249272744Skadesai gprofline( parentp ); 250272744Skadesai printchildren( parentp ); 251265555Sambrisko } 252272744Skadesai printf( "\n" ); 253272744Skadesai printf( "-----------------------------------------------\n" ); 254272744Skadesai printf( "\n" ); 255265555Sambrisko } 256272744Skadesai free( timesortnlp ); 257272744Skadesai} 258265555Sambrisko 259272744Skadesai /* 260272744Skadesai * sort by decreasing propagated time 261272744Skadesai * if times are equal, but one is a cycle header, 262265555Sambrisko * say that's first (e.g. less, i.e. -1). 263272744Skadesai * if one's name doesn't have an underscore and the other does, 264272744Skadesai * say the one is first. 265272744Skadesai * all else being equal, sort by names. 266272744Skadesai */ 267265555Sambriskoint 268272744Skadesaitotalcmp( npp1 , npp2 ) 269272744Skadesai nltype **npp1; 270272744Skadesai nltype **npp2; 271272744Skadesai{ 272272744Skadesai register nltype *np1 = *npp1; 273272744Skadesai register nltype *np2 = *npp2; 274272744Skadesai double diff; 275272744Skadesai 276272744Skadesai diff = ( np1 -> propself + np1 -> propchild ) 277272744Skadesai - ( np2 -> propself + np2 -> propchild ); 278272744Skadesai if ( diff < 0.0 ) 279272744Skadesai return 1; 280272744Skadesai if ( diff > 0.0 ) 281272744Skadesai return -1; 282272744Skadesai if ( np1 -> name == 0 && np1 -> cycleno != 0 ) 283272744Skadesai return -1; 284272744Skadesai if ( np2 -> name == 0 && np2 -> cycleno != 0 ) 285272744Skadesai return 1; 286272744Skadesai if ( np1 -> name == 0 ) 287272744Skadesai return -1; 288272744Skadesai if ( np2 -> name == 0 ) 289272744Skadesai return 1; 290272744Skadesai if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' ) 291272744Skadesai return -1; 292272744Skadesai if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' ) 293272744Skadesai return 1; 294272744Skadesai if ( np1 -> ncall > np2 -> ncall ) 295272744Skadesai return -1; 296272744Skadesai if ( np1 -> ncall < np2 -> ncall ) 297272744Skadesai return 1; 298272744Skadesai return strcmp( np1 -> name , np2 -> name ); 299272744Skadesai} 300272744Skadesai 301272744Skadesaivoid 302272744Skadesaiprintparents( childp ) 303272744Skadesai nltype *childp; 304272744Skadesai{ 305272744Skadesai nltype *parentp; 306272744Skadesai arctype *arcp; 307272744Skadesai nltype *cycleheadp; 308272744Skadesai 309272744Skadesai if ( childp -> cyclehead != 0 ) { 310272744Skadesai cycleheadp = childp -> cyclehead; 311272744Skadesai } else { 312272744Skadesai cycleheadp = childp; 313272744Skadesai } 314272744Skadesai if ( childp -> parents == 0 ) { 315272744Skadesai printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n" , 316272744Skadesai "" , "" , "" , "" , "" , "" ); 317272744Skadesai return; 318272744Skadesai } 319272744Skadesai sortparents( childp ); 320272744Skadesai for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) { 321272744Skadesai parentp = arcp -> arc_parentp; 322272744Skadesai if ( childp == parentp || ( arcp -> arc_flags & DEADARC ) || 323272744Skadesai ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) { 324272744Skadesai /* 325282532Skadesai * selfcall or call among siblings 326282532Skadesai */ 327282532Skadesai printf( "%6.6s %5.5s %7.7s %11.11s %7ld %7.7s " , 328272744Skadesai "" , "" , "" , "" , 329282532Skadesai arcp -> arc_count , "" ); 330272744Skadesai printname( parentp ); 331272744Skadesai printf( "\n" ); 332272744Skadesai } else { 333272744Skadesai /* 334272744Skadesai * regular parent of child 335272744Skadesai */ 336272744Skadesai printf( "%6.6s %5.5s %7.2f %11.2f %7ld/%-7ld " , 337282531Skadesai "" , "" , 338272744Skadesai arcp -> arc_time / hz , arcp -> arc_childtime / hz , 339272744Skadesai arcp -> arc_count , cycleheadp -> npropcall ); 340272744Skadesai printname( parentp ); 341272744Skadesai printf( "\n" ); 342272744Skadesai } 343272744Skadesai } 344272744Skadesai} 345272744Skadesai 346272744Skadesaivoid 347265555Sambriskoprintchildren( parentp ) 348299668Skadesai nltype *parentp; 349265555Sambrisko{ 350272744Skadesai nltype *childp; 351272744Skadesai arctype *arcp; 352272744Skadesai 353272744Skadesai sortchildren( parentp ); 354272744Skadesai arcp = parentp -> children; 355272744Skadesai for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 356272744Skadesai childp = arcp -> arc_childp; 357272744Skadesai if ( childp == parentp || ( arcp -> arc_flags & DEADARC ) || 358272744Skadesai ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) { 359272744Skadesai /* 360272744Skadesai * self call or call to sibling 361265555Sambrisko */ 362265555Sambrisko printf( "%6.6s %5.5s %7.7s %11.11s %7ld %7.7s " , 363272744Skadesai "" , "" , "" , "" , arcp -> arc_count , "" ); 364272744Skadesai printname( childp ); 365272744Skadesai printf( "\n" ); 366265555Sambrisko } else { 367272744Skadesai /* 368272744Skadesai * regular child of parent 369298955Spfg */ 370272744Skadesai printf( "%6.6s %5.5s %7.2f %11.2f %7ld/%-7ld " , 371272744Skadesai "" , "" , 372265555Sambrisko arcp -> arc_time / hz , arcp -> arc_childtime / hz , 373265555Sambrisko arcp -> arc_count , childp -> cyclehead -> npropcall ); 374265555Sambrisko printname( childp ); 375265555Sambrisko printf( "\n" ); 376272744Skadesai } 377272744Skadesai } 378265555Sambrisko} 379272744Skadesai 380272744Skadesaivoid 381265555Sambriskoprintname( selfp ) 382272744Skadesai nltype *selfp; 383272744Skadesai{ 384272744Skadesai 385272744Skadesai if ( selfp -> name != 0 ) { 386272744Skadesai printf( "%s" , selfp -> name ); 387272744Skadesai# ifdef DEBUG 388272744Skadesai if ( debug & DFNDEBUG ) { 389272744Skadesai printf( "{%d} " , selfp -> toporder ); 390272744Skadesai } 391272744Skadesai if ( debug & PROPDEBUG ) { 392282532Skadesai printf( "%5.2f%% " , selfp -> propfraction ); 393274819Ssmh } 394282533Skadesai# endif /* DEBUG */ 395282532Skadesai } 396282532Skadesai if ( selfp -> cycleno != 0 ) { 397282533Skadesai printf( " <cycle %d>" , selfp -> cycleno ); 398282532Skadesai } 399299666Skadesai if ( selfp -> index != 0 ) { 400272744Skadesai if ( selfp -> printflag ) { 401272744Skadesai printf( " [%d]" , selfp -> index ); 402265555Sambrisko } else { 403265555Sambrisko printf( " (%d)" , selfp -> index ); 404272744Skadesai } 405272744Skadesai } 406272744Skadesai} 407272744Skadesai 408265555Sambriskovoid 409272744Skadesaisortchildren( parentp ) 410272744Skadesai nltype *parentp; 411272744Skadesai{ 412272744Skadesai arctype *arcp; 413265555Sambrisko arctype *detachedp; 414272744Skadesai arctype sorted; 415272744Skadesai arctype *prevp; 416272744Skadesai 417265555Sambrisko /* 418272744Skadesai * unlink children from parent, 419272744Skadesai * then insertion sort back on to sorted's children. 420272744Skadesai * *arcp the arc you have detached and are inserting. 421272744Skadesai * *detachedp the rest of the arcs to be sorted. 422299667Skadesai * sorted arc list onto which you insertion sort. 423265555Sambrisko * *prevp arc before the arc you are comparing. 424272744Skadesai */ 425272744Skadesai sorted.arc_childlist = 0; 426272744Skadesai for ( (arcp = parentp -> children)&&(detachedp = arcp -> arc_childlist); 427272744Skadesai arcp ; 428272744Skadesai (arcp = detachedp)&&(detachedp = detachedp -> arc_childlist)) { 429272744Skadesai /* 430272744Skadesai * consider *arcp as disconnected 431265555Sambrisko * insert it into sorted 432272744Skadesai */ 433272744Skadesai for ( prevp = &sorted ; 434272744Skadesai prevp -> arc_childlist ; 435272744Skadesai prevp = prevp -> arc_childlist ) { 436272744Skadesai if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) { 437272744Skadesai break; 438272744Skadesai } 439272744Skadesai } 440272744Skadesai arcp -> arc_childlist = prevp -> arc_childlist; 441272744Skadesai prevp -> arc_childlist = arcp; 442272744Skadesai } 443272744Skadesai /* 444265555Sambrisko * reattach sorted children to parent 445282532Skadesai */ 446282532Skadesai parentp -> children = sorted.arc_childlist; 447272744Skadesai} 448272744Skadesai 449272744Skadesaivoid 450272744Skadesaisortparents( childp ) 451272744Skadesai nltype *childp; 452272744Skadesai{ 453272744Skadesai arctype *arcp; 454272744Skadesai arctype *detachedp; 455272744Skadesai arctype sorted; 456272744Skadesai arctype *prevp; 457272744Skadesai 458272744Skadesai /* 459272744Skadesai * unlink parents from child, 460272744Skadesai * then insertion sort back on to sorted's parents. 461272744Skadesai * *arcp the arc you have detached and are inserting. 462272744Skadesai * *detachedp the rest of the arcs to be sorted. 463272744Skadesai * sorted arc list onto which you insertion sort. 464272744Skadesai * *prevp arc before the arc you are comparing. 465265555Sambrisko */ 466299668Skadesai sorted.arc_parentlist = 0; 467272744Skadesai for ( (arcp = childp -> parents)&&(detachedp = arcp -> arc_parentlist); 468272744Skadesai arcp ; 469272744Skadesai (arcp = detachedp)&&(detachedp = detachedp -> arc_parentlist)) { 470272744Skadesai /* 471272744Skadesai * consider *arcp as disconnected 472272744Skadesai * insert it into sorted 473272744Skadesai */ 474272744Skadesai for ( prevp = &sorted ; 475282532Skadesai prevp -> arc_parentlist ; 476299668Skadesai prevp = prevp -> arc_parentlist ) { 477299668Skadesai if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) { 478299668Skadesai break; 479299668Skadesai } 480299668Skadesai } 481282532Skadesai arcp -> arc_parentlist = prevp -> arc_parentlist; 482282532Skadesai prevp -> arc_parentlist = arcp; 483282532Skadesai } 484282532Skadesai /* 485272744Skadesai * reattach sorted arcs to child 486272744Skadesai */ 487272744Skadesai childp -> parents = sorted.arc_parentlist; 488272744Skadesai} 489265555Sambrisko 490272744Skadesai /* 491272744Skadesai * print a cycle header 492299668Skadesai */ 493272744Skadesaivoid 494272744Skadesaiprintcycle( cyclep ) 495272744Skadesai nltype *cyclep; 496272744Skadesai{ 497272744Skadesai char kirkbuffer[ BUFSIZ ]; 498272744Skadesai 499272744Skadesai sprintf( kirkbuffer , "[%d]" , cyclep -> index ); 500272744Skadesai printf( "%-6.6s %5.1f %7.2f %11.2f %7ld" , 501272744Skadesai kirkbuffer , 502272744Skadesai 100 * ( cyclep -> propself + cyclep -> propchild ) / printtime , 503272744Skadesai cyclep -> propself / hz , 504272744Skadesai cyclep -> propchild / hz , 505272744Skadesai cyclep -> npropcall ); 506272744Skadesai if ( cyclep -> selfcalls != 0 ) { 507272744Skadesai printf( "+%-7ld" , cyclep -> selfcalls ); 508272744Skadesai } else { 509272744Skadesai printf( " %7.7s" , "" ); 510272744Skadesai } 511265555Sambrisko printf( " <cycle %d as a whole>\t[%d]\n" , 512272744Skadesai cyclep -> cycleno , cyclep -> index ); 513272744Skadesai} 514265555Sambrisko 515272744Skadesai /* 516272744Skadesai * print the members of a cycle 517272744Skadesai */ 518272744Skadesaivoid 519272744Skadesaiprintmembers( cyclep ) 520272744Skadesai nltype *cyclep; 521272744Skadesai{ 522265555Sambrisko nltype *memberp; 523272744Skadesai 524272744Skadesai sortmembers( cyclep ); 525272744Skadesai for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) { 526272744Skadesai printf( "%6.6s %5.5s %7.2f %11.2f %7ld" , 527272744Skadesai "" , "" , memberp -> propself / hz , memberp -> propchild / hz , 528265555Sambrisko memberp -> npropcall ); 529282526Skadesai if ( memberp -> selfcalls != 0 ) { 530299667Skadesai printf( "+%-7ld" , memberp -> selfcalls ); 531299667Skadesai } else { 532299667Skadesai printf( " %7.7s" , "" ); 533282526Skadesai } 534299667Skadesai printf( " " ); 535299667Skadesai printname( memberp ); 536272744Skadesai printf( "\n" ); 537272744Skadesai } 538272744Skadesai} 539299667Skadesai 540299667Skadesai /* 541299667Skadesai * sort members of a cycle 542299667Skadesai */ 543299667Skadesaivoid 544272744Skadesaisortmembers( cyclep ) 545272744Skadesai nltype *cyclep; 546272744Skadesai{ 547299667Skadesai nltype *todo; 548299667Skadesai nltype *doing; 549299667Skadesai nltype *prev; 550299667Skadesai 551299667Skadesai /* 552299667Skadesai * detach cycle members from cyclehead, 553299667Skadesai * and insertion sort them back on. 554299667Skadesai */ 555299667Skadesai todo = cyclep -> cnext; 556299667Skadesai cyclep -> cnext = 0; 557299667Skadesai for ( (doing = todo)&&(todo = doing -> cnext); 558299667Skadesai doing ; 559299667Skadesai (doing = todo )&&(todo = doing -> cnext )){ 560299667Skadesai for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) { 561299667Skadesai if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) { 562299667Skadesai break; 563299667Skadesai } 564299667Skadesai } 565299667Skadesai doing -> cnext = prev -> cnext; 566299667Skadesai prev -> cnext = doing; 567299667Skadesai } 568272744Skadesai} 569272744Skadesai 570265555Sambrisko /* 571272744Skadesai * major sort is on propself + propchild, 572272744Skadesai * next is sort on ncalls + selfcalls. 573272744Skadesai */ 574272744Skadesaiint 575265555Sambriskomembercmp( this , that ) 576272744Skadesai nltype *this; 577272744Skadesai nltype *that; 578272744Skadesai{ 579272744Skadesai double thistime = this -> propself + this -> propchild; 580265555Sambrisko double thattime = that -> propself + that -> propchild; 581272744Skadesai long thiscalls = this -> ncall + this -> selfcalls; 582272744Skadesai long thatcalls = that -> ncall + that -> selfcalls; 583265555Sambrisko 584272744Skadesai if ( thistime > thattime ) { 585272744Skadesai return GREATERTHAN; 586272744Skadesai } 587282532Skadesai if ( thistime < thattime ) { 588282532Skadesai return LESSTHAN; 589282533Skadesai } 590282532Skadesai if ( thiscalls > thatcalls ) { 591282532Skadesai return GREATERTHAN; 592282533Skadesai } 593282532Skadesai if ( thiscalls < thatcalls ) { 594273040Skadesai return LESSTHAN; 595265555Sambrisko } 596273040Skadesai return EQUALTO; 597272744Skadesai} 598265555Sambrisko /* 599272744Skadesai * compare two arcs to/from the same child/parent. 600272744Skadesai * - if one arc is a self arc, it's least. 601265555Sambrisko * - if one arc is within a cycle, it's less than. 602265555Sambrisko * - if both arcs are within a cycle, compare arc counts. 603272744Skadesai * - if neither arc is within a cycle, compare with 604272744Skadesai * arc_time + arc_childtime as major key 605265555Sambrisko * arc count as minor key 606265555Sambrisko */ 607272744Skadesaiint 608282526Skadesaiarccmp( thisp , thatp ) 609272744Skadesai arctype *thisp; 610265555Sambrisko arctype *thatp; 611272744Skadesai{ 612272744Skadesai nltype *thisparentp = thisp -> arc_parentp; 613265555Sambrisko nltype *thischildp = thisp -> arc_childp; 614282533Skadesai nltype *thatparentp = thatp -> arc_parentp; 615282533Skadesai nltype *thatchildp = thatp -> arc_childp; 616265555Sambrisko double thistime; 617272744Skadesai double thattime; 618265555Sambrisko 619272744Skadesai# ifdef DEBUG 620272744Skadesai if ( debug & TIMEDEBUG ) { 621272744Skadesai printf( "[arccmp] " ); 622272744Skadesai printname( thisparentp ); 623272744Skadesai printf( " calls " ); 624272744Skadesai printname ( thischildp ); 625272744Skadesai printf( " %f + %f %ld/%ld\n" , 626272744Skadesai thisp -> arc_time , thisp -> arc_childtime , 627272744Skadesai thisp -> arc_count , thischildp -> ncall ); 628282526Skadesai printf( "[arccmp] " ); 629282533Skadesai printname( thatparentp ); 630272744Skadesai printf( " calls " ); 631282526Skadesai printname( thatchildp ); 632282533Skadesai printf( " %f + %f %ld/%ld\n" , 633272744Skadesai thatp -> arc_time , thatp -> arc_childtime , 634265555Sambrisko thatp -> arc_count , thatchildp -> ncall ); 635265555Sambrisko printf( "\n" ); 636272744Skadesai } 637272744Skadesai# endif /* DEBUG */ 638272744Skadesai if ( thisparentp == thischildp ) { 639265555Sambrisko /* this is a self call */ 640272744Skadesai return LESSTHAN; 641265555Sambrisko } 642265555Sambrisko if ( thatparentp == thatchildp ) { 643272744Skadesai /* that is a self call */ 644272744Skadesai return GREATERTHAN; 645265555Sambrisko } 646272744Skadesai if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 && 647265555Sambrisko thisparentp -> cycleno == thischildp -> cycleno ) { 648272744Skadesai /* this is a call within a cycle */ 649272744Skadesai if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && 650272744Skadesai thatparentp -> cycleno == thatchildp -> cycleno ) { 651272744Skadesai /* that is a call within the cycle, too */ 652299671Skadesai if ( thisp -> arc_count < thatp -> arc_count ) { 653299671Skadesai return LESSTHAN; 654272744Skadesai } 655299671Skadesai if ( thisp -> arc_count > thatp -> arc_count ) { 656272744Skadesai return GREATERTHAN; 657272744Skadesai } 658272744Skadesai return EQUALTO; 659272744Skadesai } else { 660272744Skadesai /* that isn't a call within the cycle */ 661272744Skadesai return LESSTHAN; 662272744Skadesai } 663299671Skadesai } else { 664299671Skadesai /* this isn't a call within a cycle */ 665272744Skadesai if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && 666272744Skadesai thatparentp -> cycleno == thatchildp -> cycleno ) { 667265555Sambrisko /* that is a call within a cycle */ 668265555Sambrisko return GREATERTHAN; 669272744Skadesai } else { 670272744Skadesai /* neither is a call within a cycle */ 671272744Skadesai thistime = thisp -> arc_time + thisp -> arc_childtime; 672265555Sambrisko thattime = thatp -> arc_time + thatp -> arc_childtime; 673265555Sambrisko if ( thistime < thattime ) 674265555Sambrisko return LESSTHAN; 675272744Skadesai if ( thistime > thattime ) 676272744Skadesai return GREATERTHAN; 677265555Sambrisko if ( thisp -> arc_count < thatp -> arc_count ) 678272744Skadesai return LESSTHAN; 679265555Sambrisko if ( thisp -> arc_count > thatp -> arc_count ) 680272744Skadesai return GREATERTHAN; 681272744Skadesai return EQUALTO; 682272744Skadesai } 683272744Skadesai } 684265555Sambrisko} 685272744Skadesai 686265555Sambriskovoid 687265555Sambriskoprintblurb( blurbname ) 688272744Skadesai char *blurbname; 689272744Skadesai{ 690272744Skadesai FILE *blurbfile; 691272744Skadesai int input; 692265555Sambrisko 693265555Sambrisko blurbfile = fopen( blurbname , "r" ); 694265555Sambrisko if ( blurbfile == NULL ) { 695265555Sambrisko warn( "%s" , blurbname ); 696265555Sambrisko return; 697265555Sambrisko } 698272744Skadesai while ( ( input = getc( blurbfile ) ) != EOF ) { 699265555Sambrisko putchar( input ); 700272744Skadesai } 701272744Skadesai fclose( blurbfile ); 702272744Skadesai} 703272744Skadesai 704272744Skadesaiint 705265555Sambriskonamecmp( npp1 , npp2 ) 706272744Skadesai nltype **npp1, **npp2; 707265555Sambrisko{ 708265555Sambrisko return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); 709272744Skadesai} 710299667Skadesai 711272744Skadesaivoid 712272744Skadesaiprintindex() 713272744Skadesai{ 714265555Sambrisko nltype **namesortnlp; 715272744Skadesai register nltype *nlp; 716272744Skadesai int index, nnames, todo, i, j; 717265555Sambrisko char peterbuffer[ BUFSIZ ]; 718272744Skadesai 719299667Skadesai /* 720272744Skadesai * Now, sort regular function name alphabetically 721265555Sambrisko * to create an index. 722272744Skadesai */ 723272744Skadesai namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); 724272744Skadesai if ( namesortnlp == (nltype **) 0 ) 725272744Skadesai errx( 1 , "ran out of memory for sorting"); 726265555Sambrisko for ( index = 0 , nnames = 0 ; index < nname ; index++ ) { 727272744Skadesai if ( zflag == 0 && nl[index].ncall == 0 && nl[index].time == 0 ) 728265555Sambrisko continue; 729272744Skadesai namesortnlp[nnames++] = &nl[index]; 730272744Skadesai } 731272744Skadesai qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp ); 732272744Skadesai for ( index = 1 , todo = nnames ; index <= ncycle ; index++ ) { 733265555Sambrisko namesortnlp[todo++] = &cyclenl[index]; 734272744Skadesai } 735272744Skadesai printf( "\f\nIndex by function name\n\n" ); 736265555Sambrisko index = ( todo + 2 ) / 3; 737272744Skadesai for ( i = 0; i < index ; i++ ) { 738272744Skadesai for ( j = i; j < todo ; j += index ) { 739265555Sambrisko nlp = namesortnlp[ j ]; 740272744Skadesai if ( nlp -> printflag ) { 741272744Skadesai sprintf( peterbuffer , "[%d]" , nlp -> index ); 742282532Skadesai } else { 743299668Skadesai sprintf( peterbuffer , "(%d)" , nlp -> index ); 744272744Skadesai } 745272744Skadesai if ( j < nnames ) { 746272744Skadesai printf( "%6.6s %-19.19s" , peterbuffer , nlp -> name ); 747272744Skadesai } else { 748299668Skadesai printf( "%6.6s " , peterbuffer ); 749299668Skadesai sprintf( peterbuffer , "<cycle %d>" , nlp -> cycleno ); 750299668Skadesai printf( "%-19.19s" , peterbuffer ); 751299668Skadesai } 752272744Skadesai } 753299668Skadesai printf( "\n" ); 754299668Skadesai } 755272744Skadesai free( namesortnlp ); 756272744Skadesai} 757272744Skadesai