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: }

Defined functions

cyclelink defined in line 277; used 2 times
cycletime defined in line 368; used 1 times
doarcs defined in line 77; used 2 times
doflags defined in line 397; used 1 times
dotime defined in line 182; used 1 times
inheritflags defined in line 491; used 1 times
timepropagate defined in line 192; used 1 times
topcmp defined in line 70; used 2 times

Defined variables

sccsid defined in line 8; never used
topsortnlp defined in line 68; used 8 times
Last modified: 1985-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1997
Valid CSS Valid XHTML 1.0 Strict