8 * Return value of comparison functions used to sort tables:
14 /* declarations of automatically generated functions to output blurbs: */
15 extern void bsd_callg_blurb
PARAMS ((FILE * fp
));
16 extern void fsf_callg_blurb
PARAMS ((FILE * fp
));
18 double print_time
= 0.0;
22 DEFUN_VOID (print_header
)
32 if (!bsd_style_output
)
34 if (print_descriptions
)
36 printf ("\t\t Call graph (explanation follows)\n\n");
40 printf ("\t\t\tCall graph\n\n");
43 printf ("\ngranularity: each sample hit covers %ld byte(s)",
44 (long) hist_scale
* sizeof (UNIT
));
47 printf (" for %.2f%% of %.2f seconds\n\n",
48 100.0 / print_time
, print_time
/ hz
);
52 printf (" no time propagated\n\n");
54 * This doesn't hurt, since all the numerators will be 0.0:
60 printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
61 "", "", "", "", "called", "total", "parents");
62 printf ("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n",
63 "index", "%time", "self", "descendents",
64 "called", "self", "name", "index");
65 printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
66 "", "", "", "", "called", "total", "children");
71 printf ("index %% time self children called name\n");
77 * Print a cycle header.
80 DEFUN (print_cycle
, (cyc
), Sym
* cyc
)
84 sprintf (buf
, "[%d]", cyc
->cg
.index
);
85 printf ("%-6.6s %5.1f %7.2f %11.2f %7d", buf
,
86 100 * (cyc
->cg
.prop
.self
+ cyc
->cg
.prop
.child
) / print_time
,
87 cyc
->cg
.prop
.self
/ hz
, cyc
->cg
.prop
.child
/ hz
, cyc
->ncalls
);
88 if (cyc
->cg
.self_calls
!= 0)
90 printf ("+%-7d", cyc
->cg
.self_calls
);
94 printf (" %7.7s", "");
96 printf (" <cycle %d as a whole>\t[%d]\n", cyc
->cg
.cyc
.num
, cyc
->cg
.index
);
101 * Compare LEFT and RIGHT membmer. Major comparison key is
102 * CG.PROP.SELF+CG.PROP.CHILD, secondary key is NCALLS+CG.SELF_CALLS.
105 DEFUN (cmp_member
, (left
, right
), Sym
* left AND Sym
* right
)
107 double left_time
= left
->cg
.prop
.self
+ left
->cg
.prop
.child
;
108 double right_time
= right
->cg
.prop
.self
+ right
->cg
.prop
.child
;
109 long left_calls
= left
->ncalls
+ left
->cg
.self_calls
;
110 long right_calls
= right
->ncalls
+ right
->cg
.self_calls
;
112 if (left_time
> right_time
)
116 if (left_time
< right_time
)
121 if (left_calls
> right_calls
)
125 if (left_calls
< right_calls
)
134 * Sort members of a cycle.
137 DEFUN (sort_members
, (cyc
), Sym
* cyc
)
139 Sym
*todo
, *doing
, *prev
;
141 * Detach cycle members from cyclehead, and insertion sort them
144 todo
= cyc
->cg
.cyc
.next
;
145 cyc
->cg
.cyc
.next
= 0;
146 for (doing
= todo
; doing
&& doing
->cg
.cyc
.next
; doing
= todo
)
148 todo
= doing
->cg
.cyc
.next
;
149 for (prev
= cyc
; prev
->cg
.cyc
.next
; prev
= prev
->cg
.cyc
.next
)
151 if (cmp_member (doing
, prev
->cg
.cyc
.next
) == GREATERTHAN
)
156 doing
->cg
.cyc
.next
= prev
->cg
.cyc
.next
;
157 prev
->cg
.cyc
.next
= doing
;
163 * Print the members of a cycle.
166 DEFUN (print_members
, (cyc
), Sym
* cyc
)
171 for (member
= cyc
->cg
.cyc
.next
; member
; member
= member
->cg
.cyc
.next
)
173 printf ("%6.6s %5.5s %7.2f %11.2f %7d",
174 "", "", member
->cg
.prop
.self
/ hz
, member
->cg
.prop
.child
/ hz
,
176 if (member
->cg
.self_calls
!= 0)
178 printf ("+%-7d", member
->cg
.self_calls
);
182 printf (" %7.7s", "");
192 * Compare two arcs to/from the same child/parent.
193 * - if one arc is a self arc, it's least.
194 * - if one arc is within a cycle, it's less than.
195 * - if both arcs are within a cycle, compare arc counts.
196 * - if neither arc is within a cycle, compare with
197 * time + child_time as major key
198 * arc count as minor key
201 DEFUN (cmp_arc
, (left
, right
), Arc
* left AND Arc
* right
)
203 Sym
*left_parent
= left
->parent
;
204 Sym
*left_child
= left
->child
;
205 Sym
*right_parent
= right
->parent
;
206 Sym
*right_child
= right
->child
;
207 double left_time
, right_time
;
210 printf ("[cmp_arc] ");
211 print_name (left_parent
);
213 print_name (left_child
);
214 printf (" %f + %f %d/%d\n", left
->time
, left
->child_time
,
215 left
->count
, left_child
->ncalls
);
216 printf ("[cmp_arc] ");
217 print_name (right_parent
);
219 print_name (right_child
);
220 printf (" %f + %f %d/%d\n", right
->time
, right
->child_time
,
221 right
->count
, right_child
->ncalls
);
224 if (left_parent
== left_child
)
226 return LESSTHAN
; /* left is a self call */
228 if (right_parent
== right_child
)
230 return GREATERTHAN
; /* right is a self call */
233 if (left_parent
->cg
.cyc
.num
!= 0 && left_child
->cg
.cyc
.num
!= 0
234 && left_parent
->cg
.cyc
.num
== left_child
->cg
.cyc
.num
)
236 /* left is a call within a cycle */
237 if (right_parent
->cg
.cyc
.num
!= 0 && right_child
->cg
.cyc
.num
!= 0
238 && right_parent
->cg
.cyc
.num
== right_child
->cg
.cyc
.num
)
240 /* right is a call within the cycle, too */
241 if (left
->count
< right
->count
)
245 if (left
->count
> right
->count
)
253 /* right isn't a call within the cycle */
259 /* left isn't a call within a cycle */
260 if (right_parent
->cg
.cyc
.num
!= 0 && right_child
->cg
.cyc
.num
!= 0
261 && right_parent
->cg
.cyc
.num
== right_child
->cg
.cyc
.num
)
263 /* right is a call within a cycle */
268 /* neither is a call within a cycle */
269 left_time
= left
->time
+ left
->child_time
;
270 right_time
= right
->time
+ right
->child_time
;
271 if (left_time
< right_time
)
275 if (left_time
> right_time
)
279 if (left
->count
< right
->count
)
283 if (left
->count
> right
->count
)
294 DEFUN (sort_parents
, (child
), Sym
* child
)
296 Arc
*arc
, *detached
, sorted
, *prev
;
299 * Unlink parents from child, then insertion sort back on to
301 * *arc the arc you have detached and are inserting.
302 * *detached the rest of the arcs to be sorted.
303 * sorted arc list onto which you insertion sort.
304 * *prev arc before the arc you are comparing.
306 sorted
.next_parent
= 0;
307 for (arc
= child
->cg
.parents
; arc
; arc
= detached
)
309 detached
= arc
->next_parent
;
311 /* consider *arc as disconnected; insert it into sorted: */
312 for (prev
= &sorted
; prev
->next_parent
; prev
= prev
->next_parent
)
314 if (cmp_arc (arc
, prev
->next_parent
) != GREATERTHAN
)
319 arc
->next_parent
= prev
->next_parent
;
320 prev
->next_parent
= arc
;
323 /* reattach sorted arcs to child: */
324 child
->cg
.parents
= sorted
.next_parent
;
329 DEFUN (print_parents
, (child
), Sym
* child
)
335 if (child
->cg
.cyc
.head
!= 0)
337 cycle_head
= child
->cg
.cyc
.head
;
343 if (!child
->cg
.parents
)
345 printf (bsd_style_output
346 ? "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n"
347 : "%6.6s %5.5s %7.7s %7.7s %7.7s %7.7s <spontaneous>\n",
348 "", "", "", "", "", "");
351 sort_parents (child
);
352 for (arc
= child
->cg
.parents
; arc
; arc
= arc
->next_parent
)
354 parent
= arc
->parent
;
355 if (child
== parent
|| (child
->cg
.cyc
.num
!= 0
356 && parent
->cg
.cyc
.num
== child
->cg
.cyc
.num
))
358 /* selfcall or call among siblings: */
359 printf (bsd_style_output
360 ? "%6.6s %5.5s %7.7s %11.11s %7d %7.7s "
361 : "%6.6s %5.5s %7.7s %7.7s %7d %7.7s ",
369 /* regular parent of child: */
370 printf (bsd_style_output
371 ? "%6.6s %5.5s %7.2f %11.2f %7d/%-7d "
372 : "%6.6s %5.5s %7.2f %7.2f %7d/%-7d ",
374 arc
->time
/ hz
, arc
->child_time
/ hz
,
375 arc
->count
, cycle_head
->ncalls
);
384 DEFUN (sort_children
, (parent
), Sym
* parent
)
386 Arc
*arc
, *detached
, sorted
, *prev
;
388 * Unlink children from parent, then insertion sort back on to
390 * *arc the arc you have detached and are inserting.
391 * *detached the rest of the arcs to be sorted.
392 * sorted arc list onto which you insertion sort.
393 * *prev arc before the arc you are comparing.
395 sorted
.next_child
= 0;
396 for (arc
= parent
->cg
.children
; arc
; arc
= detached
)
398 detached
= arc
->next_child
;
400 /* consider *arc as disconnected; insert it into sorted: */
401 for (prev
= &sorted
; prev
->next_child
; prev
= prev
->next_child
)
403 if (cmp_arc (arc
, prev
->next_child
) != LESSTHAN
)
408 arc
->next_child
= prev
->next_child
;
409 prev
->next_child
= arc
;
412 /* reattach sorted children to parent: */
413 parent
->cg
.children
= sorted
.next_child
;
418 DEFUN (print_children
, (parent
), Sym
* parent
)
423 sort_children (parent
);
424 arc
= parent
->cg
.children
;
425 for (arc
= parent
->cg
.children
; arc
; arc
= arc
->next_child
)
428 if (child
== parent
|| (child
->cg
.cyc
.num
!= 0
429 && child
->cg
.cyc
.num
== parent
->cg
.cyc
.num
))
431 /* self call or call to sibling: */
432 printf (bsd_style_output
433 ? "%6.6s %5.5s %7.7s %11.11s %7d %7.7s "
434 : "%6.6s %5.5s %7.7s %7.7s %7d %7.7s ",
435 "", "", "", "", arc
->count
, "");
441 /* regular child of parent: */
442 printf (bsd_style_output
443 ? "%6.6s %5.5s %7.2f %11.2f %7d/%-7d "
444 : "%6.6s %5.5s %7.2f %7.2f %7d/%-7d ",
446 arc
->time
/ hz
, arc
->child_time
/ hz
,
447 arc
->count
, child
->cg
.cyc
.head
->ncalls
);
456 DEFUN (print_line
, (np
), Sym
* np
)
460 sprintf (buf
, "[%d]", np
->cg
.index
);
461 printf (bsd_style_output
462 ? "%-6.6s %5.1f %7.2f %11.2f"
463 : "%-6.6s %5.1f %7.2f %7.2f", buf
,
464 100 * (np
->cg
.prop
.self
+ np
->cg
.prop
.child
) / print_time
,
465 np
->cg
.prop
.self
/ hz
, np
->cg
.prop
.child
/ hz
);
466 if ((np
->ncalls
+ np
->cg
.self_calls
) != 0)
468 printf (" %7d", np
->ncalls
);
469 if (np
->cg
.self_calls
!= 0)
471 printf ("+%-7d ", np
->cg
.self_calls
);
475 printf (" %7.7s ", "");
480 printf (" %7.7s %7.7s ", "", "");
488 * Print dynamic call graph.
491 DEFUN (cg_print
, (timesortsym
), Sym
** timesortsym
)
496 if (print_descriptions
&& bsd_style_output
)
498 bsd_callg_blurb (stdout
);
503 for (index
= 0; index
< symtab
.len
+ num_cycles
; ++index
)
505 parent
= timesortsym
[index
];
506 if ((ignore_zeros
&& parent
->ncalls
== 0
507 && parent
->cg
.self_calls
== 0 && parent
->cg
.prop
.self
== 0
508 && parent
->cg
.prop
.child
== 0)
509 || !parent
->cg
.print_flag
)
513 if (!parent
->name
&& parent
->cg
.cyc
.num
!= 0)
516 print_cycle (parent
);
517 print_members (parent
);
521 print_parents (parent
);
523 print_children (parent
);
525 if (bsd_style_output
)
527 printf ("-----------------------------------------------\n");
528 if (bsd_style_output
)
532 if (print_descriptions
&& !bsd_style_output
)
534 fsf_callg_blurb (stdout
);
540 DEFUN (cmp_name
, (left
, right
), const PTR left AND
const PTR right
)
542 const Sym
**npp1
= (const Sym
**) left
;
543 const Sym
**npp2
= (const Sym
**) right
;
545 return strcmp ((*npp1
)->name
, (*npp2
)->name
);
550 DEFUN_VOID (cg_print_index
)
552 int index
, nnames
, todo
, i
, j
, col
, starting_col
;
553 Sym
**name_sorted_syms
, *sym
;
554 const char *filename
;
556 int column_width
= (output_width
- 1) / 3; /* don't write in last col! */
558 * Now, sort regular function name alphabetically to create an
561 name_sorted_syms
= (Sym
**) xmalloc ((symtab
.len
+ num_cycles
) * sizeof (Sym
*));
562 for (index
= 0, nnames
= 0; index
< symtab
.len
; index
++)
564 if (ignore_zeros
&& symtab
.base
[index
].ncalls
== 0
565 && symtab
.base
[index
].hist
.time
== 0)
569 name_sorted_syms
[nnames
++] = &symtab
.base
[index
];
571 qsort (name_sorted_syms
, nnames
, sizeof (Sym
*), cmp_name
);
572 for (index
= 1, todo
= nnames
; index
<= num_cycles
; index
++)
574 name_sorted_syms
[todo
++] = &cycle_header
[index
];
576 printf ("\f\nIndex by function name\n\n");
577 index
= (todo
+ 2) / 3;
578 for (i
= 0; i
< index
; i
++)
582 for (j
= i
; j
< todo
; j
+= index
)
584 sym
= name_sorted_syms
[j
];
585 if (sym
->cg
.print_flag
)
587 sprintf (buf
, "[%d]", sym
->cg
.index
);
591 sprintf (buf
, "(%d)", sym
->cg
.index
);
595 if (bsd_style_output
)
597 printf ("%6.6s %-19.19s", buf
, sym
->name
);
602 for (; col
< starting_col
+ 5; ++col
)
606 printf (" %s ", buf
);
607 col
+= print_name_only (sym
);
608 if (!line_granularity
&& sym
->is_static
&& sym
->file
)
610 filename
= sym
->file
->name
;
613 filename
= strrchr (filename
, '/');
620 filename
= sym
->file
->name
;
623 printf (" (%s)", filename
);
624 col
+= strlen (filename
) + 3;
630 printf ("%6.6s ", buf
);
631 sprintf (buf
, "<cycle %d>", sym
->cg
.cyc
.num
);
632 printf ("%-19.19s", buf
);
634 starting_col
+= column_width
;
638 free (name_sorted_syms
);
This page took 0.05841 seconds and 4 git commands to generate.