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