|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)arcs.c 5.2 (Berkeley) 6/4/85"; ! 9: #endif not lint ! 10: ! 11: #include "gprof.h" ! 12: ! 13: /* ! 14: * add (or just increment) an arc ! 15: */ ! 16: addarc( parentp , childp , count ) ! 17: nltype *parentp; ! 18: nltype *childp; ! 19: long count; ! 20: { ! 21: arctype *calloc(); ! 22: arctype *arcp; ! 23: ! 24: # ifdef DEBUG ! 25: if ( debug & TALLYDEBUG ) { ! 26: printf( "[addarc] %d arcs from %s to %s\n" , ! 27: count , parentp -> name , childp -> name ); ! 28: } ! 29: # endif DEBUG ! 30: arcp = arclookup( parentp , childp ); ! 31: if ( arcp != 0 ) { ! 32: /* ! 33: * a hit: just increment the count. ! 34: */ ! 35: # ifdef DEBUG ! 36: if ( debug & TALLYDEBUG ) { ! 37: printf( "[tally] hit %d += %d\n" , ! 38: arcp -> arc_count , count ); ! 39: } ! 40: # endif DEBUG ! 41: arcp -> arc_count += count; ! 42: return; ! 43: } ! 44: arcp = calloc( 1 , sizeof *arcp ); ! 45: arcp -> arc_parentp = parentp; ! 46: arcp -> arc_childp = childp; ! 47: arcp -> arc_count = count; ! 48: /* ! 49: * prepend this child to the children of this parent ! 50: */ ! 51: arcp -> arc_childlist = parentp -> children; ! 52: parentp -> children = arcp; ! 53: /* ! 54: * prepend this parent to the parents of this child ! 55: */ ! 56: arcp -> arc_parentlist = childp -> parents; ! 57: childp -> parents = arcp; ! 58: } ! 59: ! 60: /* ! 61: * the code below topologically sorts the graph (collapsing cycles), ! 62: * and propagates time bottom up and flags top down. ! 63: */ ! 64: ! 65: /* ! 66: * the topologically sorted name list pointers ! 67: */ ! 68: nltype **topsortnlp; ! 69: ! 70: topcmp( npp1 , npp2 ) ! 71: nltype **npp1; ! 72: nltype **npp2; ! 73: { ! 74: return (*npp1) -> toporder - (*npp2) -> toporder; ! 75: } ! 76: ! 77: nltype ** ! 78: doarcs() ! 79: { ! 80: nltype *parentp, **timesortnlp; ! 81: arctype *arcp; ! 82: long index; ! 83: ! 84: /* ! 85: * initialize various things: ! 86: * zero out child times. ! 87: * count self-recursive calls. ! 88: * indicate that nothing is on cycles. ! 89: */ ! 90: for ( parentp = nl ; parentp < npe ; parentp++ ) { ! 91: parentp -> childtime = 0.0; ! 92: arcp = arclookup( parentp , parentp ); ! 93: if ( arcp != 0 ) { ! 94: parentp -> ncall -= arcp -> arc_count; ! 95: parentp -> selfcalls = arcp -> arc_count; ! 96: } else { ! 97: parentp -> selfcalls = 0; ! 98: } ! 99: parentp -> propfraction = 0.0; ! 100: parentp -> propself = 0.0; ! 101: parentp -> propchild = 0.0; ! 102: parentp -> printflag = FALSE; ! 103: parentp -> toporder = DFN_NAN; ! 104: parentp -> cycleno = 0; ! 105: parentp -> cyclehead = parentp; ! 106: parentp -> cnext = 0; ! 107: if ( cflag ) { ! 108: findcalls( parentp , parentp -> value , (parentp+1) -> value ); ! 109: } ! 110: } ! 111: /* ! 112: * topologically order things ! 113: * if any node is unnumbered, ! 114: * number it and any of its descendents. ! 115: */ ! 116: for ( parentp = nl ; parentp < npe ; parentp++ ) { ! 117: if ( parentp -> toporder == DFN_NAN ) { ! 118: dfn( parentp ); ! 119: } ! 120: } ! 121: /* ! 122: * link together nodes on the same cycle ! 123: */ ! 124: cyclelink(); ! 125: /* ! 126: * Sort the symbol table in reverse topological order ! 127: */ ! 128: topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) ); ! 129: if ( topsortnlp == (nltype **) 0 ) { ! 130: fprintf( stderr , "[doarcs] ran out of memory for topo sorting\n" ); ! 131: } ! 132: for ( index = 0 ; index < nname ; index += 1 ) { ! 133: topsortnlp[ index ] = &nl[ index ]; ! 134: } ! 135: qsort( topsortnlp , nname , sizeof(nltype *) , topcmp ); ! 136: # ifdef DEBUG ! 137: if ( debug & DFNDEBUG ) { ! 138: printf( "[doarcs] topological sort listing\n" ); ! 139: for ( index = 0 ; index < nname ; index += 1 ) { ! 140: printf( "[doarcs] " ); ! 141: printf( "%d:" , topsortnlp[ index ] -> toporder ); ! 142: printname( topsortnlp[ index ] ); ! 143: printf( "\n" ); ! 144: } ! 145: } ! 146: # endif DEBUG ! 147: /* ! 148: * starting from the topological top, ! 149: * propagate print flags to children. ! 150: * also, calculate propagation fractions. ! 151: * this happens before time propagation ! 152: * since time propagation uses the fractions. ! 153: */ ! 154: doflags(); ! 155: /* ! 156: * starting from the topological bottom, ! 157: * propogate children times up to parents. ! 158: */ ! 159: dotime(); ! 160: /* ! 161: * Now, sort by propself + propchild. ! 162: * sorting both the regular function names ! 163: * and cycle headers. ! 164: */ ! 165: timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); ! 166: if ( timesortnlp == (nltype **) 0 ) { ! 167: fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami ); ! 168: } ! 169: for ( index = 0 ; index < nname ; index++ ) { ! 170: timesortnlp[index] = &nl[index]; ! 171: } ! 172: for ( index = 1 ; index <= ncycle ; index++ ) { ! 173: timesortnlp[nname+index-1] = &cyclenl[index]; ! 174: } ! 175: qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp ); ! 176: for ( index = 0 ; index < nname + ncycle ; index++ ) { ! 177: timesortnlp[ index ] -> index = index + 1; ! 178: } ! 179: return( timesortnlp ); ! 180: } ! 181: ! 182: dotime() ! 183: { ! 184: int index; ! 185: ! 186: cycletime(); ! 187: for ( index = 0 ; index < nname ; index += 1 ) { ! 188: timepropagate( topsortnlp[ index ] ); ! 189: } ! 190: } ! 191: ! 192: timepropagate( parentp ) ! 193: nltype *parentp; ! 194: { ! 195: arctype *arcp; ! 196: nltype *childp; ! 197: double share; ! 198: double propshare; ! 199: ! 200: if ( parentp -> propfraction == 0.0 ) { ! 201: return; ! 202: } ! 203: /* ! 204: * gather time from children of this parent. ! 205: */ ! 206: for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { ! 207: childp = arcp -> arc_childp; ! 208: if ( arcp -> arc_count == 0 ) { ! 209: continue; ! 210: } ! 211: if ( childp == parentp ) { ! 212: continue; ! 213: } ! 214: if ( childp -> propfraction == 0.0 ) { ! 215: continue; ! 216: } ! 217: if ( childp -> cyclehead != childp ) { ! 218: if ( parentp -> cycleno == childp -> cycleno ) { ! 219: continue; ! 220: } ! 221: if ( parentp -> toporder <= childp -> toporder ) { ! 222: fprintf( stderr , "[propagate] toporder botches\n" ); ! 223: } ! 224: childp = childp -> cyclehead; ! 225: } else { ! 226: if ( parentp -> toporder <= childp -> toporder ) { ! 227: fprintf( stderr , "[propagate] toporder botches\n" ); ! 228: continue; ! 229: } ! 230: } ! 231: if ( childp -> ncall == 0 ) { ! 232: continue; ! 233: } ! 234: /* ! 235: * distribute time for this arc ! 236: */ ! 237: arcp -> arc_time = childp -> time ! 238: * ( ( (double) arcp -> arc_count ) / ! 239: ( (double) childp -> ncall ) ); ! 240: arcp -> arc_childtime = childp -> childtime ! 241: * ( ( (double) arcp -> arc_count ) / ! 242: ( (double) childp -> ncall ) ); ! 243: share = arcp -> arc_time + arcp -> arc_childtime; ! 244: parentp -> childtime += share; ! 245: /* ! 246: * ( 1 - propfraction ) gets lost along the way ! 247: */ ! 248: propshare = parentp -> propfraction * share; ! 249: /* ! 250: * fix things for printing ! 251: */ ! 252: parentp -> propchild += propshare; ! 253: arcp -> arc_time *= parentp -> propfraction; ! 254: arcp -> arc_childtime *= parentp -> propfraction; ! 255: /* ! 256: * add this share to the parent's cycle header, if any. ! 257: */ ! 258: if ( parentp -> cyclehead != parentp ) { ! 259: parentp -> cyclehead -> childtime += share; ! 260: parentp -> cyclehead -> propchild += propshare; ! 261: } ! 262: # ifdef DEBUG ! 263: if ( debug & PROPDEBUG ) { ! 264: printf( "[dotime] child \t" ); ! 265: printname( childp ); ! 266: printf( " with %f %f %d/%d\n" , ! 267: childp -> time , childp -> childtime , ! 268: arcp -> arc_count , childp -> ncall ); ! 269: printf( "[dotime] parent\t" ); ! 270: printname( parentp ); ! 271: printf( "\n[dotime] share %f\n" , share ); ! 272: } ! 273: # endif DEBUG ! 274: } ! 275: } ! 276: ! 277: cyclelink() ! 278: { ! 279: register nltype *nlp; ! 280: register nltype *cyclenlp; ! 281: int cycle; ! 282: nltype *memberp; ! 283: arctype *arcp; ! 284: ! 285: /* ! 286: * Count the number of cycles, and initialze the cycle lists ! 287: */ ! 288: ncycle = 0; ! 289: for ( nlp = nl ; nlp < npe ; nlp++ ) { ! 290: /* ! 291: * this is how you find unattached cycles ! 292: */ ! 293: if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) { ! 294: ncycle += 1; ! 295: } ! 296: } ! 297: /* ! 298: * cyclenl is indexed by cycle number: ! 299: * i.e. it is origin 1, not origin 0. ! 300: */ ! 301: cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) ); ! 302: if ( cyclenl == 0 ) { ! 303: fprintf( stderr , "%s: No room for %d bytes of cycle headers\n" , ! 304: whoami , ( ncycle + 1 ) * sizeof( nltype ) ); ! 305: done(); ! 306: } ! 307: /* ! 308: * now link cycles to true cycleheads, ! 309: * number them, accumulate the data for the cycle ! 310: */ ! 311: cycle = 0; ! 312: for ( nlp = nl ; nlp < npe ; nlp++ ) { ! 313: if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) { ! 314: continue; ! 315: } ! 316: cycle += 1; ! 317: cyclenlp = &cyclenl[cycle]; ! 318: cyclenlp -> name = 0; /* the name */ ! 319: cyclenlp -> value = 0; /* the pc entry point */ ! 320: cyclenlp -> time = 0.0; /* ticks in this routine */ ! 321: cyclenlp -> childtime = 0.0; /* cumulative ticks in children */ ! 322: cyclenlp -> ncall = 0; /* how many times called */ ! 323: cyclenlp -> selfcalls = 0; /* how many calls to self */ ! 324: cyclenlp -> propfraction = 0.0; /* what % of time propagates */ ! 325: cyclenlp -> propself = 0.0; /* how much self time propagates */ ! 326: cyclenlp -> propchild = 0.0; /* how much child time propagates */ ! 327: cyclenlp -> printflag = TRUE; /* should this be printed? */ ! 328: cyclenlp -> index = 0; /* index in the graph list */ ! 329: cyclenlp -> toporder = DFN_NAN; /* graph call chain top-sort order */ ! 330: cyclenlp -> cycleno = cycle; /* internal number of cycle on */ ! 331: cyclenlp -> cyclehead = cyclenlp; /* pointer to head of cycle */ ! 332: cyclenlp -> cnext = nlp; /* pointer to next member of cycle */ ! 333: cyclenlp -> parents = 0; /* list of caller arcs */ ! 334: cyclenlp -> children = 0; /* list of callee arcs */ ! 335: # ifdef DEBUG ! 336: if ( debug & CYCLEDEBUG ) { ! 337: printf( "[cyclelink] " ); ! 338: printname( nlp ); ! 339: printf( " is the head of cycle %d\n" , cycle ); ! 340: } ! 341: # endif DEBUG ! 342: /* ! 343: * link members to cycle header ! 344: */ ! 345: for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { ! 346: memberp -> cycleno = cycle; ! 347: memberp -> cyclehead = cyclenlp; ! 348: } ! 349: /* ! 350: * count calls from outside the cycle ! 351: * and those among cycle members ! 352: */ ! 353: for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { ! 354: for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) { ! 355: if ( arcp -> arc_parentp == memberp ) { ! 356: continue; ! 357: } ! 358: if ( arcp -> arc_parentp -> cycleno == cycle ) { ! 359: cyclenlp -> selfcalls += arcp -> arc_count; ! 360: } else { ! 361: cyclenlp -> ncall += arcp -> arc_count; ! 362: } ! 363: } ! 364: } ! 365: } ! 366: } ! 367: ! 368: cycletime() ! 369: { ! 370: int cycle; ! 371: nltype *cyclenlp; ! 372: nltype *childp; ! 373: ! 374: for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) { ! 375: cyclenlp = &cyclenl[ cycle ]; ! 376: for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) { ! 377: if ( childp -> propfraction == 0.0 ) { ! 378: /* ! 379: * all members have the same propfraction except those ! 380: * that were excluded with -E ! 381: */ ! 382: continue; ! 383: } ! 384: cyclenlp -> time += childp -> time; ! 385: } ! 386: cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time; ! 387: } ! 388: } ! 389: ! 390: /* ! 391: * in one top to bottom pass over the topologically sorted namelist ! 392: * propagate: ! 393: * printflag as the union of parents' printflags ! 394: * propfraction as the sum of fractional parents' propfractions ! 395: * and while we're here, sum time for functions. ! 396: */ ! 397: doflags() ! 398: { ! 399: int index; ! 400: nltype *childp; ! 401: nltype *oldhead; ! 402: ! 403: oldhead = 0; ! 404: for ( index = nname-1 ; index >= 0 ; index -= 1 ) { ! 405: childp = topsortnlp[ index ]; ! 406: /* ! 407: * if we haven't done this function or cycle, ! 408: * inherit things from parent. ! 409: * this way, we are linear in the number of arcs ! 410: * since we do all members of a cycle (and the cycle itself) ! 411: * as we hit the first member of the cycle. ! 412: */ ! 413: if ( childp -> cyclehead != oldhead ) { ! 414: oldhead = childp -> cyclehead; ! 415: inheritflags( childp ); ! 416: } ! 417: # ifdef DEBUG ! 418: if ( debug & PROPDEBUG ) { ! 419: printf( "[doflags] " ); ! 420: printname( childp ); ! 421: printf( " inherits printflag %d and propfraction %f\n" , ! 422: childp -> printflag , childp -> propfraction ); ! 423: } ! 424: # endif DEBUG ! 425: if ( ! childp -> printflag ) { ! 426: /* ! 427: * printflag is off ! 428: * it gets turned on by ! 429: * being on -f list, ! 430: * or there not being any -f list and not being on -e list. ! 431: */ ! 432: if ( onlist( flist , childp -> name ) ! 433: || ( !fflag && !onlist( elist , childp -> name ) ) ) { ! 434: childp -> printflag = TRUE; ! 435: } ! 436: } else { ! 437: /* ! 438: * this function has printing parents: ! 439: * maybe someone wants to shut it up ! 440: * by putting it on -e list. (but favor -f over -e) ! 441: */ ! 442: if ( ( !onlist( flist , childp -> name ) ) ! 443: && onlist( elist , childp -> name ) ) { ! 444: childp -> printflag = FALSE; ! 445: } ! 446: } ! 447: if ( childp -> propfraction == 0.0 ) { ! 448: /* ! 449: * no parents to pass time to. ! 450: * collect time from children if ! 451: * its on -F list, ! 452: * or there isn't any -F list and its not on -E list. ! 453: */ ! 454: if ( onlist( Flist , childp -> name ) ! 455: || ( !Fflag && !onlist( Elist , childp -> name ) ) ) { ! 456: childp -> propfraction = 1.0; ! 457: } ! 458: } else { ! 459: /* ! 460: * it has parents to pass time to, ! 461: * but maybe someone wants to shut it up ! 462: * by puttting it on -E list. (but favor -F over -E) ! 463: */ ! 464: if ( !onlist( Flist , childp -> name ) ! 465: && onlist( Elist , childp -> name ) ) { ! 466: childp -> propfraction = 0.0; ! 467: } ! 468: } ! 469: childp -> propself = childp -> time * childp -> propfraction; ! 470: printtime += childp -> propself; ! 471: # ifdef DEBUG ! 472: if ( debug & PROPDEBUG ) { ! 473: printf( "[doflags] " ); ! 474: printname( childp ); ! 475: printf( " ends up with printflag %d and propfraction %f\n" , ! 476: childp -> printflag , childp -> propfraction ); ! 477: printf( "time %f propself %f printtime %f\n" , ! 478: childp -> time , childp -> propself , printtime ); ! 479: } ! 480: # endif DEBUG ! 481: } ! 482: } ! 483: ! 484: /* ! 485: * check if any parent of this child ! 486: * (or outside parents of this cycle) ! 487: * have their print flags on and set the ! 488: * print flag of the child (cycle) appropriately. ! 489: * similarly, deal with propagation fractions from parents. ! 490: */ ! 491: inheritflags( childp ) ! 492: nltype *childp; ! 493: { ! 494: nltype *headp; ! 495: arctype *arcp; ! 496: nltype *parentp; ! 497: nltype *memp; ! 498: ! 499: headp = childp -> cyclehead; ! 500: if ( childp == headp ) { ! 501: /* ! 502: * just a regular child, check its parents ! 503: */ ! 504: childp -> printflag = FALSE; ! 505: childp -> propfraction = 0.0; ! 506: for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) { ! 507: parentp = arcp -> arc_parentp; ! 508: if ( childp == parentp ) { ! 509: continue; ! 510: } ! 511: childp -> printflag |= parentp -> printflag; ! 512: /* ! 513: * if the child was never actually called ! 514: * (e.g. this arc is static (and all others are, too)) ! 515: * no time propagates along this arc. ! 516: */ ! 517: if ( childp -> ncall ) { ! 518: childp -> propfraction += parentp -> propfraction ! 519: * ( ( (double) arcp -> arc_count ) ! 520: / ( (double) childp -> ncall ) ); ! 521: } ! 522: } ! 523: } else { ! 524: /* ! 525: * its a member of a cycle, look at all parents from ! 526: * outside the cycle ! 527: */ ! 528: headp -> printflag = FALSE; ! 529: headp -> propfraction = 0.0; ! 530: for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) { ! 531: for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) { ! 532: if ( arcp -> arc_parentp -> cyclehead == headp ) { ! 533: continue; ! 534: } ! 535: parentp = arcp -> arc_parentp; ! 536: headp -> printflag |= parentp -> printflag; ! 537: /* ! 538: * if the cycle was never actually called ! 539: * (e.g. this arc is static (and all others are, too)) ! 540: * no time propagates along this arc. ! 541: */ ! 542: if ( headp -> ncall ) { ! 543: headp -> propfraction += parentp -> propfraction ! 544: * ( ( (double) arcp -> arc_count ) ! 545: / ( (double) headp -> ncall ) ); ! 546: } ! 547: } ! 548: } ! 549: for ( memp = headp ; memp ; memp = memp -> cnext ) { ! 550: memp -> printflag = headp -> printflag; ! 551: memp -> propfraction = headp -> propfraction; ! 552: } ! 553: } ! 554: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.