|
|
1.1 root 1: #ifndef lint
2: static char *sccsid = "@(#)arcs.c 1.14 (Berkeley) 7/26/83";
3: #endif lint
4:
5: #include "gprof.h"
6:
7: /*
8: * add (or just increment) an arc
9: */
10: addarc( parentp , childp , count )
11: nltype *parentp;
12: nltype *childp;
13: long count;
14: {
15: arctype *calloc();
16: arctype *arcp;
17:
18: # ifdef DEBUG
19: if ( debug & TALLYDEBUG ) {
20: printf( "[addarc] %d arcs from %s to %s\n" ,
21: count , parentp -> name , childp -> name );
22: }
23: # endif DEBUG
24: arcp = arclookup( parentp , childp );
25: if ( arcp != 0 ) {
26: /*
27: * a hit: just increment the count.
28: */
29: # ifdef DEBUG
30: if ( debug & TALLYDEBUG ) {
31: printf( "[tally] hit %d += %d\n" ,
32: arcp -> arc_count , count );
33: }
34: # endif DEBUG
35: arcp -> arc_count += count;
36: return;
37: }
38: arcp = calloc( 1 , sizeof *arcp );
39: arcp -> arc_parentp = parentp;
40: arcp -> arc_childp = childp;
41: arcp -> arc_count = count;
42: /*
43: * prepend this child to the children of this parent
44: */
45: arcp -> arc_childlist = parentp -> children;
46: parentp -> children = arcp;
47: /*
48: * prepend this parent to the parents of this child
49: */
50: arcp -> arc_parentlist = childp -> parents;
51: childp -> parents = arcp;
52: }
53:
54: /*
55: * the code below topologically sorts the graph (collapsing cycles),
56: * and propagates time bottom up and flags top down.
57: */
58:
59: /*
60: * the topologically sorted name list pointers
61: */
62: nltype **topsortnlp;
63:
64: topcmp( npp1 , npp2 )
65: nltype **npp1;
66: nltype **npp2;
67: {
68: return (*npp1) -> toporder - (*npp2) -> toporder;
69: }
70:
71: doarcs()
72: {
73: nltype *parentp;
74: arctype *arcp;
75: long index;
76:
77: /*
78: * initialize various things:
79: * zero out child times.
80: * count self-recursive calls.
81: * indicate that nothing is on cycles.
82: */
83: for ( parentp = nl ; parentp < npe ; parentp++ ) {
84: parentp -> childtime = 0.0;
85: arcp = arclookup( parentp , parentp );
86: if ( arcp != 0 ) {
87: parentp -> ncall -= arcp -> arc_count;
88: parentp -> selfcalls = arcp -> arc_count;
89: } else {
90: parentp -> selfcalls = 0;
91: }
92: parentp -> propfraction = 0.0;
93: parentp -> propself = 0.0;
94: parentp -> propchild = 0.0;
95: parentp -> printflag = FALSE;
96: parentp -> toporder = DFN_NAN;
97: parentp -> cycleno = 0;
98: parentp -> cyclehead = parentp;
99: parentp -> cnext = 0;
100: if ( cflag ) {
101: findcalls( parentp , parentp -> value , (parentp+1) -> value );
102: }
103: }
104: /*
105: * topologically order things
106: * if any node is unnumbered,
107: * number it and any of its descendents.
108: */
109: for ( parentp = nl ; parentp < npe ; parentp++ ) {
110: if ( parentp -> toporder == DFN_NAN ) {
111: dfn( parentp );
112: }
113: }
114: /*
115: * link together nodes on the same cycle
116: */
117: cyclelink();
118: /*
119: * Sort the symbol table in reverse topological order
120: */
121: topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) );
122: if ( topsortnlp == (nltype **) 0 ) {
123: fprintf( stderr , "[doarcs] ran out of memory for topo sorting\n" );
124: }
125: for ( index = 0 ; index < nname ; index += 1 ) {
126: topsortnlp[ index ] = &nl[ index ];
127: }
128: qsort( topsortnlp , nname , sizeof(nltype *) , topcmp );
129: # ifdef DEBUG
130: if ( debug & DFNDEBUG ) {
131: printf( "[doarcs] topological sort listing\n" );
132: for ( index = 0 ; index < nname ; index += 1 ) {
133: printf( "[doarcs] " );
134: printf( "%d:" , topsortnlp[ index ] -> toporder );
135: printname( topsortnlp[ index ] );
136: printf( "\n" );
137: }
138: }
139: # endif DEBUG
140: /*
141: * starting from the topological top,
142: * propagate print flags to children.
143: * also, calculate propagation fractions.
144: * this happens before time propagation
145: * since time propagation uses the fractions.
146: */
147: doflags();
148: /*
149: * starting from the topological bottom,
150: * propogate children times up to parents.
151: */
152: dotime();
153: printgprof();
154: }
155:
156: dotime()
157: {
158: int index;
159:
160: cycletime();
161: for ( index = 0 ; index < nname ; index += 1 ) {
162: timepropagate( topsortnlp[ index ] );
163: }
164: }
165:
166: timepropagate( parentp )
167: nltype *parentp;
168: {
169: arctype *arcp;
170: nltype *childp;
171: double share;
172: double propshare;
173:
174: if ( parentp -> propfraction == 0.0 ) {
175: return;
176: }
177: /*
178: * gather time from children of this parent.
179: */
180: for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
181: childp = arcp -> arc_childp;
182: if ( arcp -> arc_count == 0 ) {
183: continue;
184: }
185: if ( childp == parentp ) {
186: continue;
187: }
188: if ( childp -> propfraction == 0.0 ) {
189: continue;
190: }
191: if ( childp -> cyclehead != childp ) {
192: if ( parentp -> cycleno == childp -> cycleno ) {
193: continue;
194: }
195: if ( parentp -> toporder <= childp -> toporder ) {
196: fprintf( stderr , "[propagate] toporder botches\n" );
197: }
198: childp = childp -> cyclehead;
199: } else {
200: if ( parentp -> toporder <= childp -> toporder ) {
201: fprintf( stderr , "[propagate] toporder botches\n" );
202: continue;
203: }
204: }
205: if ( childp -> ncall == 0 ) {
206: continue;
207: }
208: /*
209: * distribute time for this arc
210: */
211: arcp -> arc_time = childp -> time
212: * ( ( (double) arcp -> arc_count ) /
213: ( (double) childp -> ncall ) );
214: arcp -> arc_childtime = childp -> childtime
215: * ( ( (double) arcp -> arc_count ) /
216: ( (double) childp -> ncall ) );
217: share = arcp -> arc_time + arcp -> arc_childtime;
218: parentp -> childtime += share;
219: /*
220: * ( 1 - propfraction ) gets lost along the way
221: */
222: propshare = parentp -> propfraction * share;
223: /*
224: * fix things for printing
225: */
226: parentp -> propchild += propshare;
227: arcp -> arc_time *= parentp -> propfraction;
228: arcp -> arc_childtime *= parentp -> propfraction;
229: /*
230: * add this share to the parent's cycle header, if any.
231: */
232: if ( parentp -> cyclehead != parentp ) {
233: parentp -> cyclehead -> childtime += share;
234: parentp -> cyclehead -> propchild += propshare;
235: }
236: # ifdef DEBUG
237: if ( debug & PROPDEBUG ) {
238: printf( "[dotime] child \t" );
239: printname( childp );
240: printf( " with %f %f %d/%d\n" ,
241: childp -> time , childp -> childtime ,
242: arcp -> arc_count , childp -> ncall );
243: printf( "[dotime] parent\t" );
244: printname( parentp );
245: printf( "\n[dotime] share %f\n" , share );
246: }
247: # endif DEBUG
248: }
249: }
250:
251: cyclelink()
252: {
253: register nltype *nlp;
254: register nltype *cyclenlp;
255: int cycle;
256: nltype *memberp;
257: arctype *arcp;
258:
259: /*
260: * Count the number of cycles, and initialze the cycle lists
261: */
262: ncycle = 0;
263: for ( nlp = nl ; nlp < npe ; nlp++ ) {
264: /*
265: * this is how you find unattached cycles
266: */
267: if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) {
268: ncycle += 1;
269: }
270: }
271: /*
272: * cyclenl is indexed by cycle number:
273: * i.e. it is origin 1, not origin 0.
274: */
275: cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) );
276: if ( cyclenl == 0 ) {
277: fprintf( stderr , "%s: No room for %d bytes of cycle headers\n" ,
278: whoami , ( ncycle + 1 ) * sizeof( nltype ) );
279: done();
280: }
281: /*
282: * now link cycles to true cycleheads,
283: * number them, accumulate the data for the cycle
284: */
285: cycle = 0;
286: for ( nlp = nl ; nlp < npe ; nlp++ ) {
287: if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) {
288: continue;
289: }
290: cycle += 1;
291: cyclenlp = &cyclenl[cycle];
292: cyclenlp -> name = 0; /* the name */
293: cyclenlp -> value = 0; /* the pc entry point */
294: cyclenlp -> time = 0.0; /* ticks in this routine */
295: cyclenlp -> childtime = 0.0; /* cumulative ticks in children */
296: cyclenlp -> ncall = 0; /* how many times called */
297: cyclenlp -> selfcalls = 0; /* how many calls to self */
298: cyclenlp -> propfraction = 0.0; /* what % of time propagates */
299: cyclenlp -> propself = 0.0; /* how much self time propagates */
300: cyclenlp -> propchild = 0.0; /* how much child time propagates */
301: cyclenlp -> printflag = TRUE; /* should this be printed? */
302: cyclenlp -> index = 0; /* index in the graph list */
303: cyclenlp -> toporder = DFN_NAN; /* graph call chain top-sort order */
304: cyclenlp -> cycleno = cycle; /* internal number of cycle on */
305: cyclenlp -> cyclehead = cyclenlp; /* pointer to head of cycle */
306: cyclenlp -> cnext = nlp; /* pointer to next member of cycle */
307: cyclenlp -> parents = 0; /* list of caller arcs */
308: cyclenlp -> children = 0; /* list of callee arcs */
309: # ifdef DEBUG
310: if ( debug & CYCLEDEBUG ) {
311: printf( "[cyclelink] " );
312: printname( nlp );
313: printf( " is the head of cycle %d\n" , cycle );
314: }
315: # endif DEBUG
316: /*
317: * link members to cycle header
318: */
319: for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) {
320: memberp -> cycleno = cycle;
321: memberp -> cyclehead = cyclenlp;
322: }
323: /*
324: * count calls from outside the cycle
325: * and those among cycle members
326: */
327: for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) {
328: for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) {
329: if ( arcp -> arc_parentp == memberp ) {
330: continue;
331: }
332: if ( arcp -> arc_parentp -> cycleno == cycle ) {
333: cyclenlp -> selfcalls += arcp -> arc_count;
334: } else {
335: cyclenlp -> ncall += arcp -> arc_count;
336: }
337: }
338: }
339: }
340: }
341:
342: cycletime()
343: {
344: int cycle;
345: nltype *cyclenlp;
346: nltype *childp;
347:
348: for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) {
349: cyclenlp = &cyclenl[ cycle ];
350: for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) {
351: if ( childp -> propfraction == 0.0 ) {
352: /*
353: * all members have the same propfraction except those
354: * that were excluded with -E
355: */
356: continue;
357: }
358: cyclenlp -> time += childp -> time;
359: }
360: cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time;
361: }
362: }
363:
364: /*
365: * in one top to bottom pass over the topologically sorted namelist
366: * propagate:
367: * printflag as the union of parents' printflags
368: * propfraction as the sum of fractional parents' propfractions
369: * and while we're here, sum time for functions.
370: */
371: doflags()
372: {
373: int index;
374: nltype *childp;
375: nltype *oldhead;
376:
377: oldhead = 0;
378: for ( index = nname-1 ; index >= 0 ; index -= 1 ) {
379: childp = topsortnlp[ index ];
380: /*
381: * if we haven't done this function or cycle,
382: * inherit things from parent.
383: * this way, we are linear in the number of arcs
384: * since we do all members of a cycle (and the cycle itself)
385: * as we hit the first member of the cycle.
386: */
387: if ( childp -> cyclehead != oldhead ) {
388: oldhead = childp -> cyclehead;
389: inheritflags( childp );
390: }
391: # ifdef DEBUG
392: if ( debug & PROPDEBUG ) {
393: printf( "[doflags] " );
394: printname( childp );
395: printf( " inherits printflag %d and propfraction %f\n" ,
396: childp -> printflag , childp -> propfraction );
397: }
398: # endif DEBUG
399: if ( ! childp -> printflag ) {
400: /*
401: * printflag is off
402: * it gets turned on by
403: * being on -f list,
404: * or there not being any -f list and not being on -e list.
405: */
406: if ( onlist( flist , childp -> name )
407: || ( !fflag && !onlist( elist , childp -> name ) ) ) {
408: childp -> printflag = TRUE;
409: }
410: } else {
411: /*
412: * this function has printing parents:
413: * maybe someone wants to shut it up
414: * by putting it on -e list. (but favor -f over -e)
415: */
416: if ( ( !onlist( flist , childp -> name ) )
417: && onlist( elist , childp -> name ) ) {
418: childp -> printflag = FALSE;
419: }
420: }
421: if ( childp -> propfraction == 0.0 ) {
422: /*
423: * no parents to pass time to.
424: * collect time from children if
425: * its on -F list,
426: * or there isn't any -F list and its not on -E list.
427: */
428: if ( onlist( Flist , childp -> name )
429: || ( !Fflag && !onlist( Elist , childp -> name ) ) ) {
430: childp -> propfraction = 1.0;
431: }
432: } else {
433: /*
434: * it has parents to pass time to,
435: * but maybe someone wants to shut it up
436: * by puttting it on -E list. (but favor -F over -E)
437: */
438: if ( !onlist( Flist , childp -> name )
439: && onlist( Elist , childp -> name ) ) {
440: childp -> propfraction = 0.0;
441: }
442: }
443: childp -> propself = childp -> time * childp -> propfraction;
444: printtime += childp -> propself;
445: # ifdef DEBUG
446: if ( debug & PROPDEBUG ) {
447: printf( "[doflags] " );
448: printname( childp );
449: printf( " ends up with printflag %d and propfraction %f\n" ,
450: childp -> printflag , childp -> propfraction );
451: printf( "time %f propself %f printtime %f\n" ,
452: childp -> time , childp -> propself , printtime );
453: }
454: # endif DEBUG
455: }
456: }
457:
458: /*
459: * check if any parent of this child
460: * (or outside parents of this cycle)
461: * have their print flags on and set the
462: * print flag of the child (cycle) appropriately.
463: * similarly, deal with propagation fractions from parents.
464: */
465: inheritflags( childp )
466: nltype *childp;
467: {
468: nltype *headp;
469: arctype *arcp;
470: nltype *parentp;
471: nltype *memp;
472:
473: headp = childp -> cyclehead;
474: if ( childp == headp ) {
475: /*
476: * just a regular child, check its parents
477: */
478: childp -> printflag = FALSE;
479: childp -> propfraction = 0.0;
480: for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) {
481: parentp = arcp -> arc_parentp;
482: if ( childp == parentp ) {
483: continue;
484: }
485: childp -> printflag |= parentp -> printflag;
486: /*
487: * if the child was never actually called
488: * (e.g. this arc is static (and all others are, too))
489: * no time propagates along this arc.
490: */
491: if ( childp -> ncall ) {
492: childp -> propfraction += parentp -> propfraction
493: * ( ( (double) arcp -> arc_count )
494: / ( (double) childp -> ncall ) );
495: }
496: }
497: } else {
498: /*
499: * its a member of a cycle, look at all parents from
500: * outside the cycle
501: */
502: headp -> printflag = FALSE;
503: headp -> propfraction = 0.0;
504: for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) {
505: for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) {
506: if ( arcp -> arc_parentp -> cyclehead == headp ) {
507: continue;
508: }
509: parentp = arcp -> arc_parentp;
510: headp -> printflag |= parentp -> printflag;
511: /*
512: * if the cycle was never actually called
513: * (e.g. this arc is static (and all others are, too))
514: * no time propagates along this arc.
515: */
516: if ( headp -> ncall ) {
517: headp -> propfraction += parentp -> propfraction
518: * ( ( (double) arcp -> arc_count )
519: / ( (double) headp -> ncall ) );
520: }
521: }
522: }
523: for ( memp = headp ; memp ; memp = memp -> cnext ) {
524: memp -> printflag = headp -> printflag;
525: memp -> propfraction = headp -> propfraction;
526: }
527: }
528: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.