2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses>
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 #include "event-parse.h"
25 #include "event-utils.h"
27 static struct func_stack
{
36 static void add_child(struct func_stack
*stack
, const char *child
, int pos
)
43 if (pos
< stack
->size
)
44 free(stack
->stack
[pos
]);
48 ptr
= realloc(stack
->stack
, sizeof(char *) *
49 (stack
->size
+ STK_BLK
));
51 warning("could not allocate plugin memory\n");
57 for (i
= stack
->size
; i
< stack
->size
+ STK_BLK
; i
++)
58 stack
->stack
[i
] = NULL
;
59 stack
->size
+= STK_BLK
;
62 stack
->stack
[pos
] = strdup(child
);
65 static int add_and_get_index(const char *parent
, const char *child
, int cpu
)
73 struct func_stack
*ptr
;
75 ptr
= realloc(fstack
, sizeof(*fstack
) * (cpu
+ 1));
77 warning("could not allocate plugin memory\n");
83 /* Account for holes in the cpu count */
84 for (i
= cpus
+ 1; i
<= cpu
; i
++)
85 memset(&fstack
[i
], 0, sizeof(fstack
[i
]));
89 for (i
= 0; i
< fstack
[cpu
].size
&& fstack
[cpu
].stack
[i
]; i
++) {
90 if (strcmp(parent
, fstack
[cpu
].stack
[i
]) == 0) {
91 add_child(&fstack
[cpu
], child
, i
+1);
97 add_child(&fstack
[cpu
], parent
, 0);
98 add_child(&fstack
[cpu
], child
, 1);
102 static int function_handler(struct trace_seq
*s
, struct pevent_record
*record
,
103 struct event_format
*event
, void *context
)
105 struct pevent
*pevent
= event
->pevent
;
106 unsigned long long function
;
107 unsigned long long pfunction
;
112 if (pevent_get_field_val(s
, event
, "ip", record
, &function
, 1))
113 return trace_seq_putc(s
, '!');
115 func
= pevent_find_function(pevent
, function
);
117 if (pevent_get_field_val(s
, event
, "parent_ip", record
, &pfunction
, 1))
118 return trace_seq_putc(s
, '!');
120 parent
= pevent_find_function(pevent
, pfunction
);
122 index
= add_and_get_index(parent
, func
, record
->cpu
);
124 trace_seq_printf(s
, "%*s", index
*3, "");
127 trace_seq_printf(s
, "%s", func
);
129 trace_seq_printf(s
, "0x%llx", function
);
131 trace_seq_printf(s
, " <-- ");
133 trace_seq_printf(s
, "%s", parent
);
135 trace_seq_printf(s
, "0x%llx", pfunction
);
140 int PEVENT_PLUGIN_LOADER(struct pevent
*pevent
)
142 pevent_register_event_handler(pevent
, -1, "ftrace", "function",
143 function_handler
, NULL
);
147 void PEVENT_PLUGIN_UNLOADER(struct pevent
*pevent
)
151 pevent_unregister_event_handler(pevent
, -1, "ftrace", "function",
152 function_handler
, NULL
);
154 for (i
= 0; i
<= cpus
; i
++) {
155 for (x
= 0; x
< fstack
[i
].size
&& fstack
[i
].stack
[x
]; x
++)
156 free(fstack
[i
].stack
[x
]);
157 free(fstack
[i
].stack
);