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