arcs.c revision 99112
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1983, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 3527313Scharnier#if 0 3627327Scharnierstatic char sccsid[] = "@(#)arcs.c 8.1 (Berkeley) 6/6/93"; 3727313Scharnier#endif 381590Srgrimes#endif /* not lint */ 3999112Sobrien#include <sys/cdefs.h> 4099112Sobrien__FBSDID("$FreeBSD: head/usr.bin/gprof/arcs.c 99112 2002-06-30 05:25:07Z obrien $"); 411590Srgrimes 4227313Scharnier#include <err.h> 431590Srgrimes#include "gprof.h" 441590Srgrimes 451590Srgrimes#ifdef DEBUG 461590Srgrimesint visited; 471590Srgrimesint viable; 481590Srgrimesint newcycle; 491590Srgrimesint oldcycle; 5097631Swollman#endif /* DEBUG */ 511590Srgrimes 521590Srgrimes /* 531590Srgrimes * add (or just increment) an arc 541590Srgrimes */ 551590Srgrimesaddarc( parentp , childp , count ) 561590Srgrimes nltype *parentp; 571590Srgrimes nltype *childp; 581590Srgrimes long count; 591590Srgrimes{ 601590Srgrimes arctype *arcp; 611590Srgrimes 621590Srgrimes# ifdef DEBUG 631590Srgrimes if ( debug & TALLYDEBUG ) { 6491018Sbde printf( "[addarc] %ld arcs from %s to %s\n" , 651590Srgrimes count , parentp -> name , childp -> name ); 661590Srgrimes } 6797631Swollman# endif /* DEBUG */ 681590Srgrimes arcp = arclookup( parentp , childp ); 691590Srgrimes if ( arcp != 0 ) { 701590Srgrimes /* 711590Srgrimes * a hit: just increment the count. 721590Srgrimes */ 731590Srgrimes# ifdef DEBUG 741590Srgrimes if ( debug & TALLYDEBUG ) { 7591018Sbde printf( "[tally] hit %ld += %ld\n" , 761590Srgrimes arcp -> arc_count , count ); 771590Srgrimes } 7897631Swollman# endif /* DEBUG */ 791590Srgrimes arcp -> arc_count += count; 801590Srgrimes return; 811590Srgrimes } 821590Srgrimes arcp = (arctype *)calloc( 1 , sizeof *arcp ); 831590Srgrimes arcp -> arc_parentp = parentp; 841590Srgrimes arcp -> arc_childp = childp; 851590Srgrimes arcp -> arc_count = count; 861590Srgrimes /* 871590Srgrimes * prepend this child to the children of this parent 881590Srgrimes */ 891590Srgrimes arcp -> arc_childlist = parentp -> children; 901590Srgrimes parentp -> children = arcp; 911590Srgrimes /* 921590Srgrimes * prepend this parent to the parents of this child 931590Srgrimes */ 941590Srgrimes arcp -> arc_parentlist = childp -> parents; 951590Srgrimes childp -> parents = arcp; 961590Srgrimes} 971590Srgrimes 981590Srgrimes /* 991590Srgrimes * the code below topologically sorts the graph (collapsing cycles), 1001590Srgrimes * and propagates time bottom up and flags top down. 1011590Srgrimes */ 1021590Srgrimes 1031590Srgrimes /* 1041590Srgrimes * the topologically sorted name list pointers 1051590Srgrimes */ 1061590Srgrimesnltype **topsortnlp; 1071590Srgrimes 1081590Srgrimestopcmp( npp1 , npp2 ) 1091590Srgrimes nltype **npp1; 1101590Srgrimes nltype **npp2; 1111590Srgrimes{ 1121590Srgrimes return (*npp1) -> toporder - (*npp2) -> toporder; 1131590Srgrimes} 1141590Srgrimes 1151590Srgrimesnltype ** 1161590Srgrimesdoarcs() 1171590Srgrimes{ 1181590Srgrimes nltype *parentp, **timesortnlp; 1191590Srgrimes arctype *arcp; 1201590Srgrimes long index; 1211590Srgrimes long pass; 1221590Srgrimes 1231590Srgrimes /* 1241590Srgrimes * initialize various things: 1251590Srgrimes * zero out child times. 1261590Srgrimes * count self-recursive calls. 1271590Srgrimes * indicate that nothing is on cycles. 1281590Srgrimes */ 1291590Srgrimes for ( parentp = nl ; parentp < npe ; parentp++ ) { 1301590Srgrimes parentp -> childtime = 0.0; 1311590Srgrimes arcp = arclookup( parentp , parentp ); 1321590Srgrimes if ( arcp != 0 ) { 1331590Srgrimes parentp -> ncall -= arcp -> arc_count; 1341590Srgrimes parentp -> selfcalls = arcp -> arc_count; 1351590Srgrimes } else { 1361590Srgrimes parentp -> selfcalls = 0; 1371590Srgrimes } 1381590Srgrimes parentp -> npropcall = parentp -> ncall; 1391590Srgrimes parentp -> propfraction = 0.0; 1401590Srgrimes parentp -> propself = 0.0; 1411590Srgrimes parentp -> propchild = 0.0; 1421590Srgrimes parentp -> printflag = FALSE; 1431590Srgrimes parentp -> toporder = DFN_NAN; 1441590Srgrimes parentp -> cycleno = 0; 1451590Srgrimes parentp -> cyclehead = parentp; 1461590Srgrimes parentp -> cnext = 0; 1471590Srgrimes if ( cflag ) { 1481590Srgrimes findcall( parentp , parentp -> value , (parentp+1) -> value ); 1491590Srgrimes } 1501590Srgrimes } 1511590Srgrimes for ( pass = 1 ; ; pass++ ) { 1521590Srgrimes /* 1531590Srgrimes * topologically order things 1541590Srgrimes * if any node is unnumbered, 1551590Srgrimes * number it and any of its descendents. 1561590Srgrimes */ 1571590Srgrimes for ( dfn_init() , parentp = nl ; parentp < npe ; parentp++ ) { 1581590Srgrimes if ( parentp -> toporder == DFN_NAN ) { 1591590Srgrimes dfn( parentp ); 1601590Srgrimes } 1611590Srgrimes } 1621590Srgrimes /* 1631590Srgrimes * link together nodes on the same cycle 1641590Srgrimes */ 1651590Srgrimes cyclelink(); 1661590Srgrimes /* 1671590Srgrimes * if no cycles to break up, proceed 1681590Srgrimes */ 1691590Srgrimes if ( ! Cflag ) 1701590Srgrimes break; 1711590Srgrimes /* 1721590Srgrimes * analyze cycles to determine breakup 1731590Srgrimes */ 1741590Srgrimes# ifdef DEBUG 1751590Srgrimes if ( debug & BREAKCYCLE ) { 17691018Sbde printf("[doarcs] pass %ld, cycle(s) %d\n" , pass , ncycle ); 1771590Srgrimes } 17897631Swollman# endif /* DEBUG */ 1791590Srgrimes if ( pass == 1 ) { 1801590Srgrimes printf( "\n\n%s %s\n%s %d:\n" , 1811590Srgrimes "The following arcs were deleted" , 1821590Srgrimes "from the propagation calculation" , 1831590Srgrimes "to reduce the maximum cycle size to", cyclethreshold ); 1841590Srgrimes } 1851590Srgrimes if ( cycleanalyze() ) 1861590Srgrimes break; 1871590Srgrimes free ( cyclenl ); 1881590Srgrimes ncycle = 0; 1891590Srgrimes for ( parentp = nl ; parentp < npe ; parentp++ ) { 1901590Srgrimes parentp -> toporder = DFN_NAN; 1911590Srgrimes parentp -> cycleno = 0; 1921590Srgrimes parentp -> cyclehead = parentp; 1931590Srgrimes parentp -> cnext = 0; 1941590Srgrimes } 1951590Srgrimes } 1961590Srgrimes if ( pass > 1 ) { 1971590Srgrimes printf( "\f\n" ); 1981590Srgrimes } else { 1991590Srgrimes printf( "\tNone\n\n" ); 2001590Srgrimes } 2011590Srgrimes /* 2021590Srgrimes * Sort the symbol table in reverse topological order 2031590Srgrimes */ 2041590Srgrimes topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) ); 2051590Srgrimes if ( topsortnlp == (nltype **) 0 ) { 2061590Srgrimes fprintf( stderr , "[doarcs] ran out of memory for topo sorting\n" ); 2071590Srgrimes } 2081590Srgrimes for ( index = 0 ; index < nname ; index += 1 ) { 2091590Srgrimes topsortnlp[ index ] = &nl[ index ]; 2101590Srgrimes } 2111590Srgrimes qsort( topsortnlp , nname , sizeof(nltype *) , topcmp ); 2121590Srgrimes# ifdef DEBUG 2131590Srgrimes if ( debug & DFNDEBUG ) { 2141590Srgrimes printf( "[doarcs] topological sort listing\n" ); 2151590Srgrimes for ( index = 0 ; index < nname ; index += 1 ) { 2161590Srgrimes printf( "[doarcs] " ); 2171590Srgrimes printf( "%d:" , topsortnlp[ index ] -> toporder ); 2181590Srgrimes printname( topsortnlp[ index ] ); 2191590Srgrimes printf( "\n" ); 2201590Srgrimes } 2211590Srgrimes } 22297631Swollman# endif /* DEBUG */ 2231590Srgrimes /* 2241590Srgrimes * starting from the topological top, 2251590Srgrimes * propagate print flags to children. 2261590Srgrimes * also, calculate propagation fractions. 2271590Srgrimes * this happens before time propagation 2281590Srgrimes * since time propagation uses the fractions. 2291590Srgrimes */ 2301590Srgrimes doflags(); 2311590Srgrimes /* 2328874Srgrimes * starting from the topological bottom, 2331590Srgrimes * propogate children times up to parents. 2341590Srgrimes */ 2351590Srgrimes dotime(); 2361590Srgrimes /* 2371590Srgrimes * Now, sort by propself + propchild. 2381590Srgrimes * sorting both the regular function names 2391590Srgrimes * and cycle headers. 2401590Srgrimes */ 2411590Srgrimes timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); 2421590Srgrimes if ( timesortnlp == (nltype **) 0 ) { 24327313Scharnier warnx("ran out of memory for sorting"); 2441590Srgrimes } 2451590Srgrimes for ( index = 0 ; index < nname ; index++ ) { 2461590Srgrimes timesortnlp[index] = &nl[index]; 2471590Srgrimes } 2481590Srgrimes for ( index = 1 ; index <= ncycle ; index++ ) { 2491590Srgrimes timesortnlp[nname+index-1] = &cyclenl[index]; 2501590Srgrimes } 2511590Srgrimes qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp ); 2521590Srgrimes for ( index = 0 ; index < nname + ncycle ; index++ ) { 2531590Srgrimes timesortnlp[ index ] -> index = index + 1; 2541590Srgrimes } 2551590Srgrimes return( timesortnlp ); 2561590Srgrimes} 2571590Srgrimes 2581590Srgrimesdotime() 2591590Srgrimes{ 2601590Srgrimes int index; 2611590Srgrimes 2621590Srgrimes cycletime(); 2631590Srgrimes for ( index = 0 ; index < nname ; index += 1 ) { 2641590Srgrimes timepropagate( topsortnlp[ index ] ); 2651590Srgrimes } 2661590Srgrimes} 2671590Srgrimes 2681590Srgrimestimepropagate( parentp ) 2691590Srgrimes nltype *parentp; 2701590Srgrimes{ 2711590Srgrimes arctype *arcp; 2721590Srgrimes nltype *childp; 2731590Srgrimes double share; 2741590Srgrimes double propshare; 2751590Srgrimes 2761590Srgrimes if ( parentp -> propfraction == 0.0 ) { 2771590Srgrimes return; 2781590Srgrimes } 2791590Srgrimes /* 2801590Srgrimes * gather time from children of this parent. 2811590Srgrimes */ 2821590Srgrimes for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 2831590Srgrimes childp = arcp -> arc_childp; 2841590Srgrimes if ( arcp -> arc_flags & DEADARC ) { 2851590Srgrimes continue; 2861590Srgrimes } 2871590Srgrimes if ( arcp -> arc_count == 0 ) { 2881590Srgrimes continue; 2891590Srgrimes } 2901590Srgrimes if ( childp == parentp ) { 2911590Srgrimes continue; 2921590Srgrimes } 2931590Srgrimes if ( childp -> propfraction == 0.0 ) { 2941590Srgrimes continue; 2951590Srgrimes } 2961590Srgrimes if ( childp -> cyclehead != childp ) { 2971590Srgrimes if ( parentp -> cycleno == childp -> cycleno ) { 2981590Srgrimes continue; 2991590Srgrimes } 3001590Srgrimes if ( parentp -> toporder <= childp -> toporder ) { 3011590Srgrimes fprintf( stderr , "[propagate] toporder botches\n" ); 3021590Srgrimes } 3031590Srgrimes childp = childp -> cyclehead; 3041590Srgrimes } else { 3051590Srgrimes if ( parentp -> toporder <= childp -> toporder ) { 3061590Srgrimes fprintf( stderr , "[propagate] toporder botches\n" ); 3071590Srgrimes continue; 3081590Srgrimes } 3091590Srgrimes } 3101590Srgrimes if ( childp -> npropcall == 0 ) { 3111590Srgrimes continue; 3121590Srgrimes } 3131590Srgrimes /* 3141590Srgrimes * distribute time for this arc 3151590Srgrimes */ 3161590Srgrimes arcp -> arc_time = childp -> time 3171590Srgrimes * ( ( (double) arcp -> arc_count ) / 3181590Srgrimes ( (double) childp -> npropcall ) ); 3191590Srgrimes arcp -> arc_childtime = childp -> childtime 3201590Srgrimes * ( ( (double) arcp -> arc_count ) / 3211590Srgrimes ( (double) childp -> npropcall ) ); 3221590Srgrimes share = arcp -> arc_time + arcp -> arc_childtime; 3231590Srgrimes parentp -> childtime += share; 3241590Srgrimes /* 3251590Srgrimes * ( 1 - propfraction ) gets lost along the way 3261590Srgrimes */ 3271590Srgrimes propshare = parentp -> propfraction * share; 3281590Srgrimes /* 3291590Srgrimes * fix things for printing 3301590Srgrimes */ 3311590Srgrimes parentp -> propchild += propshare; 3321590Srgrimes arcp -> arc_time *= parentp -> propfraction; 3331590Srgrimes arcp -> arc_childtime *= parentp -> propfraction; 3341590Srgrimes /* 3351590Srgrimes * add this share to the parent's cycle header, if any. 3361590Srgrimes */ 3371590Srgrimes if ( parentp -> cyclehead != parentp ) { 3381590Srgrimes parentp -> cyclehead -> childtime += share; 3391590Srgrimes parentp -> cyclehead -> propchild += propshare; 3401590Srgrimes } 3411590Srgrimes# ifdef DEBUG 3421590Srgrimes if ( debug & PROPDEBUG ) { 3431590Srgrimes printf( "[dotime] child \t" ); 3441590Srgrimes printname( childp ); 34591018Sbde printf( " with %f %f %ld/%ld\n" , 3461590Srgrimes childp -> time , childp -> childtime , 3471590Srgrimes arcp -> arc_count , childp -> npropcall ); 3481590Srgrimes printf( "[dotime] parent\t" ); 3491590Srgrimes printname( parentp ); 3501590Srgrimes printf( "\n[dotime] share %f\n" , share ); 3511590Srgrimes } 35297631Swollman# endif /* DEBUG */ 3531590Srgrimes } 3541590Srgrimes} 3551590Srgrimes 3561590Srgrimescyclelink() 3571590Srgrimes{ 3581590Srgrimes register nltype *nlp; 3591590Srgrimes register nltype *cyclenlp; 3601590Srgrimes int cycle; 3611590Srgrimes nltype *memberp; 3621590Srgrimes arctype *arcp; 3631590Srgrimes 3641590Srgrimes /* 3651590Srgrimes * Count the number of cycles, and initialze the cycle lists 3661590Srgrimes */ 3671590Srgrimes ncycle = 0; 3681590Srgrimes for ( nlp = nl ; nlp < npe ; nlp++ ) { 3691590Srgrimes /* 3701590Srgrimes * this is how you find unattached cycles 3711590Srgrimes */ 3721590Srgrimes if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) { 3731590Srgrimes ncycle += 1; 3741590Srgrimes } 3751590Srgrimes } 3761590Srgrimes /* 3771590Srgrimes * cyclenl is indexed by cycle number: 3781590Srgrimes * i.e. it is origin 1, not origin 0. 3791590Srgrimes */ 3801590Srgrimes cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) ); 3811590Srgrimes if ( cyclenl == 0 ) { 38227414Scharnier warnx("no room for %d bytes of cycle headers", 38327414Scharnier ( ncycle + 1 ) * sizeof( nltype ) ); 3841590Srgrimes done(); 3851590Srgrimes } 3861590Srgrimes /* 3871590Srgrimes * now link cycles to true cycleheads, 3881590Srgrimes * number them, accumulate the data for the cycle 3891590Srgrimes */ 3901590Srgrimes cycle = 0; 3911590Srgrimes for ( nlp = nl ; nlp < npe ; nlp++ ) { 3921590Srgrimes if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) { 3931590Srgrimes continue; 3941590Srgrimes } 3951590Srgrimes cycle += 1; 3961590Srgrimes cyclenlp = &cyclenl[cycle]; 3971590Srgrimes cyclenlp -> name = 0; /* the name */ 3981590Srgrimes cyclenlp -> value = 0; /* the pc entry point */ 3991590Srgrimes cyclenlp -> time = 0.0; /* ticks in this routine */ 4001590Srgrimes cyclenlp -> childtime = 0.0; /* cumulative ticks in children */ 4011590Srgrimes cyclenlp -> ncall = 0; /* how many times called */ 4021590Srgrimes cyclenlp -> selfcalls = 0; /* how many calls to self */ 4031590Srgrimes cyclenlp -> propfraction = 0.0; /* what % of time propagates */ 4041590Srgrimes cyclenlp -> propself = 0.0; /* how much self time propagates */ 4051590Srgrimes cyclenlp -> propchild = 0.0; /* how much child time propagates */ 4061590Srgrimes cyclenlp -> printflag = TRUE; /* should this be printed? */ 4071590Srgrimes cyclenlp -> index = 0; /* index in the graph list */ 4081590Srgrimes cyclenlp -> toporder = DFN_NAN; /* graph call chain top-sort order */ 4091590Srgrimes cyclenlp -> cycleno = cycle; /* internal number of cycle on */ 4101590Srgrimes cyclenlp -> cyclehead = cyclenlp; /* pointer to head of cycle */ 4111590Srgrimes cyclenlp -> cnext = nlp; /* pointer to next member of cycle */ 4121590Srgrimes cyclenlp -> parents = 0; /* list of caller arcs */ 4131590Srgrimes cyclenlp -> children = 0; /* list of callee arcs */ 4141590Srgrimes# ifdef DEBUG 4151590Srgrimes if ( debug & CYCLEDEBUG ) { 4161590Srgrimes printf( "[cyclelink] " ); 4171590Srgrimes printname( nlp ); 4181590Srgrimes printf( " is the head of cycle %d\n" , cycle ); 4191590Srgrimes } 42097631Swollman# endif /* DEBUG */ 4211590Srgrimes /* 4221590Srgrimes * link members to cycle header 4231590Srgrimes */ 4248874Srgrimes for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { 4251590Srgrimes memberp -> cycleno = cycle; 4261590Srgrimes memberp -> cyclehead = cyclenlp; 4271590Srgrimes } 4281590Srgrimes /* 4291590Srgrimes * count calls from outside the cycle 4301590Srgrimes * and those among cycle members 4311590Srgrimes */ 4321590Srgrimes for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { 4331590Srgrimes for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) { 4341590Srgrimes if ( arcp -> arc_parentp == memberp ) { 4351590Srgrimes continue; 4361590Srgrimes } 4371590Srgrimes if ( arcp -> arc_parentp -> cycleno == cycle ) { 4381590Srgrimes cyclenlp -> selfcalls += arcp -> arc_count; 4391590Srgrimes } else { 4401590Srgrimes cyclenlp -> npropcall += arcp -> arc_count; 4411590Srgrimes } 4421590Srgrimes } 4431590Srgrimes } 4441590Srgrimes } 4451590Srgrimes} 4461590Srgrimes 4471590Srgrimes /* 4481590Srgrimes * analyze cycles to determine breakup 4491590Srgrimes */ 4501590Srgrimescycleanalyze() 4511590Srgrimes{ 4521590Srgrimes arctype **cyclestack; 4531590Srgrimes arctype **stkp; 4541590Srgrimes arctype **arcpp; 4551590Srgrimes arctype **endlist; 4561590Srgrimes arctype *arcp; 4571590Srgrimes nltype *nlp; 4581590Srgrimes cltype *clp; 4591590Srgrimes bool ret; 4601590Srgrimes bool done; 4611590Srgrimes int size; 4621590Srgrimes int cycleno; 4631590Srgrimes 4641590Srgrimes /* 4651590Srgrimes * calculate the size of the cycle, and find nodes that 4661590Srgrimes * exit the cycle as they are desirable targets to cut 4671590Srgrimes * some of their parents 4681590Srgrimes */ 4691590Srgrimes for ( done = TRUE , cycleno = 1 ; cycleno <= ncycle ; cycleno++ ) { 4701590Srgrimes size = 0; 4711590Srgrimes for (nlp = cyclenl[ cycleno ] . cnext; nlp; nlp = nlp -> cnext) { 4721590Srgrimes size += 1; 4731590Srgrimes nlp -> parentcnt = 0; 4741590Srgrimes nlp -> flags &= ~HASCYCLEXIT; 4751590Srgrimes for ( arcp = nlp -> parents; arcp; arcp = arcp -> arc_parentlist ) { 4761590Srgrimes nlp -> parentcnt += 1; 4771590Srgrimes if ( arcp -> arc_parentp -> cycleno != cycleno ) 4781590Srgrimes nlp -> flags |= HASCYCLEXIT; 4791590Srgrimes } 4801590Srgrimes } 4811590Srgrimes if ( size <= cyclethreshold ) 4821590Srgrimes continue; 4831590Srgrimes done = FALSE; 4841590Srgrimes cyclestack = (arctype **) calloc( size + 1 , sizeof( arctype *) ); 4851590Srgrimes if ( cyclestack == 0 ) { 48627414Scharnier warnx("no room for %d bytes of cycle stack", 48727414Scharnier ( size + 1 ) * sizeof( arctype * ) ); 4881590Srgrimes return; 4891590Srgrimes } 4901590Srgrimes# ifdef DEBUG 4911590Srgrimes if ( debug & BREAKCYCLE ) { 4921590Srgrimes printf( "[cycleanalyze] starting cycle %d of %d, size %d\n" , 4931590Srgrimes cycleno , ncycle , size ); 4941590Srgrimes } 49597631Swollman# endif /* DEBUG */ 4961590Srgrimes for ( nlp = cyclenl[ cycleno ] . cnext ; nlp ; nlp = nlp -> cnext ) { 4971590Srgrimes stkp = &cyclestack[0]; 4981590Srgrimes nlp -> flags |= CYCLEHEAD; 4991590Srgrimes ret = descend ( nlp , cyclestack , stkp ); 5001590Srgrimes nlp -> flags &= ~CYCLEHEAD; 5011590Srgrimes if ( ret == FALSE ) 5021590Srgrimes break; 5031590Srgrimes } 5041590Srgrimes free( cyclestack ); 5051590Srgrimes if ( cyclecnt > 0 ) { 5061590Srgrimes compresslist(); 5071590Srgrimes for ( clp = cyclehead ; clp ; ) { 5081590Srgrimes endlist = &clp -> list[ clp -> size ]; 5091590Srgrimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 5101590Srgrimes (*arcpp) -> arc_cyclecnt--; 5111590Srgrimes cyclecnt--; 5121590Srgrimes clp = clp -> next; 5131590Srgrimes free( clp ); 5141590Srgrimes } 5151590Srgrimes cyclehead = 0; 5161590Srgrimes } 5171590Srgrimes } 5181590Srgrimes# ifdef DEBUG 5191590Srgrimes if ( debug & BREAKCYCLE ) { 5201590Srgrimes printf("%s visited %d, viable %d, newcycle %d, oldcycle %d\n", 5211590Srgrimes "[doarcs]" , visited , viable , newcycle , oldcycle); 5221590Srgrimes } 52397631Swollman# endif /* DEBUG */ 5241590Srgrimes return( done ); 5251590Srgrimes} 5261590Srgrimes 5271590Srgrimesdescend( node , stkstart , stkp ) 5281590Srgrimes nltype *node; 5291590Srgrimes arctype **stkstart; 5301590Srgrimes arctype **stkp; 5311590Srgrimes{ 5321590Srgrimes arctype *arcp; 5331590Srgrimes bool ret; 5341590Srgrimes 5351590Srgrimes for ( arcp = node -> children ; arcp ; arcp = arcp -> arc_childlist ) { 5361590Srgrimes# ifdef DEBUG 5371590Srgrimes visited++; 53897631Swollman# endif /* DEBUG */ 5391590Srgrimes if ( arcp -> arc_childp -> cycleno != node -> cycleno 5401590Srgrimes || ( arcp -> arc_childp -> flags & VISITED ) 5411590Srgrimes || ( arcp -> arc_flags & DEADARC ) ) 5421590Srgrimes continue; 5431590Srgrimes# ifdef DEBUG 5441590Srgrimes viable++; 54597631Swollman# endif /* DEBUG */ 5461590Srgrimes *stkp = arcp; 5471590Srgrimes if ( arcp -> arc_childp -> flags & CYCLEHEAD ) { 5481590Srgrimes if ( addcycle( stkstart , stkp ) == FALSE ) 5491590Srgrimes return( FALSE ); 5501590Srgrimes continue; 5511590Srgrimes } 5521590Srgrimes arcp -> arc_childp -> flags |= VISITED; 5531590Srgrimes ret = descend( arcp -> arc_childp , stkstart , stkp + 1 ); 5541590Srgrimes arcp -> arc_childp -> flags &= ~VISITED; 5551590Srgrimes if ( ret == FALSE ) 5561590Srgrimes return( FALSE ); 5571590Srgrimes } 5581590Srgrimes} 5591590Srgrimes 5601590Srgrimesaddcycle( stkstart , stkend ) 5611590Srgrimes arctype **stkstart; 5621590Srgrimes arctype **stkend; 5631590Srgrimes{ 5641590Srgrimes arctype **arcpp; 5651590Srgrimes arctype **stkloc; 5661590Srgrimes arctype **stkp; 5671590Srgrimes arctype **endlist; 5681590Srgrimes arctype *minarc; 5691590Srgrimes arctype *arcp; 5701590Srgrimes cltype *clp; 5711590Srgrimes int size; 5721590Srgrimes 5731590Srgrimes size = stkend - stkstart + 1; 5741590Srgrimes if ( size <= 1 ) 5751590Srgrimes return( TRUE ); 5761590Srgrimes for ( arcpp = stkstart , minarc = *arcpp ; arcpp <= stkend ; arcpp++ ) { 5771590Srgrimes if ( *arcpp > minarc ) 5781590Srgrimes continue; 5791590Srgrimes minarc = *arcpp; 5801590Srgrimes stkloc = arcpp; 5811590Srgrimes } 5821590Srgrimes for ( clp = cyclehead ; clp ; clp = clp -> next ) { 5831590Srgrimes if ( clp -> size != size ) 5841590Srgrimes continue; 5851590Srgrimes stkp = stkloc; 5861590Srgrimes endlist = &clp -> list[ size ]; 5871590Srgrimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) { 5881590Srgrimes if ( *stkp++ != *arcpp ) 5891590Srgrimes break; 5901590Srgrimes if ( stkp > stkend ) 5911590Srgrimes stkp = stkstart; 5921590Srgrimes } 5931590Srgrimes if ( arcpp == endlist ) { 5941590Srgrimes# ifdef DEBUG 5951590Srgrimes oldcycle++; 59697631Swollman# endif /* DEBUG */ 5971590Srgrimes return( TRUE ); 5981590Srgrimes } 5991590Srgrimes } 6001590Srgrimes clp = (cltype *) 6011590Srgrimes calloc( 1 , sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) ); 6021590Srgrimes if ( clp == 0 ) { 60327313Scharnier warnx("no room for %d bytes of subcycle storage", 60427313Scharnier sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) ); 6051590Srgrimes return( FALSE ); 6061590Srgrimes } 6071590Srgrimes stkp = stkloc; 6081590Srgrimes endlist = &clp -> list[ size ]; 6091590Srgrimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) { 6101590Srgrimes arcp = *arcpp = *stkp++; 6111590Srgrimes if ( stkp > stkend ) 6121590Srgrimes stkp = stkstart; 6131590Srgrimes arcp -> arc_cyclecnt++; 6141590Srgrimes if ( ( arcp -> arc_flags & ONLIST ) == 0 ) { 6151590Srgrimes arcp -> arc_flags |= ONLIST; 6161590Srgrimes arcp -> arc_next = archead; 6171590Srgrimes archead = arcp; 6181590Srgrimes } 6191590Srgrimes } 6201590Srgrimes clp -> size = size; 6211590Srgrimes clp -> next = cyclehead; 6221590Srgrimes cyclehead = clp; 6231590Srgrimes# ifdef DEBUG 6241590Srgrimes newcycle++; 6251590Srgrimes if ( debug & SUBCYCLELIST ) { 6261590Srgrimes printsubcycle( clp ); 6271590Srgrimes } 62897631Swollman# endif /* DEBUG */ 6291590Srgrimes cyclecnt++; 6301590Srgrimes if ( cyclecnt >= CYCLEMAX ) 6311590Srgrimes return( FALSE ); 6321590Srgrimes return( TRUE ); 6331590Srgrimes} 6341590Srgrimes 6351590Srgrimescompresslist() 6361590Srgrimes{ 6371590Srgrimes cltype *clp; 6381590Srgrimes cltype **prev; 6391590Srgrimes arctype **arcpp; 6401590Srgrimes arctype **endlist; 6411590Srgrimes arctype *arcp; 6421590Srgrimes arctype *maxarcp; 6431590Srgrimes arctype *maxexitarcp; 6441590Srgrimes arctype *maxwithparentarcp; 6451590Srgrimes arctype *maxnoparentarcp; 6461590Srgrimes int maxexitcnt; 6471590Srgrimes int maxwithparentcnt; 6481590Srgrimes int maxnoparentcnt; 64991012Sbde# ifdef DEBUG 65091012Sbde const char *type; 65197631Swollman# endif /* DEBUG */ 6521590Srgrimes 6531590Srgrimes maxexitcnt = 0; 6541590Srgrimes maxwithparentcnt = 0; 6551590Srgrimes maxnoparentcnt = 0; 6561590Srgrimes for ( endlist = &archead , arcp = archead ; arcp ; ) { 6571590Srgrimes if ( arcp -> arc_cyclecnt == 0 ) { 6581590Srgrimes arcp -> arc_flags &= ~ONLIST; 6591590Srgrimes *endlist = arcp -> arc_next; 6601590Srgrimes arcp -> arc_next = 0; 6611590Srgrimes arcp = *endlist; 6621590Srgrimes continue; 6631590Srgrimes } 6641590Srgrimes if ( arcp -> arc_childp -> flags & HASCYCLEXIT ) { 6651590Srgrimes if ( arcp -> arc_cyclecnt > maxexitcnt || 6661590Srgrimes ( arcp -> arc_cyclecnt == maxexitcnt && 6671590Srgrimes arcp -> arc_cyclecnt < maxexitarcp -> arc_count ) ) { 6681590Srgrimes maxexitcnt = arcp -> arc_cyclecnt; 6691590Srgrimes maxexitarcp = arcp; 6701590Srgrimes } 6711590Srgrimes } else if ( arcp -> arc_childp -> parentcnt > 1 ) { 6721590Srgrimes if ( arcp -> arc_cyclecnt > maxwithparentcnt || 6731590Srgrimes ( arcp -> arc_cyclecnt == maxwithparentcnt && 6741590Srgrimes arcp -> arc_cyclecnt < maxwithparentarcp -> arc_count ) ) { 6751590Srgrimes maxwithparentcnt = arcp -> arc_cyclecnt; 6761590Srgrimes maxwithparentarcp = arcp; 6771590Srgrimes } 6781590Srgrimes } else { 6791590Srgrimes if ( arcp -> arc_cyclecnt > maxnoparentcnt || 6801590Srgrimes ( arcp -> arc_cyclecnt == maxnoparentcnt && 6811590Srgrimes arcp -> arc_cyclecnt < maxnoparentarcp -> arc_count ) ) { 6821590Srgrimes maxnoparentcnt = arcp -> arc_cyclecnt; 6831590Srgrimes maxnoparentarcp = arcp; 6841590Srgrimes } 6851590Srgrimes } 6861590Srgrimes endlist = &arcp -> arc_next; 6871590Srgrimes arcp = arcp -> arc_next; 6881590Srgrimes } 6891590Srgrimes if ( maxexitcnt > 0 ) { 6901590Srgrimes /* 6911590Srgrimes * first choice is edge leading to node with out-of-cycle parent 6921590Srgrimes */ 6931590Srgrimes maxarcp = maxexitarcp; 6941590Srgrimes# ifdef DEBUG 6951590Srgrimes type = "exit"; 69697631Swollman# endif /* DEBUG */ 6971590Srgrimes } else if ( maxwithparentcnt > 0 ) { 6981590Srgrimes /* 6991590Srgrimes * second choice is edge leading to node with at least one 7001590Srgrimes * other in-cycle parent 7011590Srgrimes */ 7021590Srgrimes maxarcp = maxwithparentarcp; 7031590Srgrimes# ifdef DEBUG 7041590Srgrimes type = "internal"; 70597631Swollman# endif /* DEBUG */ 7061590Srgrimes } else { 7071590Srgrimes /* 7081590Srgrimes * last choice is edge leading to node with only this arc as 7091590Srgrimes * a parent (as it will now be orphaned) 7101590Srgrimes */ 7111590Srgrimes maxarcp = maxnoparentarcp; 7121590Srgrimes# ifdef DEBUG 7131590Srgrimes type = "orphan"; 71497631Swollman# endif /* DEBUG */ 7151590Srgrimes } 7161590Srgrimes maxarcp -> arc_flags |= DEADARC; 7171590Srgrimes maxarcp -> arc_childp -> parentcnt -= 1; 7181590Srgrimes maxarcp -> arc_childp -> npropcall -= maxarcp -> arc_count; 7191590Srgrimes# ifdef DEBUG 7201590Srgrimes if ( debug & BREAKCYCLE ) { 72191018Sbde printf( "%s delete %s arc: %s (%ld) -> %s from %u cycle(s)\n" , 7221590Srgrimes "[compresslist]" , type , maxarcp -> arc_parentp -> name , 7231590Srgrimes maxarcp -> arc_count , maxarcp -> arc_childp -> name , 7241590Srgrimes maxarcp -> arc_cyclecnt ); 7251590Srgrimes } 72697631Swollman# endif /* DEBUG */ 72791018Sbde printf( "\t%s to %s with %ld calls\n" , maxarcp -> arc_parentp -> name , 7281590Srgrimes maxarcp -> arc_childp -> name , maxarcp -> arc_count ); 7291590Srgrimes prev = &cyclehead; 7301590Srgrimes for ( clp = cyclehead ; clp ; ) { 7311590Srgrimes endlist = &clp -> list[ clp -> size ]; 7321590Srgrimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 7331590Srgrimes if ( (*arcpp) -> arc_flags & DEADARC ) 7341590Srgrimes break; 7351590Srgrimes if ( arcpp == endlist ) { 7361590Srgrimes prev = &clp -> next; 7371590Srgrimes clp = clp -> next; 7381590Srgrimes continue; 7391590Srgrimes } 7401590Srgrimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 7411590Srgrimes (*arcpp) -> arc_cyclecnt--; 7421590Srgrimes cyclecnt--; 7431590Srgrimes *prev = clp -> next; 7441590Srgrimes clp = clp -> next; 7451590Srgrimes free( clp ); 7461590Srgrimes } 7471590Srgrimes} 7481590Srgrimes 7491590Srgrimes#ifdef DEBUG 7501590Srgrimesprintsubcycle( clp ) 7511590Srgrimes cltype *clp; 7521590Srgrimes{ 7531590Srgrimes arctype **arcpp; 7541590Srgrimes arctype **endlist; 7551590Srgrimes 7561590Srgrimes arcpp = clp -> list; 7571590Srgrimes printf( "%s <cycle %d>\n" , (*arcpp) -> arc_parentp -> name , 7581590Srgrimes (*arcpp) -> arc_parentp -> cycleno ) ; 7591590Srgrimes for ( endlist = &clp -> list[ clp -> size ]; arcpp < endlist ; arcpp++ ) 76091018Sbde printf( "\t(%ld) -> %s\n" , (*arcpp) -> arc_count , 7611590Srgrimes (*arcpp) -> arc_childp -> name ) ; 7621590Srgrimes} 76397631Swollman#endif /* DEBUG */ 7641590Srgrimes 7651590Srgrimescycletime() 7661590Srgrimes{ 7671590Srgrimes int cycle; 7681590Srgrimes nltype *cyclenlp; 7691590Srgrimes nltype *childp; 7701590Srgrimes 7711590Srgrimes for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) { 7721590Srgrimes cyclenlp = &cyclenl[ cycle ]; 7731590Srgrimes for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) { 7741590Srgrimes if ( childp -> propfraction == 0.0 ) { 7751590Srgrimes /* 7761590Srgrimes * all members have the same propfraction except those 7771590Srgrimes * that were excluded with -E 7781590Srgrimes */ 7791590Srgrimes continue; 7801590Srgrimes } 7811590Srgrimes cyclenlp -> time += childp -> time; 7821590Srgrimes } 7831590Srgrimes cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time; 7841590Srgrimes } 7851590Srgrimes} 7861590Srgrimes 7871590Srgrimes /* 7881590Srgrimes * in one top to bottom pass over the topologically sorted namelist 7891590Srgrimes * propagate: 7901590Srgrimes * printflag as the union of parents' printflags 7911590Srgrimes * propfraction as the sum of fractional parents' propfractions 7921590Srgrimes * and while we're here, sum time for functions. 7931590Srgrimes */ 7941590Srgrimesdoflags() 7951590Srgrimes{ 7961590Srgrimes int index; 7971590Srgrimes nltype *childp; 7981590Srgrimes nltype *oldhead; 7991590Srgrimes 8001590Srgrimes oldhead = 0; 8011590Srgrimes for ( index = nname-1 ; index >= 0 ; index -= 1 ) { 8021590Srgrimes childp = topsortnlp[ index ]; 8031590Srgrimes /* 8041590Srgrimes * if we haven't done this function or cycle, 8051590Srgrimes * inherit things from parent. 8061590Srgrimes * this way, we are linear in the number of arcs 8071590Srgrimes * since we do all members of a cycle (and the cycle itself) 8081590Srgrimes * as we hit the first member of the cycle. 8091590Srgrimes */ 8101590Srgrimes if ( childp -> cyclehead != oldhead ) { 8111590Srgrimes oldhead = childp -> cyclehead; 8121590Srgrimes inheritflags( childp ); 8131590Srgrimes } 8141590Srgrimes# ifdef DEBUG 8151590Srgrimes if ( debug & PROPDEBUG ) { 8161590Srgrimes printf( "[doflags] " ); 8171590Srgrimes printname( childp ); 8181590Srgrimes printf( " inherits printflag %d and propfraction %f\n" , 8191590Srgrimes childp -> printflag , childp -> propfraction ); 8201590Srgrimes } 82197631Swollman# endif /* DEBUG */ 8221590Srgrimes if ( ! childp -> printflag ) { 8231590Srgrimes /* 8241590Srgrimes * printflag is off 8251590Srgrimes * it gets turned on by 8261590Srgrimes * being on -f list, 8271590Srgrimes * or there not being any -f list and not being on -e list. 8281590Srgrimes */ 8291590Srgrimes if ( onlist( flist , childp -> name ) 8301590Srgrimes || ( !fflag && !onlist( elist , childp -> name ) ) ) { 8311590Srgrimes childp -> printflag = TRUE; 8321590Srgrimes } 8331590Srgrimes } else { 8341590Srgrimes /* 8351590Srgrimes * this function has printing parents: 8361590Srgrimes * maybe someone wants to shut it up 8371590Srgrimes * by putting it on -e list. (but favor -f over -e) 8381590Srgrimes */ 8391590Srgrimes if ( ( !onlist( flist , childp -> name ) ) 8401590Srgrimes && onlist( elist , childp -> name ) ) { 8411590Srgrimes childp -> printflag = FALSE; 8421590Srgrimes } 8431590Srgrimes } 8441590Srgrimes if ( childp -> propfraction == 0.0 ) { 8451590Srgrimes /* 8461590Srgrimes * no parents to pass time to. 8471590Srgrimes * collect time from children if 8481590Srgrimes * its on -F list, 8491590Srgrimes * or there isn't any -F list and its not on -E list. 8501590Srgrimes */ 8511590Srgrimes if ( onlist( Flist , childp -> name ) 8521590Srgrimes || ( !Fflag && !onlist( Elist , childp -> name ) ) ) { 8531590Srgrimes childp -> propfraction = 1.0; 8541590Srgrimes } 8551590Srgrimes } else { 8561590Srgrimes /* 8578874Srgrimes * it has parents to pass time to, 8581590Srgrimes * but maybe someone wants to shut it up 8591590Srgrimes * by puttting it on -E list. (but favor -F over -E) 8601590Srgrimes */ 8611590Srgrimes if ( !onlist( Flist , childp -> name ) 8621590Srgrimes && onlist( Elist , childp -> name ) ) { 8631590Srgrimes childp -> propfraction = 0.0; 8641590Srgrimes } 8651590Srgrimes } 8661590Srgrimes childp -> propself = childp -> time * childp -> propfraction; 8671590Srgrimes printtime += childp -> propself; 8681590Srgrimes# ifdef DEBUG 8691590Srgrimes if ( debug & PROPDEBUG ) { 8701590Srgrimes printf( "[doflags] " ); 8711590Srgrimes printname( childp ); 8721590Srgrimes printf( " ends up with printflag %d and propfraction %f\n" , 8731590Srgrimes childp -> printflag , childp -> propfraction ); 8741590Srgrimes printf( "time %f propself %f printtime %f\n" , 8751590Srgrimes childp -> time , childp -> propself , printtime ); 8761590Srgrimes } 87797631Swollman# endif /* DEBUG */ 8781590Srgrimes } 8791590Srgrimes} 8801590Srgrimes 8811590Srgrimes /* 8821590Srgrimes * check if any parent of this child 8831590Srgrimes * (or outside parents of this cycle) 8848874Srgrimes * have their print flags on and set the 8851590Srgrimes * print flag of the child (cycle) appropriately. 8861590Srgrimes * similarly, deal with propagation fractions from parents. 8871590Srgrimes */ 8881590Srgrimesinheritflags( childp ) 8891590Srgrimes nltype *childp; 8901590Srgrimes{ 8911590Srgrimes nltype *headp; 8921590Srgrimes arctype *arcp; 8931590Srgrimes nltype *parentp; 8941590Srgrimes nltype *memp; 8951590Srgrimes 8961590Srgrimes headp = childp -> cyclehead; 8971590Srgrimes if ( childp == headp ) { 8981590Srgrimes /* 8991590Srgrimes * just a regular child, check its parents 9001590Srgrimes */ 9011590Srgrimes childp -> printflag = FALSE; 9021590Srgrimes childp -> propfraction = 0.0; 9031590Srgrimes for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) { 9041590Srgrimes parentp = arcp -> arc_parentp; 9051590Srgrimes if ( childp == parentp ) { 9061590Srgrimes continue; 9071590Srgrimes } 9081590Srgrimes childp -> printflag |= parentp -> printflag; 9091590Srgrimes /* 9101590Srgrimes * if the child was never actually called 9111590Srgrimes * (e.g. this arc is static (and all others are, too)) 9121590Srgrimes * no time propagates along this arc. 9131590Srgrimes */ 9141590Srgrimes if ( arcp -> arc_flags & DEADARC ) { 9151590Srgrimes continue; 9161590Srgrimes } 9171590Srgrimes if ( childp -> npropcall ) { 9181590Srgrimes childp -> propfraction += parentp -> propfraction 9191590Srgrimes * ( ( (double) arcp -> arc_count ) 9201590Srgrimes / ( (double) childp -> npropcall ) ); 9211590Srgrimes } 9221590Srgrimes } 9231590Srgrimes } else { 9241590Srgrimes /* 9258874Srgrimes * its a member of a cycle, look at all parents from 9261590Srgrimes * outside the cycle 9271590Srgrimes */ 9281590Srgrimes headp -> printflag = FALSE; 9291590Srgrimes headp -> propfraction = 0.0; 9301590Srgrimes for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) { 9311590Srgrimes for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) { 9321590Srgrimes if ( arcp -> arc_parentp -> cyclehead == headp ) { 9331590Srgrimes continue; 9341590Srgrimes } 9351590Srgrimes parentp = arcp -> arc_parentp; 9361590Srgrimes headp -> printflag |= parentp -> printflag; 9371590Srgrimes /* 9381590Srgrimes * if the cycle was never actually called 9391590Srgrimes * (e.g. this arc is static (and all others are, too)) 9401590Srgrimes * no time propagates along this arc. 9411590Srgrimes */ 9421590Srgrimes if ( arcp -> arc_flags & DEADARC ) { 9431590Srgrimes continue; 9441590Srgrimes } 9451590Srgrimes if ( headp -> npropcall ) { 9461590Srgrimes headp -> propfraction += parentp -> propfraction 9471590Srgrimes * ( ( (double) arcp -> arc_count ) 9481590Srgrimes / ( (double) headp -> npropcall ) ); 9491590Srgrimes } 9501590Srgrimes } 9511590Srgrimes } 9521590Srgrimes for ( memp = headp ; memp ; memp = memp -> cnext ) { 9531590Srgrimes memp -> printflag = headp -> printflag; 9541590Srgrimes memp -> propfraction = headp -> propfraction; 9551590Srgrimes } 9561590Srgrimes } 9571590Srgrimes} 958