@@ -1134,55 +1134,60 @@ out:
return peer_handle;
}
-/** Initialize the FTRACE data input (from file). */
-int kshark_tep_init_input(struct kshark_data_stream *stream,
- const char *file)
+static int kshark_tep_init_stream(struct kshark_context *kshark_ctx,
+ struct kshark_data_stream *stream,
+ const char *file,
+ struct kshark_data_stream *parent,
+ int instance)
{
- struct kshark_context *kshark_ctx = NULL;
struct tepdata_handle *tep_handle;
- struct kshark_plugin_list *plugin;
+ struct tepdata_handle *tep_parent;
struct tracecmd_input *merge_peer;
+ struct kshark_plugin_list *plugin;
struct tep_event *event;
int i, n_tep_plugins;
int ret;
-
- if (!kshark_instance(&kshark_ctx) || !init_thread_seq())
- return -EEXIST;
-
- /*
- * Turn off function trace indent and turn on show parent
- * if possible.
- */
- tep_plugin_add_option("ftrace:parent", "1");
- tep_plugin_add_option("ftrace:indent", "0");
+ char *name;
tep_handle = calloc(1, sizeof(*tep_handle));
if (!tep_handle)
return -EFAULT;
- /** Open the tracing file, parse headers and create trace input context */
- tep_handle->input = tracecmd_open_head(file);
- if (!tep_handle->input) {
- free(tep_handle);
- stream->interface.handle = NULL;
- return -EEXIST;
+ if (!parent || instance < 0) {
+ /** Open the tracing file, parse headers and create trace input context */
+ tep_handle->input = tracecmd_open_head(file);
+ if (!tep_handle->input) {
+ free(tep_handle);
+ stream->interface.handle = NULL;
+ return -EEXIST;
+ }
+ /** Find a merge peer from the same tracing session */
+ merge_peer = kshark_tep_find_merge_peer(kshark_ctx, tep_handle->input);
+ if (merge_peer)
+ tracecmd_pair_peer(tep_handle->input, merge_peer);
+
+ /** Read the racing data from the file */
+ ret = tracecmd_init_data(tep_handle->input);
+ name = "top";
+ } else {
+ tep_parent = (struct tepdata_handle *)parent->interface.handle;
+ name = tracecmd_buffer_instance_name(tep_parent->input, instance);
+ stream->file = strdup(file);
+ asprintf(&stream->name, "%s:%s", stream->file, name);
+ tep_handle->input = tracecmd_buffer_instance_handle(tep_parent->input, instance);
+ tracecmd_print_stats(tep_handle->input);
+ if (!tep_handle->input)
+ ret = -1;
+ else
+ ret = 0;
}
- /** Find a merge peer from the same tracing session */
- merge_peer = kshark_tep_find_merge_peer(kshark_ctx, tep_handle->input);
- if (merge_peer)
- tracecmd_pair_peer(tep_handle->input, merge_peer);
-
- /** Read the racing data from the file */
- ret = tracecmd_init_data(tep_handle->input);
-
if (ret < 0) {
tracecmd_close(tep_handle->input);
free(tep_handle);
stream->interface.handle = NULL;
return -EEXIST;
}
-
tep_handle->tep = tracecmd_get_pevent(tep_handle->input);
tep_handle->sched_switch_event_id = -EINVAL;
@@ -1224,8 +1229,65 @@ int kshark_tep_init_input(struct kshark_data_stream *stream,
}
kshark_handle_all_dpis(stream, KSHARK_PLUGIN_INIT);
+ return 0;
+}
+/** Initialize the FTRACE data input (from file). */
+int kshark_tep_init_input(struct kshark_data_stream *stream,
+ const char *file)
+{
+ struct kshark_context *kshark_ctx = NULL;
+ struct kshark_data_stream *child_stream;
+ struct tepdata_handle *tep_handle;
+ int count;
+ int ret;
+ int sd;
+ int i;
+
+ if (!kshark_instance(&kshark_ctx) || !init_thread_seq())
+ return -EEXIST;
+
+ /*
+ * Turn off function trace indent and turn on show parent
+ * if possible.
+ */
+ tep_plugin_add_option("ftrace:parent", "1");
+ tep_plugin_add_option("ftrace:indent", "0");
+
+ ret = kshark_tep_init_stream(kshark_ctx, stream, file, NULL, -1);
+ if (ret < 0)
+ return ret;
+ tep_handle = (struct tepdata_handle *)stream->interface.handle;
+ count = tracecmd_buffer_instances(tep_handle->input);
+ for (i = 0; i < count; i++) {
+ sd = kshark_add_stream(kshark_ctx);
+ if (sd < 0) {
+ ret = sd;
+ goto error;
+ }
+ child_stream = kshark_ctx->stream[sd];
+ if (!child_stream) {
+ ret = -ENOMEM;
+ goto error;
+ }
+ if (pthread_mutex_init(&child_stream->input_mutex, NULL) != 0) {
+ ret = -EAGAIN;
+ goto error;
+ }
+ child_stream->format = KS_TEP_DATA;
+ ret = kshark_tep_init_stream(kshark_ctx, child_stream, file, stream, i);
+ if (ret < 0)
+ goto error;
+ kshark_ctx->n_streams++;
+ }
return 0;
+
+error:
+ tracecmd_close(tep_handle->input);
+ free(tep_handle);
+ stream->interface.handle = NULL;
+ return ret;
+
}
/** Initialize using the locally available tracing events. */