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