Annotation of 43BSD/ucb/gprof/arcs.c, revision 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.