kernel - Correct missing unlock in SCSI pass device
[dragonfly.git] / usr.bin / gprof / arcs.c
blob2d7b02cef627ce85d6e1ce64b030ad5154796053
1 /*
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
33 * @(#)arcs.c 8.1 (Berkeley) 6/6/93
34 * $FreeBSD: src/usr.bin/gprof/arcs.c,v 1.6 1999/08/28 01:01:54 peter Exp $
35 * $DragonFly: src/usr.bin/gprof/arcs.c,v 1.5 2006/01/22 03:43:37 swildner Exp $
38 #include <err.h>
39 #include "gprof.h"
41 #ifdef DEBUG
42 int visited;
43 int viable;
44 int newcycle;
45 int oldcycle;
46 #endif /* DEBUG */
49 * add (or just increment) an arc
51 addarc(nltype *parentp, nltype *childp, long count)
53 arctype *arcp;
55 # ifdef DEBUG
56 if ( debug & TALLYDEBUG ) {
57 printf( "[addarc] %d arcs from %s to %s\n" ,
58 count , parentp -> name , childp -> name );
60 # endif /* DEBUG */
61 arcp = arclookup( parentp , childp );
62 if ( arcp != 0 ) {
64 * a hit: just increment the count.
66 # ifdef DEBUG
67 if ( debug & TALLYDEBUG ) {
68 printf( "[tally] hit %d += %d\n" ,
69 arcp -> arc_count , count );
71 # endif /* DEBUG */
72 arcp -> arc_count += count;
73 return;
75 arcp = (arctype *)calloc( 1 , sizeof *arcp );
76 arcp -> arc_parentp = parentp;
77 arcp -> arc_childp = childp;
78 arcp -> arc_count = count;
80 * prepend this child to the children of this parent
82 arcp -> arc_childlist = parentp -> children;
83 parentp -> children = arcp;
85 * prepend this parent to the parents of this child
87 arcp -> arc_parentlist = childp -> parents;
88 childp -> parents = arcp;
92 * the code below topologically sorts the graph (collapsing cycles),
93 * and propagates time bottom up and flags top down.
97 * the topologically sorted name list pointers
99 nltype **topsortnlp;
102 topcmp(const void *arg1, const void *arg2)
104 nltype *const*npp1 = arg1;
105 nltype *const*npp2 = arg2;
107 return (*npp1) -> toporder - (*npp2) -> toporder;
110 nltype **
111 doarcs(void)
113 nltype *parentp, **timesortnlp;
114 arctype *arcp;
115 long index;
116 long pass;
119 * initialize various things:
120 * zero out child times.
121 * count self-recursive calls.
122 * indicate that nothing is on cycles.
124 for ( parentp = nl ; parentp < npe ; parentp++ ) {
125 parentp -> childtime = 0.0;
126 arcp = arclookup( parentp , parentp );
127 if ( arcp != 0 ) {
128 parentp -> ncall -= arcp -> arc_count;
129 parentp -> selfcalls = arcp -> arc_count;
130 } else {
131 parentp -> selfcalls = 0;
133 parentp -> npropcall = parentp -> ncall;
134 parentp -> propfraction = 0.0;
135 parentp -> propself = 0.0;
136 parentp -> propchild = 0.0;
137 parentp -> printflag = FALSE;
138 parentp -> toporder = DFN_NAN;
139 parentp -> cycleno = 0;
140 parentp -> cyclehead = parentp;
141 parentp -> cnext = 0;
142 if ( cflag ) {
143 findcall( parentp , parentp -> value , (parentp+1) -> value );
146 for ( pass = 1 ; ; pass++ ) {
148 * topologically order things
149 * if any node is unnumbered,
150 * number it and any of its descendants.
152 for ( dfn_init() , parentp = nl ; parentp < npe ; parentp++ ) {
153 if ( parentp -> toporder == DFN_NAN ) {
154 dfn( parentp );
158 * link together nodes on the same cycle
160 cyclelink();
162 * if no cycles to break up, proceed
164 if ( ! Cflag )
165 break;
167 * analyze cycles to determine breakup
169 # ifdef DEBUG
170 if ( debug & BREAKCYCLE ) {
171 printf("[doarcs] pass %d, cycle(s) %d\n" , pass , ncycle );
173 # endif /* DEBUG */
174 if ( pass == 1 ) {
175 printf( "\n\n%s %s\n%s %d:\n" ,
176 "The following arcs were deleted" ,
177 "from the propagation calculation" ,
178 "to reduce the maximum cycle size to", cyclethreshold );
180 if ( cycleanalyze() )
181 break;
182 free ( cyclenl );
183 ncycle = 0;
184 for ( parentp = nl ; parentp < npe ; parentp++ ) {
185 parentp -> toporder = DFN_NAN;
186 parentp -> cycleno = 0;
187 parentp -> cyclehead = parentp;
188 parentp -> cnext = 0;
191 if ( pass > 1 ) {
192 printf( "\f\n" );
193 } else {
194 printf( "\tNone\n\n" );
197 * Sort the symbol table in reverse topological order
199 topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) );
200 if ( topsortnlp == NULL ) {
201 fprintf( stderr , "[doarcs] ran out of memory for topo sorting\n" );
203 for ( index = 0 ; index < nname ; index += 1 ) {
204 topsortnlp[ index ] = &nl[ index ];
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" );
217 # endif /* DEBUG */
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.
225 doflags();
227 * starting from the topological bottom,
228 * propogate children times up to parents.
230 dotime();
232 * Now, sort by propself + propchild.
233 * sorting both the regular function names
234 * and cycle headers.
236 timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
237 if ( timesortnlp == NULL ) {
238 warnx("ran out of memory for sorting");
240 for ( index = 0 ; index < nname ; index++ ) {
241 timesortnlp[index] = &nl[index];
243 for ( index = 1 ; index <= ncycle ; index++ ) {
244 timesortnlp[nname+index-1] = &cyclenl[index];
246 qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp );
247 for ( index = 0 ; index < nname + ncycle ; index++ ) {
248 timesortnlp[ index ] -> index = index + 1;
250 return( timesortnlp );
253 dotime(void)
255 int index;
257 cycletime();
258 for ( index = 0 ; index < nname ; index += 1 ) {
259 timepropagate( topsortnlp[ index ] );
263 timepropagate(nltype *parentp)
265 arctype *arcp;
266 nltype *childp;
267 double share;
268 double propshare;
270 if ( parentp -> propfraction == 0.0 ) {
271 return;
274 * gather time from children of this parent.
276 for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
277 childp = arcp -> arc_childp;
278 if ( arcp -> arc_flags & DEADARC ) {
279 continue;
281 if ( arcp -> arc_count == 0 ) {
282 continue;
284 if ( childp == parentp ) {
285 continue;
287 if ( childp -> propfraction == 0.0 ) {
288 continue;
290 if ( childp -> cyclehead != childp ) {
291 if ( parentp -> cycleno == childp -> cycleno ) {
292 continue;
294 if ( parentp -> toporder <= childp -> toporder ) {
295 fprintf( stderr , "[propagate] toporder botches\n" );
297 childp = childp -> cyclehead;
298 } else {
299 if ( parentp -> toporder <= childp -> toporder ) {
300 fprintf( stderr , "[propagate] toporder botches\n" );
301 continue;
304 if ( childp -> npropcall == 0 ) {
305 continue;
308 * distribute time for this arc
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;
319 * ( 1 - propfraction ) gets lost along the way
321 propshare = parentp -> propfraction * share;
323 * fix things for printing
325 parentp -> propchild += propshare;
326 arcp -> arc_time *= parentp -> propfraction;
327 arcp -> arc_childtime *= parentp -> propfraction;
329 * add this share to the parent's cycle header, if any.
331 if ( parentp -> cyclehead != parentp ) {
332 parentp -> cyclehead -> childtime += share;
333 parentp -> cyclehead -> propchild += propshare;
335 # ifdef DEBUG
336 if ( debug & PROPDEBUG ) {
337 printf( "[dotime] child \t" );
338 printname( childp );
339 printf( " with %f %f %d/%d\n" ,
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 );
346 # endif /* DEBUG */
350 cyclelink(void)
352 nltype *nlp;
353 nltype *cyclenlp;
354 int cycle;
355 nltype *memberp;
356 arctype *arcp;
359 * Count the number of cycles, and initialze the cycle lists
361 ncycle = 0;
362 for ( nlp = nl ; nlp < npe ; nlp++ ) {
364 * this is how you find unattached cycles
366 if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) {
367 ncycle += 1;
371 * cyclenl is indexed by cycle number:
372 * i.e. it is origin 1, not origin 0.
374 cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) );
375 if ( cyclenl == 0 ) {
376 warnx("no room for %d bytes of cycle headers",
377 ( ncycle + 1 ) * sizeof( nltype ) );
378 done();
381 * now link cycles to true cycleheads,
382 * number them, accumulate the data for the cycle
384 cycle = 0;
385 for ( nlp = nl ; nlp < npe ; nlp++ ) {
386 if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) {
387 continue;
389 cycle += 1;
390 cyclenlp = &cyclenl[cycle];
391 cyclenlp -> name = 0; /* the name */
392 cyclenlp -> value = 0; /* the pc entry point */
393 cyclenlp -> time = 0.0; /* ticks in this routine */
394 cyclenlp -> childtime = 0.0; /* cumulative ticks in children */
395 cyclenlp -> ncall = 0; /* how many times called */
396 cyclenlp -> selfcalls = 0; /* how many calls to self */
397 cyclenlp -> propfraction = 0.0; /* what % of time propagates */
398 cyclenlp -> propself = 0.0; /* how much self time propagates */
399 cyclenlp -> propchild = 0.0; /* how much child time propagates */
400 cyclenlp -> printflag = TRUE; /* should this be printed? */
401 cyclenlp -> index = 0; /* index in the graph list */
402 cyclenlp -> toporder = DFN_NAN; /* graph call chain top-sort order */
403 cyclenlp -> cycleno = cycle; /* internal number of cycle on */
404 cyclenlp -> cyclehead = cyclenlp; /* pointer to head of cycle */
405 cyclenlp -> cnext = nlp; /* pointer to next member of cycle */
406 cyclenlp -> parents = 0; /* list of caller arcs */
407 cyclenlp -> children = 0; /* list of callee arcs */
408 # ifdef DEBUG
409 if ( debug & CYCLEDEBUG ) {
410 printf( "[cyclelink] " );
411 printname( nlp );
412 printf( " is the head of cycle %d\n" , cycle );
414 # endif /* DEBUG */
416 * link members to cycle header
418 for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) {
419 memberp -> cycleno = cycle;
420 memberp -> cyclehead = cyclenlp;
423 * count calls from outside the cycle
424 * and those among cycle members
426 for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) {
427 for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) {
428 if ( arcp -> arc_parentp == memberp ) {
429 continue;
431 if ( arcp -> arc_parentp -> cycleno == cycle ) {
432 cyclenlp -> selfcalls += arcp -> arc_count;
433 } else {
434 cyclenlp -> npropcall += arcp -> arc_count;
442 * analyze cycles to determine breakup
444 cycleanalyze(void)
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;
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
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;
475 if ( size <= cyclethreshold )
476 continue;
477 done = FALSE;
478 cyclestack = (arctype **) calloc( size + 1 , sizeof( arctype *) );
479 if ( cyclestack == 0 ) {
480 warnx("no room for %d bytes of cycle stack",
481 ( size + 1 ) * sizeof( arctype * ) );
482 return;
484 # ifdef DEBUG
485 if ( debug & BREAKCYCLE ) {
486 printf( "[cycleanalyze] starting cycle %d of %d, size %d\n" ,
487 cycleno , ncycle , size );
489 # endif /* DEBUG */
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;
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 );
509 cyclehead = 0;
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);
517 # endif /* DEBUG */
518 return( done );
521 descend(nltype *node , arctype **stkstart, arctype **stkp)
523 arctype *arcp;
524 bool ret;
526 for ( arcp = node -> children ; arcp ; arcp = arcp -> arc_childlist ) {
527 # ifdef DEBUG
528 visited++;
529 # endif /* DEBUG */
530 if ( arcp -> arc_childp -> cycleno != node -> cycleno
531 || ( arcp -> arc_childp -> flags & VISITED )
532 || ( arcp -> arc_flags & DEADARC ) )
533 continue;
534 # ifdef DEBUG
535 viable++;
536 # endif /* DEBUG */
537 *stkp = arcp;
538 if ( arcp -> arc_childp -> flags & CYCLEHEAD ) {
539 if ( addcycle( stkstart , stkp ) == FALSE )
540 return( FALSE );
541 continue;
543 arcp -> arc_childp -> flags |= VISITED;
544 ret = descend( arcp -> arc_childp , stkstart , stkp + 1 );
545 arcp -> arc_childp -> flags &= ~VISITED;
546 if ( ret == FALSE )
547 return( FALSE );
551 addcycle(arctype **stkstart, arctype **stkend)
553 arctype **arcpp;
554 arctype **stkloc;
555 arctype **stkp;
556 arctype **endlist;
557 arctype *minarc;
558 arctype *arcp;
559 cltype *clp;
560 int size;
562 size = stkend - stkstart + 1;
563 if ( size <= 1 )
564 return( TRUE );
565 for ( arcpp = stkstart , minarc = *arcpp ; arcpp <= stkend ; arcpp++ ) {
566 if ( *arcpp > minarc )
567 continue;
568 minarc = *arcpp;
569 stkloc = arcpp;
571 for ( clp = cyclehead ; clp ; clp = clp -> next ) {
572 if ( clp -> size != size )
573 continue;
574 stkp = stkloc;
575 endlist = &clp -> list[ size ];
576 for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) {
577 if ( *stkp++ != *arcpp )
578 break;
579 if ( stkp > stkend )
580 stkp = stkstart;
582 if ( arcpp == endlist ) {
583 # ifdef DEBUG
584 oldcycle++;
585 # endif /* DEBUG */
586 return( TRUE );
589 clp = (cltype *)
590 calloc( 1 , sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) );
591 if ( clp == 0 ) {
592 warnx("no room for %d bytes of subcycle storage",
593 sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) );
594 return( FALSE );
596 stkp = stkloc;
597 endlist = &clp -> list[ size ];
598 for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) {
599 arcp = *arcpp = *stkp++;
600 if ( stkp > stkend )
601 stkp = stkstart;
602 arcp -> arc_cyclecnt++;
603 if ( ( arcp -> arc_flags & ONLIST ) == 0 ) {
604 arcp -> arc_flags |= ONLIST;
605 arcp -> arc_next = archead;
606 archead = arcp;
609 clp -> size = size;
610 clp -> next = cyclehead;
611 cyclehead = clp;
612 # ifdef DEBUG
613 newcycle++;
614 if ( debug & SUBCYCLELIST ) {
615 printsubcycle( clp );
617 # endif /* DEBUG */
618 cyclecnt++;
619 if ( cyclecnt >= CYCLEMAX )
620 return( FALSE );
621 return( TRUE );
624 compresslist(void)
626 cltype *clp;
627 cltype **prev;
628 arctype **arcpp;
629 arctype **endlist;
630 arctype *arcp;
631 arctype *maxarcp;
632 arctype *maxexitarcp;
633 arctype *maxwithparentarcp;
634 arctype *maxnoparentarcp;
635 int maxexitcnt;
636 int maxwithparentcnt;
637 int maxnoparentcnt;
639 maxexitcnt = 0;
640 maxwithparentcnt = 0;
641 maxnoparentcnt = 0;
642 for ( endlist = &archead , arcp = archead ; arcp ; ) {
643 if ( arcp -> arc_cyclecnt == 0 ) {
644 arcp -> arc_flags &= ~ONLIST;
645 *endlist = arcp -> arc_next;
646 arcp -> arc_next = 0;
647 arcp = *endlist;
648 continue;
650 if ( arcp -> arc_childp -> flags & HASCYCLEXIT ) {
651 if ( arcp -> arc_cyclecnt > maxexitcnt ||
652 ( arcp -> arc_cyclecnt == maxexitcnt &&
653 arcp -> arc_cyclecnt < maxexitarcp -> arc_count ) ) {
654 maxexitcnt = arcp -> arc_cyclecnt;
655 maxexitarcp = arcp;
657 } else if ( arcp -> arc_childp -> parentcnt > 1 ) {
658 if ( arcp -> arc_cyclecnt > maxwithparentcnt ||
659 ( arcp -> arc_cyclecnt == maxwithparentcnt &&
660 arcp -> arc_cyclecnt < maxwithparentarcp -> arc_count ) ) {
661 maxwithparentcnt = arcp -> arc_cyclecnt;
662 maxwithparentarcp = arcp;
664 } else {
665 if ( arcp -> arc_cyclecnt > maxnoparentcnt ||
666 ( arcp -> arc_cyclecnt == maxnoparentcnt &&
667 arcp -> arc_cyclecnt < maxnoparentarcp -> arc_count ) ) {
668 maxnoparentcnt = arcp -> arc_cyclecnt;
669 maxnoparentarcp = arcp;
672 endlist = &arcp -> arc_next;
673 arcp = arcp -> arc_next;
675 if ( maxexitcnt > 0 ) {
677 * first choice is edge leading to node with out-of-cycle parent
679 maxarcp = maxexitarcp;
680 # ifdef DEBUG
681 type = "exit";
682 # endif /* DEBUG */
683 } else if ( maxwithparentcnt > 0 ) {
685 * second choice is edge leading to node with at least one
686 * other in-cycle parent
688 maxarcp = maxwithparentarcp;
689 # ifdef DEBUG
690 type = "internal";
691 # endif /* DEBUG */
692 } else {
694 * last choice is edge leading to node with only this arc as
695 * a parent (as it will now be orphaned)
697 maxarcp = maxnoparentarcp;
698 # ifdef DEBUG
699 type = "orphan";
700 # endif /* DEBUG */
702 maxarcp -> arc_flags |= DEADARC;
703 maxarcp -> arc_childp -> parentcnt -= 1;
704 maxarcp -> arc_childp -> npropcall -= maxarcp -> arc_count;
705 # ifdef DEBUG
706 if ( debug & BREAKCYCLE ) {
707 printf( "%s delete %s arc: %s (%d) -> %s from %d cycle(s)\n" ,
708 "[compresslist]" , type , maxarcp -> arc_parentp -> name ,
709 maxarcp -> arc_count , maxarcp -> arc_childp -> name ,
710 maxarcp -> arc_cyclecnt );
712 # endif /* DEBUG */
713 printf( "\t%s to %s with %d calls\n" , maxarcp -> arc_parentp -> name ,
714 maxarcp -> arc_childp -> name , maxarcp -> arc_count );
715 prev = &cyclehead;
716 for ( clp = cyclehead ; clp ; ) {
717 endlist = &clp -> list[ clp -> size ];
718 for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ )
719 if ( (*arcpp) -> arc_flags & DEADARC )
720 break;
721 if ( arcpp == endlist ) {
722 prev = &clp -> next;
723 clp = clp -> next;
724 continue;
726 for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ )
727 (*arcpp) -> arc_cyclecnt--;
728 cyclecnt--;
729 *prev = clp -> next;
730 clp = clp -> next;
731 free( clp );
735 #ifdef DEBUG
736 printsubcycle(cltype *clp)
738 arctype **arcpp;
739 arctype **endlist;
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++ )
745 printf( "\t(%d) -> %s\n" , (*arcpp) -> arc_count ,
746 (*arcpp) -> arc_childp -> name ) ;
748 #endif /* DEBUG */
750 cycletime(void)
752 int cycle;
753 nltype *cyclenlp;
754 nltype *childp;
756 for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) {
757 cyclenlp = &cyclenl[ cycle ];
758 for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) {
759 if ( childp -> propfraction == 0.0 ) {
761 * all members have the same propfraction except those
762 * that were excluded with -E
764 continue;
766 cyclenlp -> time += childp -> time;
768 cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time;
773 * in one top to bottom pass over the topologically sorted namelist
774 * propagate:
775 * printflag as the union of parents' printflags
776 * propfraction as the sum of fractional parents' propfractions
777 * and while we're here, sum time for functions.
779 doflags(void)
781 int index;
782 nltype *childp;
783 nltype *oldhead;
785 oldhead = 0;
786 for ( index = nname-1 ; index >= 0 ; index -= 1 ) {
787 childp = topsortnlp[ index ];
789 * if we haven't done this function or cycle,
790 * inherit things from parent.
791 * this way, we are linear in the number of arcs
792 * since we do all members of a cycle (and the cycle itself)
793 * as we hit the first member of the cycle.
795 if ( childp -> cyclehead != oldhead ) {
796 oldhead = childp -> cyclehead;
797 inheritflags( childp );
799 # ifdef DEBUG
800 if ( debug & PROPDEBUG ) {
801 printf( "[doflags] " );
802 printname( childp );
803 printf( " inherits printflag %d and propfraction %f\n" ,
804 childp -> printflag , childp -> propfraction );
806 # endif /* DEBUG */
807 if ( ! childp -> printflag ) {
809 * printflag is off
810 * it gets turned on by
811 * being on -f list,
812 * or there not being any -f list and not being on -e list.
814 if ( onlist( flist , childp -> name )
815 || ( !fflag && !onlist( elist , childp -> name ) ) ) {
816 childp -> printflag = TRUE;
818 } else {
820 * this function has printing parents:
821 * maybe someone wants to shut it up
822 * by putting it on -e list. (but favor -f over -e)
824 if ( ( !onlist( flist , childp -> name ) )
825 && onlist( elist , childp -> name ) ) {
826 childp -> printflag = FALSE;
829 if ( childp -> propfraction == 0.0 ) {
831 * no parents to pass time to.
832 * collect time from children if
833 * its on -F list,
834 * or there isn't any -F list and its not on -E list.
836 if ( onlist( Flist , childp -> name )
837 || ( !Fflag && !onlist( Elist , childp -> name ) ) ) {
838 childp -> propfraction = 1.0;
840 } else {
842 * it has parents to pass time to,
843 * but maybe someone wants to shut it up
844 * by puttting it on -E list. (but favor -F over -E)
846 if ( !onlist( Flist , childp -> name )
847 && onlist( Elist , childp -> name ) ) {
848 childp -> propfraction = 0.0;
851 childp -> propself = childp -> time * childp -> propfraction;
852 printtime += childp -> propself;
853 # ifdef DEBUG
854 if ( debug & PROPDEBUG ) {
855 printf( "[doflags] " );
856 printname( childp );
857 printf( " ends up with printflag %d and propfraction %f\n" ,
858 childp -> printflag , childp -> propfraction );
859 printf( "time %f propself %f printtime %f\n" ,
860 childp -> time , childp -> propself , printtime );
862 # endif /* DEBUG */
867 * check if any parent of this child
868 * (or outside parents of this cycle)
869 * have their print flags on and set the
870 * print flag of the child (cycle) appropriately.
871 * similarly, deal with propagation fractions from parents.
873 inheritflags(nltype *childp)
875 nltype *headp;
876 arctype *arcp;
877 nltype *parentp;
878 nltype *memp;
880 headp = childp -> cyclehead;
881 if ( childp == headp ) {
883 * just a regular child, check its parents
885 childp -> printflag = FALSE;
886 childp -> propfraction = 0.0;
887 for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) {
888 parentp = arcp -> arc_parentp;
889 if ( childp == parentp ) {
890 continue;
892 childp -> printflag |= parentp -> printflag;
894 * if the child was never actually called
895 * (e.g. this arc is static (and all others are, too))
896 * no time propagates along this arc.
898 if ( arcp -> arc_flags & DEADARC ) {
899 continue;
901 if ( childp -> npropcall ) {
902 childp -> propfraction += parentp -> propfraction
903 * ( ( (double) arcp -> arc_count )
904 / ( (double) childp -> npropcall ) );
907 } else {
909 * its a member of a cycle, look at all parents from
910 * outside the cycle
912 headp -> printflag = FALSE;
913 headp -> propfraction = 0.0;
914 for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) {
915 for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) {
916 if ( arcp -> arc_parentp -> cyclehead == headp ) {
917 continue;
919 parentp = arcp -> arc_parentp;
920 headp -> printflag |= parentp -> printflag;
922 * if the cycle was never actually called
923 * (e.g. this arc is static (and all others are, too))
924 * no time propagates along this arc.
926 if ( arcp -> arc_flags & DEADARC ) {
927 continue;
929 if ( headp -> npropcall ) {
930 headp -> propfraction += parentp -> propfraction
931 * ( ( (double) arcp -> arc_count )
932 / ( (double) headp -> npropcall ) );
936 for ( memp = headp ; memp ; memp = memp -> cnext ) {
937 memp -> printflag = headp -> printflag;
938 memp -> propfraction = headp -> propfraction;