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