14508Speter #ifndef lint 2*4561Speter static char *sccsid = "@(#)arcs.c 1.2 (Berkeley) 10/20/81"; 34508Speter #endif lint 44508Speter 5*4561Speter #include "gprof.h" 64508Speter 74508Speter topcmp( npp1 , npp2 ) 84508Speter nltype **npp1; 94508Speter nltype **npp2; 104508Speter { 114508Speter return (*npp1) -> toporder - (*npp2) -> toporder; 124508Speter } 134508Speter 144508Speter /* 154508Speter * sort by decreasing total time (time+childtime) 164508Speter * if times are equal, but one is a cycle header, 174508Speter * say that's first (e.g. less) 184508Speter */ 194508Speter int 204508Speter totalcmp( npp1 , npp2 ) 214508Speter nltype **npp1; 224508Speter nltype **npp2; 234508Speter { 244508Speter register nltype *np1 = *npp1; 254508Speter register nltype *np2 = *npp2; 264508Speter double diff; 274508Speter 284508Speter diff = ( np1 -> time + np1 -> childtime ) 294508Speter - ( np2 -> time + np2 -> childtime ); 304508Speter if ( diff < 0.0 ) 314508Speter return 1; 324508Speter if ( diff > 0.0 ) 334508Speter return -1; 344508Speter if ( np1 -> name == 0 && np1 -> cycleno != 0 ) 354508Speter return -1; 364508Speter if ( np2 -> name == 0 && np1 -> cycleno != 0 ) 374508Speter return 1; 384508Speter return 0; 394508Speter } 404508Speter 414508Speter doarcs() 424508Speter { 434508Speter nltype *parentp; 444508Speter arctype *arcp; 454508Speter nltype **topsortnlp; 464508Speter long index; 474508Speter nltype *childp; 484508Speter double share; 494508Speter 504508Speter /* 514508Speter * initialize various things: 524508Speter * zero out child times. 534508Speter * count self-recursive calls. 544508Speter * indicate that nothing is on cycles. 554508Speter */ 564508Speter for ( parentp = nl ; parentp < npe ; parentp++ ) { 574508Speter parentp -> childtime = 0.0; 584508Speter arcp = arclookup( parentp , parentp ); 594508Speter if ( arcp != 0 ) { 604508Speter parentp -> ncall -= arcp -> arc_count; 614508Speter parentp -> selfcalls = arcp -> arc_count; 624508Speter } else { 634508Speter parentp -> selfcalls = 0; 644508Speter } 654508Speter parentp -> toporder = 0; 664508Speter parentp -> cycleno = 0; 674508Speter parentp -> cyclehead = parentp; 684508Speter parentp -> cnext = 0; 694508Speter } 704508Speter /* 714508Speter * topologically order things 724508Speter * from each of the roots of the call graph 734508Speter */ 744508Speter for ( parentp = nl ; parentp < npe ; parentp++ ) { 754508Speter if ( parentp -> parents == 0 ) { 764508Speter dfn( parentp ); 774508Speter } 784508Speter } 794508Speter /* 804508Speter * link together nodes on the same cycle 814508Speter */ 824508Speter cyclelink(); 834508Speter /* 844508Speter * Sort the symbol table in reverse topological order 854508Speter */ 864508Speter topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) ); 874508Speter if ( topsortnlp == (nltype **) 0 ) { 884508Speter fprintf( stderr , "[doarcs] ran out of memory for topo sorting\n" ); 894508Speter } 904508Speter for ( index = 0 ; index < nname ; index += 1 ) { 914508Speter topsortnlp[ index ] = &nl[ index ]; 924508Speter } 934508Speter qsort( topsortnlp , nname , sizeof(nltype *) , topcmp ); 944508Speter # ifdef DEBUG 954508Speter if ( debug & DFNDEBUG ) { 964508Speter printf( "[doarcs] topological sort listing\n" ); 974508Speter for ( index = 0 ; index < nname ; index += 1 ) { 984508Speter printf( "[doarcs] " ); 994508Speter printf( "%d:" , topsortnlp[ index ] -> toporder ); 1004508Speter printname( topsortnlp[ index ] ); 1014508Speter printf( "\n" ); 1024508Speter } 1034508Speter } 1044508Speter # endif DEBUG 1054508Speter /* 1064508Speter * starting from the topological bottom, 1074508Speter * propogate children times 1084508Speter */ 1094508Speter for ( index = 0 ; index < nname ; index += 1 ) { 1104508Speter parentp = topsortnlp[ index ]; 1114508Speter for ( arcp = parentp->children ; arcp ; arcp = arcp->arc_childlist ) { 1124508Speter childp = arcp -> arc_childp; 1134508Speter # ifdef DEBUG 1144508Speter if ( debug & ARCDEBUG ) { 1154508Speter printf( "[doarcs] " ); 1164508Speter printname( parentp ); 1174508Speter printf( " calls " ); 1184508Speter printname( childp ); 1194508Speter printf( " %d (%d) times\n" , 1204508Speter arcp -> arc_count , childp -> ncall ); 1214508Speter } 1224508Speter # endif DEBUG 1234508Speter if ( arcp -> arc_count == 0 ) { 1244508Speter continue; 1254508Speter } 1264508Speter if ( childp -> ncall == 0 ) { 1274508Speter continue; 1284508Speter } 1294508Speter if ( childp == parentp ) { 1304508Speter continue; 1314508Speter } 1324508Speter if ( childp -> cyclehead != childp ) { 1334508Speter if ( parentp -> cycleno == childp -> cycleno ) { 1344508Speter continue; 1354508Speter } 1364508Speter # ifdef DEBUG 1374508Speter if ( debug & ARCDEBUG ) { 1384508Speter printf( "[doarcs]\t it's a call into cycle %d\n" , 1394508Speter childp -> cycleno ); 1404508Speter } 1414508Speter # endif DEBUG 1424508Speter if ( parentp -> toporder <= childp -> toporder ) { 1434508Speter fprintf( stderr , "[doarcs] toporder botches\n" ); 1444508Speter } 1454508Speter childp = childp -> cyclehead; 1464508Speter } else { 1474508Speter if ( parentp -> toporder <= childp -> toporder ) { 1484508Speter fprintf( stderr , "[doarcs] toporder botches\n" ); 1494508Speter continue; 1504508Speter } 1514508Speter } 1524508Speter /* 1534508Speter * distribute time for this arc 1544508Speter */ 1554508Speter arcp -> arc_time = childp -> time * 1564508Speter ( ( (double) arcp -> arc_count ) / 1574508Speter ( (double) childp -> ncall ) ); 1584508Speter arcp -> arc_childtime = childp -> childtime * 1594508Speter ( ( (double) arcp -> arc_count ) / 1604508Speter ( (double) childp -> ncall ) ); 1614508Speter share = arcp -> arc_time + arcp -> arc_childtime; 1624508Speter # ifdef DEBUG 1634508Speter if ( debug & ARCDEBUG ) { 1644508Speter printf( "[doarcs]\t " ); 1654508Speter printname( childp ); 1664508Speter printf( " time %8.2f + childtime %8.2f\n" , 1674508Speter childp -> time , childp -> childtime ); 1684508Speter printf( "[doarcs]\t this is %d arcs of the %d calls\n", 1694508Speter arcp -> arc_count , childp -> ncall ); 1704508Speter printf( "[doarcs]\t so this gives %8.2f+%8.2f to %s\n" , 1714508Speter arcp -> arc_time , arcp -> arc_childtime , 1724508Speter parentp -> name ); 1734508Speter } 1744508Speter # endif DEBUG 1754508Speter parentp -> childtime += share; 1764508Speter /* 1774508Speter * add this share to the cycle header, if any 1784508Speter */ 1794508Speter if ( parentp -> cyclehead != parentp ) { 1804508Speter # ifdef DEBUG 1814508Speter if ( debug & ARCDEBUG ) { 1824508Speter printf( "[doarcs]\t and to cycle %d\n" , 1834508Speter parentp -> cycleno ); 1844508Speter } 1854508Speter # endif DEBUG 1864508Speter parentp -> cyclehead -> childtime += share; 1874508Speter } 1884508Speter } 1894508Speter } 190*4561Speter printgprof(); 1914508Speter } 1924508Speter 1934508Speter cyclelink() 1944508Speter { 1954508Speter register nltype *nlp; 1964508Speter register nltype *parentp; 1974508Speter register nltype *childp; 1984508Speter register nltype *cyclenlp; 1994508Speter int cycle; 2004508Speter arctype *arcp; 2014508Speter long ncall; 2024508Speter double time; 2034508Speter long callsamong; 2044508Speter 2054508Speter /* 2064508Speter * Count the number of cycles, and initialze the cycle lists 2074508Speter */ 2084508Speter cyclemax = 0; 2094508Speter for ( nlp = nl ; nlp < npe ; nlp++ ) { 2104508Speter /* 2114508Speter * this is how you find unattached cycles 2124508Speter */ 2134508Speter if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) { 2144508Speter cyclemax += 1; 2154508Speter } 2164508Speter } 2174508Speter if ( cyclemax > ncycles ) { 2184508Speter fprintf( stderr , "prof: %d cycles in %d names exceeds %f%%\n" , 2194508Speter cyclemax , nname , CYCLEFRACTION * 100.0 ); 2204508Speter exit( 1 ); 2214508Speter } 2224508Speter /* 2234508Speter * now link cycles to true cycleheads, 2244508Speter * number them, accumulate the data for the cycle 2254508Speter */ 2264508Speter cycle = 0; 2274508Speter for ( nlp = nl ; nlp < npe ; nlp++ ) { 2284508Speter if ( nlp -> cyclehead != nlp || nlp -> cnext == 0 ) { 2294508Speter continue; 2304508Speter } 2314508Speter cycle += 1; 2324508Speter cyclenlp = &nl[nname+cycle]; 2334508Speter cyclenlp -> cycleno = cycle; 2344508Speter cyclenlp -> cyclehead = cyclenlp; 2354508Speter cyclenlp -> cnext = nlp; 2364508Speter # ifdef DEBUG 2374508Speter if ( debug & CYCLEDEBUG ) { 2384508Speter printf( "[cyclelink] " ); 2394508Speter printname( nlp ); 2404508Speter printf( " is the head of cycle %d\n" , cycle ); 2414508Speter } 2424508Speter # endif DEBUG 2434508Speter /* 2444508Speter * n-squaredly (in the size of the cycle) 2454508Speter * find all the call within the cycle 2464508Speter * (including self-recursive calls) 2474508Speter * and remove them, thus making the cycle into 2484508Speter * `node' with calls only from the outside. 2494508Speter * note: that this doesn't deal with 2504508Speter * self-recursive calls outside cycles (sigh). 2514508Speter */ 2524508Speter callsamong = 0; 2534508Speter for ( parentp = nlp ; parentp ; parentp = parentp -> cnext ) { 2544508Speter parentp -> cycleno = cycle; 2554508Speter parentp -> cyclehead = cyclenlp; 2564508Speter for ( childp = nlp ; childp ; childp = childp -> cnext ) { 2574508Speter if ( parentp == childp ) { 2584508Speter continue; 2594508Speter } 2604508Speter arcp = arclookup( parentp , childp ); 2614508Speter if ( arcp != 0 ) { 2624508Speter callsamong += arcp -> arc_count; 2634508Speter # ifdef DEBUG 2644508Speter if ( debug & CYCLEDEBUG ) { 2654508Speter printf("[cyclelink] %s calls sibling %s %d times\n", 2664508Speter parentp -> name , childp -> name , 2674508Speter arcp -> arc_count ); 2684508Speter } 2694508Speter # endif DEBUG 2704508Speter } 2714508Speter } 2724508Speter } 2734508Speter /* 2744508Speter * collect calls and time around the cycle, 2754508Speter * and save it in the cycle header. 2764508Speter */ 2774508Speter ncall = -callsamong; 2784508Speter time = 0.0; 2794508Speter for ( parentp = nlp ; parentp ; parentp = parentp -> cnext ) { 2804508Speter ncall += parentp -> ncall; 2814508Speter time += parentp -> time; 2824508Speter } 2834508Speter # ifdef DEBUG 2844508Speter if ( debug & CYCLEDEBUG ) { 2854508Speter printf( "[cyclelink] cycle %d %f ticks in %d (%d) calls\n" , 2864508Speter cycle , time , ncall , callsamong ); 2874508Speter } 2884508Speter # endif DEBUG 2894508Speter cyclenlp -> ncall = ncall; 2904508Speter cyclenlp -> selfcalls = callsamong; 2914508Speter cyclenlp -> time = time; 2924508Speter cyclenlp -> childtime = 0.0; 2934508Speter } 2944508Speter } 295