2 * Copyright (c) 1983 Regents of the University of California.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that: (1) source distributions retain this entire copyright
7 * notice and comment, and (2) distributions including binaries display
8 * the following acknowledgement: ``This product includes software
9 * developed by the University of California, Berkeley and its contributors''
10 * in the documentation or other materials provided with the distribution
11 * and in all advertising materials mentioning features or use of this
12 * software. Neither the name of the University nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 static char sccsid
[] = "@(#)arcs.c 5.6 (Berkeley) 6/1/90";
27 * add (or just increment) an arc
29 addarc( parentp
, childp
, count
)
38 if ( debug
& TALLYDEBUG
) {
39 printf( "[addarc] %d arcs from %s to %s\n" ,
40 count
, parentp
-> name
, childp
-> name
);
43 arcp
= arclookup( parentp
, childp
);
46 * a hit: just increment the count.
49 if ( debug
& TALLYDEBUG
) {
50 printf( "[tally] hit %d += %d\n" ,
51 arcp
-> arc_count
, count
);
54 arcp
-> arc_count
+= count
;
57 arcp
= calloc( 1 , sizeof *arcp
);
58 arcp
-> arc_parentp
= parentp
;
59 arcp
-> arc_childp
= childp
;
60 arcp
-> arc_count
= count
;
62 * prepend this child to the children of this parent
64 arcp
-> arc_childlist
= parentp
-> children
;
65 parentp
-> children
= arcp
;
67 * prepend this parent to the parents of this child
69 arcp
-> arc_parentlist
= childp
-> parents
;
70 childp
-> parents
= arcp
;
74 * the code below topologically sorts the graph (collapsing cycles),
75 * and propagates time bottom up and flags top down.
79 * the topologically sorted name list pointers
87 return (*npp1
) -> toporder
- (*npp2
) -> toporder
;
93 nltype
*parentp
, **timesortnlp
;
98 * initialize various things:
99 * zero out child times.
100 * count self-recursive calls.
101 * indicate that nothing is on cycles.
103 for ( parentp
= nl
; parentp
< npe
; parentp
++ ) {
104 parentp
-> childtime
= 0.0;
105 arcp
= arclookup( parentp
, parentp
);
107 parentp
-> ncall
-= arcp
-> arc_count
;
108 parentp
-> selfcalls
= arcp
-> arc_count
;
110 parentp
-> selfcalls
= 0;
112 parentp
-> propfraction
= 0.0;
113 parentp
-> propself
= 0.0;
114 parentp
-> propchild
= 0.0;
115 parentp
-> printflag
= FALSE
;
116 parentp
-> toporder
= DFN_NAN
;
117 parentp
-> cycleno
= 0;
118 parentp
-> cyclehead
= parentp
;
119 parentp
-> cnext
= 0;
121 findcall( parentp
, parentp
-> value
, (parentp
+1) -> value
);
125 * topologically order things
126 * if any node is unnumbered,
127 * number it and any of its descendents.
129 for ( parentp
= nl
; parentp
< npe
; parentp
++ ) {
130 if ( parentp
-> toporder
== DFN_NAN
) {
135 * link together nodes on the same cycle
139 * Sort the symbol table in reverse topological order
141 topsortnlp
= (nltype
**) calloc( nname
, sizeof(nltype
*) );
142 if ( topsortnlp
== (nltype
**) 0 ) {
143 fprintf( stderr
, "[doarcs] ran out of memory for topo sorting\n" );
145 for ( index
= 0 ; index
< nname
; index
+= 1 ) {
146 topsortnlp
[ index
] = &nl
[ index
];
148 qsort( topsortnlp
, nname
, sizeof(nltype
*) , topcmp
);
150 if ( debug
& DFNDEBUG
) {
151 printf( "[doarcs] topological sort listing\n" );
152 for ( index
= 0 ; index
< nname
; index
+= 1 ) {
153 printf( "[doarcs] " );
154 printf( "%d:" , topsortnlp
[ index
] -> toporder
);
155 printname( topsortnlp
[ index
] );
161 * starting from the topological top,
162 * propagate print flags to children.
163 * also, calculate propagation fractions.
164 * this happens before time propagation
165 * since time propagation uses the fractions.
169 * starting from the topological bottom,
170 * propogate children times up to parents.
174 * Now, sort by propself + propchild.
175 * sorting both the regular function names
178 timesortnlp
= (nltype
**) calloc( nname
+ ncycle
, sizeof(nltype
*) );
179 if ( timesortnlp
== (nltype
**) 0 ) {
180 fprintf( stderr
, "%s: ran out of memory for sorting\n" , whoami
);
182 for ( index
= 0 ; index
< nname
; index
++ ) {
183 timesortnlp
[index
] = &nl
[index
];
185 for ( index
= 1 ; index
<= ncycle
; index
++ ) {
186 timesortnlp
[nname
+index
-1] = &cyclenl
[index
];
188 qsort( timesortnlp
, nname
+ ncycle
, sizeof(nltype
*) , totalcmp
);
189 for ( index
= 0 ; index
< nname
+ ncycle
; index
++ ) {
190 timesortnlp
[ index
] -> index
= index
+ 1;
192 return( timesortnlp
);
200 for ( index
= 0 ; index
< nname
; index
+= 1 ) {
201 timepropagate( topsortnlp
[ index
] );
205 timepropagate( parentp
)
213 if ( parentp
-> propfraction
== 0.0 ) {
217 * gather time from children of this parent.
219 for ( arcp
= parentp
-> children
; arcp
; arcp
= arcp
-> arc_childlist
) {
220 childp
= arcp
-> arc_childp
;
221 if ( arcp
-> arc_count
== 0 ) {
224 if ( childp
== parentp
) {
227 if ( childp
-> propfraction
== 0.0 ) {
230 if ( childp
-> cyclehead
!= childp
) {
231 if ( parentp
-> cycleno
== childp
-> cycleno
) {
234 if ( parentp
-> toporder
<= childp
-> toporder
) {
235 fprintf( stderr
, "[propagate] toporder botches\n" );
237 childp
= childp
-> cyclehead
;
239 if ( parentp
-> toporder
<= childp
-> toporder
) {
240 fprintf( stderr
, "[propagate] toporder botches\n" );
244 if ( childp
-> ncall
== 0 ) {
248 * distribute time for this arc
250 arcp
-> arc_time
= childp
-> time
251 * ( ( (double) arcp
-> arc_count
) /
252 ( (double) childp
-> ncall
) );
253 arcp
-> arc_childtime
= childp
-> childtime
254 * ( ( (double) arcp
-> arc_count
) /
255 ( (double) childp
-> ncall
) );
256 share
= arcp
-> arc_time
+ arcp
-> arc_childtime
;
257 parentp
-> childtime
+= share
;
259 * ( 1 - propfraction ) gets lost along the way
261 propshare
= parentp
-> propfraction
* share
;
263 * fix things for printing
265 parentp
-> propchild
+= propshare
;
266 arcp
-> arc_time
*= parentp
-> propfraction
;
267 arcp
-> arc_childtime
*= parentp
-> propfraction
;
269 * add this share to the parent's cycle header, if any.
271 if ( parentp
-> cyclehead
!= parentp
) {
272 parentp
-> cyclehead
-> childtime
+= share
;
273 parentp
-> cyclehead
-> propchild
+= propshare
;
276 if ( debug
& PROPDEBUG
) {
277 printf( "[dotime] child \t" );
279 printf( " with %f %f %d/%d\n" ,
280 childp
-> time
, childp
-> childtime
,
281 arcp
-> arc_count
, childp
-> ncall
);
282 printf( "[dotime] parent\t" );
283 printname( parentp
);
284 printf( "\n[dotime] share %f\n" , share
);
292 register nltype
*nlp
;
293 register nltype
*cyclenlp
;
299 * Count the number of cycles, and initialze the cycle lists
302 for ( nlp
= nl
; nlp
< npe
; nlp
++ ) {
304 * this is how you find unattached cycles
306 if ( nlp
-> cyclehead
== nlp
&& nlp
-> cnext
!= 0 ) {
311 * cyclenl is indexed by cycle number:
312 * i.e. it is origin 1, not origin 0.
314 cyclenl
= (nltype
*) calloc( ncycle
+ 1 , sizeof( nltype
) );
315 if ( cyclenl
== 0 ) {
316 fprintf( stderr
, "%s: No room for %d bytes of cycle headers\n" ,
317 whoami
, ( ncycle
+ 1 ) * sizeof( nltype
) );
321 * now link cycles to true cycleheads,
322 * number them, accumulate the data for the cycle
325 for ( nlp
= nl
; nlp
< npe
; nlp
++ ) {
326 if ( !( nlp
-> cyclehead
== nlp
&& nlp
-> cnext
!= 0 ) ) {
330 cyclenlp
= &cyclenl
[cycle
];
331 cyclenlp
-> name
= 0; /* the name */
332 cyclenlp
-> value
= 0; /* the pc entry point */
333 cyclenlp
-> time
= 0.0; /* ticks in this routine */
334 cyclenlp
-> childtime
= 0.0; /* cumulative ticks in children */
335 cyclenlp
-> ncall
= 0; /* how many times called */
336 cyclenlp
-> selfcalls
= 0; /* how many calls to self */
337 cyclenlp
-> propfraction
= 0.0; /* what % of time propagates */
338 cyclenlp
-> propself
= 0.0; /* how much self time propagates */
339 cyclenlp
-> propchild
= 0.0; /* how much child time propagates */
340 cyclenlp
-> printflag
= TRUE
; /* should this be printed? */
341 cyclenlp
-> index
= 0; /* index in the graph list */
342 cyclenlp
-> toporder
= DFN_NAN
; /* graph call chain top-sort order */
343 cyclenlp
-> cycleno
= cycle
; /* internal number of cycle on */
344 cyclenlp
-> cyclehead
= cyclenlp
; /* pointer to head of cycle */
345 cyclenlp
-> cnext
= nlp
; /* pointer to next member of cycle */
346 cyclenlp
-> parents
= 0; /* list of caller arcs */
347 cyclenlp
-> children
= 0; /* list of callee arcs */
349 if ( debug
& CYCLEDEBUG
) {
350 printf( "[cyclelink] " );
352 printf( " is the head of cycle %d\n" , cycle
);
356 * link members to cycle header
358 for ( memberp
= nlp
; memberp
; memberp
= memberp
-> cnext
) {
359 memberp
-> cycleno
= cycle
;
360 memberp
-> cyclehead
= cyclenlp
;
363 * count calls from outside the cycle
364 * and those among cycle members
366 for ( memberp
= nlp
; memberp
; memberp
= memberp
-> cnext
) {
367 for ( arcp
=memberp
->parents
; arcp
; arcp
=arcp
->arc_parentlist
) {
368 if ( arcp
-> arc_parentp
== memberp
) {
371 if ( arcp
-> arc_parentp
-> cycleno
== cycle
) {
372 cyclenlp
-> selfcalls
+= arcp
-> arc_count
;
374 cyclenlp
-> ncall
+= arcp
-> arc_count
;
387 for ( cycle
= 1 ; cycle
<= ncycle
; cycle
+= 1 ) {
388 cyclenlp
= &cyclenl
[ cycle
];
389 for ( childp
= cyclenlp
-> cnext
; childp
; childp
= childp
-> cnext
) {
390 if ( childp
-> propfraction
== 0.0 ) {
392 * all members have the same propfraction except those
393 * that were excluded with -E
397 cyclenlp
-> time
+= childp
-> time
;
399 cyclenlp
-> propself
= cyclenlp
-> propfraction
* cyclenlp
-> time
;
404 * in one top to bottom pass over the topologically sorted namelist
406 * printflag as the union of parents' printflags
407 * propfraction as the sum of fractional parents' propfractions
408 * and while we're here, sum time for functions.
417 for ( index
= nname
-1 ; index
>= 0 ; index
-= 1 ) {
418 childp
= topsortnlp
[ index
];
420 * if we haven't done this function or cycle,
421 * inherit things from parent.
422 * this way, we are linear in the number of arcs
423 * since we do all members of a cycle (and the cycle itself)
424 * as we hit the first member of the cycle.
426 if ( childp
-> cyclehead
!= oldhead
) {
427 oldhead
= childp
-> cyclehead
;
428 inheritflags( childp
);
431 if ( debug
& PROPDEBUG
) {
432 printf( "[doflags] " );
434 printf( " inherits printflag %d and propfraction %f\n" ,
435 childp
-> printflag
, childp
-> propfraction
);
438 if ( ! childp
-> printflag
) {
441 * it gets turned on by
443 * or there not being any -f list and not being on -e list.
445 if ( onlist( flist
, childp
-> name
)
446 || ( !fflag
&& !onlist( elist
, childp
-> name
) ) ) {
447 childp
-> printflag
= TRUE
;
451 * this function has printing parents:
452 * maybe someone wants to shut it up
453 * by putting it on -e list. (but favor -f over -e)
455 if ( ( !onlist( flist
, childp
-> name
) )
456 && onlist( elist
, childp
-> name
) ) {
457 childp
-> printflag
= FALSE
;
460 if ( childp
-> propfraction
== 0.0 ) {
462 * no parents to pass time to.
463 * collect time from children if
465 * or there isn't any -F list and its not on -E list.
467 if ( onlist( Flist
, childp
-> name
)
468 || ( !Fflag
&& !onlist( Elist
, childp
-> name
) ) ) {
469 childp
-> propfraction
= 1.0;
473 * it has parents to pass time to,
474 * but maybe someone wants to shut it up
475 * by puttting it on -E list. (but favor -F over -E)
477 if ( !onlist( Flist
, childp
-> name
)
478 && onlist( Elist
, childp
-> name
) ) {
479 childp
-> propfraction
= 0.0;
482 childp
-> propself
= childp
-> time
* childp
-> propfraction
;
483 printtime
+= childp
-> propself
;
485 if ( debug
& PROPDEBUG
) {
486 printf( "[doflags] " );
488 printf( " ends up with printflag %d and propfraction %f\n" ,
489 childp
-> printflag
, childp
-> propfraction
);
490 printf( "time %f propself %f printtime %f\n" ,
491 childp
-> time
, childp
-> propself
, printtime
);
498 * check if any parent of this child
499 * (or outside parents of this cycle)
500 * have their print flags on and set the
501 * print flag of the child (cycle) appropriately.
502 * similarly, deal with propagation fractions from parents.
504 inheritflags( childp
)
512 headp
= childp
-> cyclehead
;
513 if ( childp
== headp
) {
515 * just a regular child, check its parents
517 childp
-> printflag
= FALSE
;
518 childp
-> propfraction
= 0.0;
519 for (arcp
= childp
-> parents
; arcp
; arcp
= arcp
-> arc_parentlist
) {
520 parentp
= arcp
-> arc_parentp
;
521 if ( childp
== parentp
) {
524 childp
-> printflag
|= parentp
-> printflag
;
526 * if the child was never actually called
527 * (e.g. this arc is static (and all others are, too))
528 * no time propagates along this arc.
530 if ( childp
-> ncall
) {
531 childp
-> propfraction
+= parentp
-> propfraction
532 * ( ( (double) arcp
-> arc_count
)
533 / ( (double) childp
-> ncall
) );
538 * its a member of a cycle, look at all parents from
541 headp
-> printflag
= FALSE
;
542 headp
-> propfraction
= 0.0;
543 for ( memp
= headp
-> cnext
; memp
; memp
= memp
-> cnext
) {
544 for (arcp
= memp
->parents
; arcp
; arcp
= arcp
->arc_parentlist
) {
545 if ( arcp
-> arc_parentp
-> cyclehead
== headp
) {
548 parentp
= arcp
-> arc_parentp
;
549 headp
-> printflag
|= parentp
-> printflag
;
551 * if the cycle was never actually called
552 * (e.g. this arc is static (and all others are, too))
553 * no time propagates along this arc.
555 if ( headp
-> ncall
) {
556 headp
-> propfraction
+= parentp
-> propfraction
557 * ( ( (double) arcp
-> arc_count
)
558 / ( (double) headp
-> ncall
) );
562 for ( memp
= headp
; memp
; memp
= memp
-> cnext
) {
563 memp
-> printflag
= headp
-> printflag
;
564 memp
-> propfraction
= headp
-> propfraction
;
This page took 0.040628 seconds and 4 git commands to generate.