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

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

unix.superglobalmegacorp.com

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