Annotation of 42BSD/ucb/gprof/arcs.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.