Annotation of src/usr.bin/gprof/arcs.c, Revision 1.6
1.6 ! danh 1: /* $OpenBSD: arcs.c,v 1.5 2001/11/19 19:02:14 mpech Exp $ */
1.1 deraadt 2: /* $NetBSD: arcs.c,v 1.6 1995/04/19 07:15:52 cgd Exp $ */
3:
4: /*
5: * Copyright (c) 1983, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
38: #if 0
39: static char sccsid[] = "@(#)arcs.c 8.1 (Berkeley) 6/6/93";
40: #else
1.6 ! danh 41: static char rcsid[] = "$OpenBSD: arcs.c,v 1.5 2001/11/19 19:02:14 mpech Exp $";
1.1 deraadt 42: #endif
43: #endif /* not lint */
44:
45: #include "gprof.h"
46:
47: #ifdef DEBUG
48: int visited;
49: int viable;
50: int newcycle;
51: int oldcycle;
1.4 heko 52: #endif /* DEBUG */
1.1 deraadt 53:
54: /*
55: * add (or just increment) an arc
56: */
1.3 mickey 57: void
1.1 deraadt 58: addarc( parentp , childp , count )
59: nltype *parentp;
60: nltype *childp;
61: long count;
62: {
63: arctype *arcp;
64:
65: # ifdef DEBUG
66: if ( debug & TALLYDEBUG ) {
67: printf( "[addarc] %d arcs from %s to %s\n" ,
68: count , parentp -> name , childp -> name );
69: }
1.6 ! danh 70: # endif /* DEBUG */
1.1 deraadt 71: arcp = arclookup( parentp , childp );
72: if ( arcp != 0 ) {
73: /*
74: * a hit: just increment the count.
75: */
76: # ifdef DEBUG
77: if ( debug & TALLYDEBUG ) {
78: printf( "[tally] hit %d += %d\n" ,
79: arcp -> arc_count , count );
80: }
1.6 ! danh 81: # endif /* DEBUG */
1.1 deraadt 82: arcp -> arc_count += count;
83: return;
84: }
85: arcp = (arctype *)calloc( 1 , sizeof *arcp );
86: arcp -> arc_parentp = parentp;
87: arcp -> arc_childp = childp;
88: arcp -> arc_count = count;
89: /*
90: * prepend this child to the children of this parent
91: */
92: arcp -> arc_childlist = parentp -> children;
93: parentp -> children = arcp;
94: /*
95: * prepend this parent to the parents of this child
96: */
97: arcp -> arc_parentlist = childp -> parents;
98: childp -> parents = arcp;
99: }
100:
101: /*
102: * the code below topologically sorts the graph (collapsing cycles),
103: * and propagates time bottom up and flags top down.
104: */
105:
106: /*
107: * the topologically sorted name list pointers
108: */
109: nltype **topsortnlp;
110:
1.3 mickey 111: int
1.1 deraadt 112: topcmp( npp1 , npp2 )
113: nltype **npp1;
114: nltype **npp2;
115: {
116: return (*npp1) -> toporder - (*npp2) -> toporder;
117: }
118:
119: nltype **
120: doarcs()
121: {
122: nltype *parentp, **timesortnlp;
123: arctype *arcp;
124: long index;
125: long pass;
126:
127: /*
128: * initialize various things:
129: * zero out child times.
130: * count self-recursive calls.
131: * indicate that nothing is on cycles.
132: */
133: for ( parentp = nl ; parentp < npe ; parentp++ ) {
134: parentp -> childtime = 0.0;
135: arcp = arclookup( parentp , parentp );
136: if ( arcp != 0 ) {
137: parentp -> ncall -= arcp -> arc_count;
138: parentp -> selfcalls = arcp -> arc_count;
139: } else {
140: parentp -> selfcalls = 0;
141: }
142: parentp -> npropcall = parentp -> ncall;
143: parentp -> propfraction = 0.0;
144: parentp -> propself = 0.0;
145: parentp -> propchild = 0.0;
146: parentp -> printflag = FALSE;
147: parentp -> toporder = DFN_NAN;
148: parentp -> cycleno = 0;
149: parentp -> cyclehead = parentp;
150: parentp -> cnext = 0;
151: if ( cflag ) {
152: findcall( parentp , parentp -> value , (parentp+1) -> value );
153: }
154: }
155: for ( pass = 1 ; ; pass++ ) {
156: /*
157: * topologically order things
158: * if any node is unnumbered,
159: * number it and any of its descendents.
160: */
161: for ( dfn_init() , parentp = nl ; parentp < npe ; parentp++ ) {
162: if ( parentp -> toporder == DFN_NAN ) {
163: dfn( parentp );
164: }
165: }
166: /*
167: * link together nodes on the same cycle
168: */
169: cyclelink();
170: /*
171: * if no cycles to break up, proceed
172: */
173: if ( ! Cflag )
174: break;
175: /*
176: * analyze cycles to determine breakup
177: */
178: # ifdef DEBUG
179: if ( debug & BREAKCYCLE ) {
180: printf("[doarcs] pass %d, cycle(s) %d\n" , pass , ncycle );
181: }
1.6 ! danh 182: # endif /* DEBUG */
1.1 deraadt 183: if ( pass == 1 ) {
184: printf( "\n\n%s %s\n%s %d:\n" ,
185: "The following arcs were deleted" ,
186: "from the propagation calculation" ,
187: "to reduce the maximum cycle size to", cyclethreshold );
188: }
189: if ( cycleanalyze() )
190: break;
191: free ( cyclenl );
192: ncycle = 0;
193: for ( parentp = nl ; parentp < npe ; parentp++ ) {
194: parentp -> toporder = DFN_NAN;
195: parentp -> cycleno = 0;
196: parentp -> cyclehead = parentp;
197: parentp -> cnext = 0;
198: }
199: }
200: if ( pass > 1 ) {
201: printf( "\f\n" );
202: } else {
203: printf( "\tNone\n\n" );
204: }
205: /*
206: * Sort the symbol table in reverse topological order
207: */
208: topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) );
1.3 mickey 209: if ( topsortnlp == (nltype **) 0 )
210: warnx("[doarcs] ran out of memory for topo sorting");
1.1 deraadt 211: for ( index = 0 ; index < nname ; index += 1 ) {
212: topsortnlp[ index ] = &nl[ index ];
213: }
214: qsort( topsortnlp , nname , sizeof(nltype *) , topcmp );
215: # ifdef DEBUG
216: if ( debug & DFNDEBUG ) {
217: printf( "[doarcs] topological sort listing\n" );
218: for ( index = 0 ; index < nname ; index += 1 ) {
219: printf( "[doarcs] " );
220: printf( "%d:" , topsortnlp[ index ] -> toporder );
221: printname( topsortnlp[ index ] );
222: printf( "\n" );
223: }
224: }
1.6 ! danh 225: # endif /* DEBUG */
1.1 deraadt 226: /*
227: * starting from the topological top,
228: * propagate print flags to children.
229: * also, calculate propagation fractions.
230: * this happens before time propagation
231: * since time propagation uses the fractions.
232: */
233: doflags();
234: /*
1.3 mickey 235: * starting from the topological bottom,
1.1 deraadt 236: * propogate children times up to parents.
237: */
238: dotime();
239: /*
240: * Now, sort by propself + propchild.
241: * sorting both the regular function names
242: * and cycle headers.
243: */
244: timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
1.3 mickey 245: if ( timesortnlp == (nltype **) 0 )
246: warnx("ran out of memory for sorting");
1.1 deraadt 247: for ( index = 0 ; index < nname ; index++ ) {
248: timesortnlp[index] = &nl[index];
249: }
250: for ( index = 1 ; index <= ncycle ; index++ ) {
251: timesortnlp[nname+index-1] = &cyclenl[index];
252: }
253: qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp );
254: for ( index = 0 ; index < nname + ncycle ; index++ ) {
255: timesortnlp[ index ] -> index = index + 1;
256: }
257: return( timesortnlp );
258: }
259:
1.3 mickey 260: void
1.1 deraadt 261: dotime()
262: {
263: int index;
264:
265: cycletime();
266: for ( index = 0 ; index < nname ; index += 1 ) {
267: timepropagate( topsortnlp[ index ] );
268: }
269: }
270:
1.3 mickey 271: void
1.1 deraadt 272: timepropagate( parentp )
273: nltype *parentp;
274: {
275: arctype *arcp;
276: nltype *childp;
277: double share;
278: double propshare;
279:
280: if ( parentp -> propfraction == 0.0 ) {
281: return;
282: }
283: /*
284: * gather time from children of this parent.
285: */
286: for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
287: childp = arcp -> arc_childp;
288: if ( arcp -> arc_flags & DEADARC ) {
289: continue;
290: }
291: if ( arcp -> arc_count == 0 ) {
292: continue;
293: }
294: if ( childp == parentp ) {
295: continue;
296: }
297: if ( childp -> propfraction == 0.0 ) {
298: continue;
299: }
300: if ( childp -> cyclehead != childp ) {
301: if ( parentp -> cycleno == childp -> cycleno ) {
302: continue;
303: }
1.3 mickey 304: if ( parentp -> toporder <= childp -> toporder )
305: warnx("[propagate] toporder botches");
1.1 deraadt 306: childp = childp -> cyclehead;
307: } else {
308: if ( parentp -> toporder <= childp -> toporder ) {
1.3 mickey 309: warnx("[propagate] toporder botches");
1.1 deraadt 310: continue;
311: }
312: }
313: if ( childp -> npropcall == 0 ) {
314: continue;
315: }
316: /*
317: * distribute time for this arc
318: */
319: arcp -> arc_time = childp -> time
320: * ( ( (double) arcp -> arc_count ) /
321: ( (double) childp -> npropcall ) );
322: arcp -> arc_childtime = childp -> childtime
323: * ( ( (double) arcp -> arc_count ) /
324: ( (double) childp -> npropcall ) );
325: share = arcp -> arc_time + arcp -> arc_childtime;
326: parentp -> childtime += share;
327: /*
328: * ( 1 - propfraction ) gets lost along the way
329: */
330: propshare = parentp -> propfraction * share;
331: /*
332: * fix things for printing
333: */
334: parentp -> propchild += propshare;
335: arcp -> arc_time *= parentp -> propfraction;
336: arcp -> arc_childtime *= parentp -> propfraction;
337: /*
338: * add this share to the parent's cycle header, if any.
339: */
340: if ( parentp -> cyclehead != parentp ) {
341: parentp -> cyclehead -> childtime += share;
342: parentp -> cyclehead -> propchild += propshare;
343: }
344: # ifdef DEBUG
345: if ( debug & PROPDEBUG ) {
346: printf( "[dotime] child \t" );
347: printname( childp );
348: printf( " with %f %f %d/%d\n" ,
349: childp -> time , childp -> childtime ,
350: arcp -> arc_count , childp -> npropcall );
351: printf( "[dotime] parent\t" );
352: printname( parentp );
353: printf( "\n[dotime] share %f\n" , share );
354: }
1.6 ! danh 355: # endif /* DEBUG */
1.1 deraadt 356: }
357: }
358:
1.3 mickey 359: void
1.1 deraadt 360: cyclelink()
361: {
1.5 mpech 362: nltype *nlp;
363: nltype *cyclenlp;
1.1 deraadt 364: int cycle;
365: nltype *memberp;
366: arctype *arcp;
367:
368: /*
369: * Count the number of cycles, and initialze the cycle lists
370: */
371: ncycle = 0;
372: for ( nlp = nl ; nlp < npe ; nlp++ ) {
373: /*
374: * this is how you find unattached cycles
375: */
376: if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) {
377: ncycle += 1;
378: }
379: }
380: /*
381: * cyclenl is indexed by cycle number:
382: * i.e. it is origin 1, not origin 0.
383: */
384: cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) );
1.3 mickey 385: if ( cyclenl == 0 )
386: errx(0, "No room for %d bytes of cycle headers",
387: (ncycle + 1) * sizeof(nltype));
1.1 deraadt 388: /*
389: * now link cycles to true cycleheads,
390: * number them, accumulate the data for the cycle
391: */
392: cycle = 0;
393: for ( nlp = nl ; nlp < npe ; nlp++ ) {
394: if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) {
395: continue;
396: }
397: cycle += 1;
398: cyclenlp = &cyclenl[cycle];
399: cyclenlp -> name = 0; /* the name */
400: cyclenlp -> value = 0; /* the pc entry point */
401: cyclenlp -> time = 0.0; /* ticks in this routine */
402: cyclenlp -> childtime = 0.0; /* cumulative ticks in children */
403: cyclenlp -> ncall = 0; /* how many times called */
404: cyclenlp -> selfcalls = 0; /* how many calls to self */
405: cyclenlp -> propfraction = 0.0; /* what % of time propagates */
406: cyclenlp -> propself = 0.0; /* how much self time propagates */
407: cyclenlp -> propchild = 0.0; /* how much child time propagates */
408: cyclenlp -> printflag = TRUE; /* should this be printed? */
409: cyclenlp -> index = 0; /* index in the graph list */
410: cyclenlp -> toporder = DFN_NAN; /* graph call chain top-sort order */
411: cyclenlp -> cycleno = cycle; /* internal number of cycle on */
412: cyclenlp -> cyclehead = cyclenlp; /* pointer to head of cycle */
413: cyclenlp -> cnext = nlp; /* pointer to next member of cycle */
414: cyclenlp -> parents = 0; /* list of caller arcs */
415: cyclenlp -> children = 0; /* list of callee arcs */
416: # ifdef DEBUG
417: if ( debug & CYCLEDEBUG ) {
418: printf( "[cyclelink] " );
419: printname( nlp );
420: printf( " is the head of cycle %d\n" , cycle );
421: }
1.6 ! danh 422: # endif /* DEBUG */
1.1 deraadt 423: /*
424: * link members to cycle header
425: */
1.3 mickey 426: for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) {
1.1 deraadt 427: memberp -> cycleno = cycle;
428: memberp -> cyclehead = cyclenlp;
429: }
430: /*
431: * count calls from outside the cycle
432: * and those among cycle members
433: */
434: for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) {
435: for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) {
436: if ( arcp -> arc_parentp == memberp ) {
437: continue;
438: }
439: if ( arcp -> arc_parentp -> cycleno == cycle ) {
440: cyclenlp -> selfcalls += arcp -> arc_count;
441: } else {
442: cyclenlp -> npropcall += arcp -> arc_count;
443: }
444: }
445: }
446: }
447: }
448:
449: /*
450: * analyze cycles to determine breakup
451: */
1.3 mickey 452: int
1.1 deraadt 453: cycleanalyze()
454: {
455: arctype **cyclestack;
456: arctype **stkp;
457: arctype **arcpp;
458: arctype **endlist;
459: arctype *arcp;
460: nltype *nlp;
461: cltype *clp;
462: bool ret;
463: bool done;
464: int size;
465: int cycleno;
466:
467: /*
468: * calculate the size of the cycle, and find nodes that
469: * exit the cycle as they are desirable targets to cut
470: * some of their parents
471: */
472: for ( done = TRUE , cycleno = 1 ; cycleno <= ncycle ; cycleno++ ) {
473: size = 0;
474: for (nlp = cyclenl[ cycleno ] . cnext; nlp; nlp = nlp -> cnext) {
475: size += 1;
476: nlp -> parentcnt = 0;
477: nlp -> flags &= ~HASCYCLEXIT;
478: for ( arcp = nlp -> parents; arcp; arcp = arcp -> arc_parentlist ) {
479: nlp -> parentcnt += 1;
480: if ( arcp -> arc_parentp -> cycleno != cycleno )
481: nlp -> flags |= HASCYCLEXIT;
482: }
483: }
484: if ( size <= cyclethreshold )
485: continue;
486: done = FALSE;
487: cyclestack = (arctype **) calloc( size + 1 , sizeof( arctype *) );
488: if ( cyclestack == 0 ) {
1.3 mickey 489: warnx("No room for %d bytes of cycle stack" ,
490: (size + 1) * sizeof(arctype *));
491: return (done);
1.1 deraadt 492: }
493: # ifdef DEBUG
494: if ( debug & BREAKCYCLE ) {
495: printf( "[cycleanalyze] starting cycle %d of %d, size %d\n" ,
496: cycleno , ncycle , size );
497: }
1.6 ! danh 498: # endif /* DEBUG */
1.1 deraadt 499: for ( nlp = cyclenl[ cycleno ] . cnext ; nlp ; nlp = nlp -> cnext ) {
500: stkp = &cyclestack[0];
501: nlp -> flags |= CYCLEHEAD;
502: ret = descend ( nlp , cyclestack , stkp );
503: nlp -> flags &= ~CYCLEHEAD;
504: if ( ret == FALSE )
505: break;
506: }
507: free( cyclestack );
508: if ( cyclecnt > 0 ) {
509: compresslist();
510: for ( clp = cyclehead ; clp ; ) {
511: endlist = &clp -> list[ clp -> size ];
512: for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ )
513: (*arcpp) -> arc_cyclecnt--;
514: cyclecnt--;
515: clp = clp -> next;
516: free( clp );
517: }
518: cyclehead = 0;
519: }
520: }
521: # ifdef DEBUG
522: if ( debug & BREAKCYCLE ) {
523: printf("%s visited %d, viable %d, newcycle %d, oldcycle %d\n",
524: "[doarcs]" , visited , viable , newcycle , oldcycle);
525: }
1.6 ! danh 526: # endif /* DEBUG */
1.3 mickey 527: return (done);
1.1 deraadt 528: }
529:
1.3 mickey 530: int
1.1 deraadt 531: descend( node , stkstart , stkp )
532: nltype *node;
533: arctype **stkstart;
534: arctype **stkp;
535: {
536: arctype *arcp;
537: bool ret;
538:
539: for ( arcp = node -> children ; arcp ; arcp = arcp -> arc_childlist ) {
540: # ifdef DEBUG
541: visited++;
1.6 ! danh 542: # endif /* DEBUG */
1.1 deraadt 543: if ( arcp -> arc_childp -> cycleno != node -> cycleno
544: || ( arcp -> arc_childp -> flags & VISITED )
545: || ( arcp -> arc_flags & DEADARC ) )
546: continue;
547: # ifdef DEBUG
548: viable++;
1.6 ! danh 549: # endif /* DEBUG */
1.1 deraadt 550: *stkp = arcp;
551: if ( arcp -> arc_childp -> flags & CYCLEHEAD ) {
552: if ( addcycle( stkstart , stkp ) == FALSE )
553: return( FALSE );
554: continue;
555: }
556: arcp -> arc_childp -> flags |= VISITED;
557: ret = descend( arcp -> arc_childp , stkstart , stkp + 1 );
558: arcp -> arc_childp -> flags &= ~VISITED;
559: if ( ret == FALSE )
560: return( FALSE );
561: }
1.3 mickey 562: return (TRUE);
1.1 deraadt 563: }
564:
1.3 mickey 565: int
1.1 deraadt 566: addcycle( stkstart , stkend )
567: arctype **stkstart;
568: arctype **stkend;
569: {
570: arctype **arcpp;
571: arctype **stkloc;
572: arctype **stkp;
573: arctype **endlist;
574: arctype *minarc;
575: arctype *arcp;
576: cltype *clp;
577: int size;
578:
579: size = stkend - stkstart + 1;
580: if ( size <= 1 )
581: return( TRUE );
582: for ( arcpp = stkstart , minarc = *arcpp ; arcpp <= stkend ; arcpp++ ) {
583: if ( *arcpp > minarc )
584: continue;
585: minarc = *arcpp;
586: stkloc = arcpp;
587: }
588: for ( clp = cyclehead ; clp ; clp = clp -> next ) {
589: if ( clp -> size != size )
590: continue;
591: stkp = stkloc;
592: endlist = &clp -> list[ size ];
593: for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) {
594: if ( *stkp++ != *arcpp )
595: break;
596: if ( stkp > stkend )
597: stkp = stkstart;
598: }
599: if ( arcpp == endlist ) {
600: # ifdef DEBUG
601: oldcycle++;
1.6 ! danh 602: # endif /* DEBUG */
1.1 deraadt 603: return( TRUE );
604: }
605: }
606: clp = (cltype *)
607: calloc( 1 , sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) );
608: if ( clp == 0 ) {
1.3 mickey 609: warnx("No room for %d bytes of subcycle storage" ,
610: sizeof(cltype) + (size - 1) * sizeof(arctype *));
1.1 deraadt 611: return( FALSE );
612: }
613: stkp = stkloc;
614: endlist = &clp -> list[ size ];
615: for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) {
616: arcp = *arcpp = *stkp++;
617: if ( stkp > stkend )
618: stkp = stkstart;
619: arcp -> arc_cyclecnt++;
620: if ( ( arcp -> arc_flags & ONLIST ) == 0 ) {
621: arcp -> arc_flags |= ONLIST;
622: arcp -> arc_next = archead;
623: archead = arcp;
624: }
625: }
626: clp -> size = size;
627: clp -> next = cyclehead;
628: cyclehead = clp;
629: # ifdef DEBUG
630: newcycle++;
631: if ( debug & SUBCYCLELIST ) {
632: printsubcycle( clp );
633: }
1.6 ! danh 634: # endif /* DEBUG */
1.1 deraadt 635: cyclecnt++;
636: if ( cyclecnt >= CYCLEMAX )
637: return( FALSE );
638: return( TRUE );
639: }
640:
1.3 mickey 641: void
1.1 deraadt 642: compresslist()
643: {
644: cltype *clp;
645: cltype **prev;
646: arctype **arcpp;
647: arctype **endlist;
648: arctype *arcp;
649: arctype *maxarcp;
650: arctype *maxexitarcp;
651: arctype *maxwithparentarcp;
652: arctype *maxnoparentarcp;
653: int maxexitcnt;
654: int maxwithparentcnt;
655: int maxnoparentcnt;
1.3 mickey 656: # ifdef DEBUG
657: char *type;
658: # endif
1.1 deraadt 659:
660: maxexitcnt = 0;
661: maxwithparentcnt = 0;
662: maxnoparentcnt = 0;
663: for ( endlist = &archead , arcp = archead ; arcp ; ) {
664: if ( arcp -> arc_cyclecnt == 0 ) {
665: arcp -> arc_flags &= ~ONLIST;
666: *endlist = arcp -> arc_next;
667: arcp -> arc_next = 0;
668: arcp = *endlist;
669: continue;
670: }
671: if ( arcp -> arc_childp -> flags & HASCYCLEXIT ) {
672: if ( arcp -> arc_cyclecnt > maxexitcnt ||
673: ( arcp -> arc_cyclecnt == maxexitcnt &&
674: arcp -> arc_cyclecnt < maxexitarcp -> arc_count ) ) {
675: maxexitcnt = arcp -> arc_cyclecnt;
676: maxexitarcp = arcp;
677: }
678: } else if ( arcp -> arc_childp -> parentcnt > 1 ) {
679: if ( arcp -> arc_cyclecnt > maxwithparentcnt ||
680: ( arcp -> arc_cyclecnt == maxwithparentcnt &&
681: arcp -> arc_cyclecnt < maxwithparentarcp -> arc_count ) ) {
682: maxwithparentcnt = arcp -> arc_cyclecnt;
683: maxwithparentarcp = arcp;
684: }
685: } else {
686: if ( arcp -> arc_cyclecnt > maxnoparentcnt ||
687: ( arcp -> arc_cyclecnt == maxnoparentcnt &&
688: arcp -> arc_cyclecnt < maxnoparentarcp -> arc_count ) ) {
689: maxnoparentcnt = arcp -> arc_cyclecnt;
690: maxnoparentarcp = arcp;
691: }
692: }
693: endlist = &arcp -> arc_next;
694: arcp = arcp -> arc_next;
695: }
696: if ( maxexitcnt > 0 ) {
697: /*
698: * first choice is edge leading to node with out-of-cycle parent
699: */
700: maxarcp = maxexitarcp;
701: # ifdef DEBUG
702: type = "exit";
1.6 ! danh 703: # endif /* DEBUG */
1.1 deraadt 704: } else if ( maxwithparentcnt > 0 ) {
705: /*
706: * second choice is edge leading to node with at least one
707: * other in-cycle parent
708: */
709: maxarcp = maxwithparentarcp;
710: # ifdef DEBUG
711: type = "internal";
1.6 ! danh 712: # endif /* DEBUG */
1.1 deraadt 713: } else {
714: /*
715: * last choice is edge leading to node with only this arc as
716: * a parent (as it will now be orphaned)
717: */
718: maxarcp = maxnoparentarcp;
719: # ifdef DEBUG
720: type = "orphan";
1.6 ! danh 721: # endif /* DEBUG */
1.1 deraadt 722: }
723: maxarcp -> arc_flags |= DEADARC;
724: maxarcp -> arc_childp -> parentcnt -= 1;
725: maxarcp -> arc_childp -> npropcall -= maxarcp -> arc_count;
726: # ifdef DEBUG
727: if ( debug & BREAKCYCLE ) {
1.3 mickey 728: printf("[compresslist] delete %s arc: "
729: "%s (%ld) -> %s from %d cycle(s)\n", type,
730: maxarcp -> arc_parentp -> name, maxarcp -> arc_count,
731: maxarcp -> arc_childp -> name, maxarcp -> arc_cyclecnt);
1.1 deraadt 732: }
1.6 ! danh 733: # endif /* DEBUG */
1.3 mickey 734: printf("\t%s to %s with %ld calls\n", maxarcp->arc_parentp -> name,
735: maxarcp->arc_childp->name, maxarcp->arc_count);
1.1 deraadt 736: prev = &cyclehead;
737: for ( clp = cyclehead ; clp ; ) {
738: endlist = &clp -> list[ clp -> size ];
739: for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ )
740: if ( (*arcpp) -> arc_flags & DEADARC )
741: break;
742: if ( arcpp == endlist ) {
743: prev = &clp -> next;
744: clp = clp -> next;
745: continue;
746: }
747: for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ )
748: (*arcpp) -> arc_cyclecnt--;
749: cyclecnt--;
750: *prev = clp -> next;
751: clp = clp -> next;
752: free( clp );
753: }
754: }
755:
756: #ifdef DEBUG
757: printsubcycle( clp )
758: cltype *clp;
759: {
760: arctype **arcpp;
761: arctype **endlist;
762:
763: arcpp = clp -> list;
764: printf( "%s <cycle %d>\n" , (*arcpp) -> arc_parentp -> name ,
765: (*arcpp) -> arc_parentp -> cycleno ) ;
766: for ( endlist = &clp -> list[ clp -> size ]; arcpp < endlist ; arcpp++ )
767: printf( "\t(%d) -> %s\n" , (*arcpp) -> arc_count ,
768: (*arcpp) -> arc_childp -> name ) ;
769: }
1.4 heko 770: #endif /* DEBUG */
1.1 deraadt 771:
1.3 mickey 772: void
1.1 deraadt 773: cycletime()
774: {
775: int cycle;
776: nltype *cyclenlp;
777: nltype *childp;
778:
779: for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) {
780: cyclenlp = &cyclenl[ cycle ];
781: for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) {
782: if ( childp -> propfraction == 0.0 ) {
783: /*
784: * all members have the same propfraction except those
785: * that were excluded with -E
786: */
787: continue;
788: }
789: cyclenlp -> time += childp -> time;
790: }
791: cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time;
792: }
793: }
794:
795: /*
796: * in one top to bottom pass over the topologically sorted namelist
797: * propagate:
798: * printflag as the union of parents' printflags
799: * propfraction as the sum of fractional parents' propfractions
800: * and while we're here, sum time for functions.
801: */
1.3 mickey 802: void
1.1 deraadt 803: doflags()
804: {
805: int index;
806: nltype *childp;
807: nltype *oldhead;
808:
809: oldhead = 0;
810: for ( index = nname-1 ; index >= 0 ; index -= 1 ) {
811: childp = topsortnlp[ index ];
812: /*
813: * if we haven't done this function or cycle,
814: * inherit things from parent.
815: * this way, we are linear in the number of arcs
816: * since we do all members of a cycle (and the cycle itself)
817: * as we hit the first member of the cycle.
818: */
819: if ( childp -> cyclehead != oldhead ) {
820: oldhead = childp -> cyclehead;
821: inheritflags( childp );
822: }
823: # ifdef DEBUG
824: if ( debug & PROPDEBUG ) {
825: printf( "[doflags] " );
826: printname( childp );
827: printf( " inherits printflag %d and propfraction %f\n" ,
828: childp -> printflag , childp -> propfraction );
829: }
1.6 ! danh 830: # endif /* DEBUG */
1.1 deraadt 831: if ( ! childp -> printflag ) {
832: /*
833: * printflag is off
834: * it gets turned on by
835: * being on -f list,
836: * or there not being any -f list and not being on -e list.
837: */
838: if ( onlist( flist , childp -> name )
839: || ( !fflag && !onlist( elist , childp -> name ) ) ) {
840: childp -> printflag = TRUE;
841: }
842: } else {
843: /*
844: * this function has printing parents:
845: * maybe someone wants to shut it up
846: * by putting it on -e list. (but favor -f over -e)
847: */
848: if ( ( !onlist( flist , childp -> name ) )
849: && onlist( elist , childp -> name ) ) {
850: childp -> printflag = FALSE;
851: }
852: }
853: if ( childp -> propfraction == 0.0 ) {
854: /*
855: * no parents to pass time to.
856: * collect time from children if
857: * its on -F list,
858: * or there isn't any -F list and its not on -E list.
859: */
860: if ( onlist( Flist , childp -> name )
861: || ( !Fflag && !onlist( Elist , childp -> name ) ) ) {
862: childp -> propfraction = 1.0;
863: }
864: } else {
865: /*
1.3 mickey 866: * it has parents to pass time to,
1.1 deraadt 867: * but maybe someone wants to shut it up
868: * by puttting it on -E list. (but favor -F over -E)
869: */
870: if ( !onlist( Flist , childp -> name )
871: && onlist( Elist , childp -> name ) ) {
872: childp -> propfraction = 0.0;
873: }
874: }
875: childp -> propself = childp -> time * childp -> propfraction;
876: printtime += childp -> propself;
877: # ifdef DEBUG
878: if ( debug & PROPDEBUG ) {
879: printf( "[doflags] " );
880: printname( childp );
881: printf( " ends up with printflag %d and propfraction %f\n" ,
882: childp -> printflag , childp -> propfraction );
883: printf( "time %f propself %f printtime %f\n" ,
884: childp -> time , childp -> propself , printtime );
885: }
1.6 ! danh 886: # endif /* DEBUG */
1.1 deraadt 887: }
888: }
889:
890: /*
891: * check if any parent of this child
892: * (or outside parents of this cycle)
1.3 mickey 893: * have their print flags on and set the
1.1 deraadt 894: * print flag of the child (cycle) appropriately.
895: * similarly, deal with propagation fractions from parents.
896: */
1.3 mickey 897: void
1.1 deraadt 898: inheritflags( childp )
899: nltype *childp;
900: {
901: nltype *headp;
902: arctype *arcp;
903: nltype *parentp;
904: nltype *memp;
905:
906: headp = childp -> cyclehead;
907: if ( childp == headp ) {
908: /*
909: * just a regular child, check its parents
910: */
911: childp -> printflag = FALSE;
912: childp -> propfraction = 0.0;
913: for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) {
914: parentp = arcp -> arc_parentp;
915: if ( childp == parentp ) {
916: continue;
917: }
918: childp -> printflag |= parentp -> printflag;
919: /*
920: * if the child was never actually called
921: * (e.g. this arc is static (and all others are, too))
922: * no time propagates along this arc.
923: */
924: if ( arcp -> arc_flags & DEADARC ) {
925: continue;
926: }
927: if ( childp -> npropcall ) {
928: childp -> propfraction += parentp -> propfraction
929: * ( ( (double) arcp -> arc_count )
930: / ( (double) childp -> npropcall ) );
931: }
932: }
933: } else {
934: /*
1.3 mickey 935: * its a member of a cycle, look at all parents from
1.1 deraadt 936: * outside the cycle
937: */
938: headp -> printflag = FALSE;
939: headp -> propfraction = 0.0;
940: for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) {
941: for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) {
942: if ( arcp -> arc_parentp -> cyclehead == headp ) {
943: continue;
944: }
945: parentp = arcp -> arc_parentp;
946: headp -> printflag |= parentp -> printflag;
947: /*
948: * if the cycle was never actually called
949: * (e.g. this arc is static (and all others are, too))
950: * no time propagates along this arc.
951: */
952: if ( arcp -> arc_flags & DEADARC ) {
953: continue;
954: }
955: if ( headp -> npropcall ) {
956: headp -> propfraction += parentp -> propfraction
957: * ( ( (double) arcp -> arc_count )
958: / ( (double) headp -> npropcall ) );
959: }
960: }
961: }
962: for ( memp = headp ; memp ; memp = memp -> cnext ) {
963: memp -> printflag = headp -> printflag;
964: memp -> propfraction = headp -> propfraction;
965: }
966: }
967: }