// SPDX-License-Identifier: GPL-2.0-only /* * db-export.c: Support for exporting data suitable for import to a database * Copyright (c) 2014, Intel Corporation.
*/
if (dbe->export_comm) return dbe->export_comm(dbe, comm, thread);
return 0;
}
int db_export__comm(struct db_export *dbe, struct comm *comm, struct thread *thread)
{ if (comm->db_id) return 0;
return __db_export__comm(dbe, comm, thread);
}
/* * Export the "exec" comm. The "exec" comm is the program / application command * name at the time it first executes. It is used to group threads for the same * program. Note that the main thread pid (or thread group id tgid) cannot be * used because it does not change when a new program is exec'ed.
*/ int db_export__exec_comm(struct db_export *dbe, struct comm *comm, struct thread *main_thread)
{ int err;
if (comm->db_id) return 0;
err = __db_export__comm(dbe, comm, main_thread); if (err) return err;
/* * Record the main thread for this comm. Note that the main thread can * have many "exec" comms because there will be a new one every time it * exec's. An "exec" comm however will only ever have 1 main thread. * That is different to any other threads for that same program because * exec() will effectively kill them, so the relationship between the * "exec" comm and non-main threads is 1-to-1. That is why * db_export__comm_thread() is called here for the main thread, but it * is called for non-main threads when they are exported.
*/ return db_export__comm_thread(dbe, comm, main_thread);
}
int db_export__comm_thread(struct db_export *dbe, struct comm *comm, struct thread *thread)
{
u64 db_id;
db_id = ++dbe->comm_thread_last_db_id;
if (dbe->export_comm_thread) return dbe->export_comm_thread(dbe, db_id, comm, thread);
return 0;
}
int db_export__dso(struct db_export *dbe, struct dso *dso, struct machine *machine)
{ if (dso__db_id(dso)) return 0;
dso__set_db_id(dso, ++dbe->dso_last_db_id);
if (dbe->export_dso) return dbe->export_dso(dbe, dso, machine);
return 0;
}
int db_export__symbol(struct db_export *dbe, struct symbol *sym, struct dso *dso)
{
u64 *sym_db_id = symbol__priv(sym);
if (*sym_db_id) return 0;
*sym_db_id = ++dbe->symbol_last_db_id;
if (dbe->export_symbol) return dbe->export_symbol(dbe, sym, dso);
if (!symbol_conf.use_callchain || !sample->callchain) return NULL;
/* * Since the call path tree must be built starting with the root, we * must use ORDER_CALL for call chain resolution, in order to process * the callchain starting with the root node and ending with the leaf.
*/
callchain_param.order = ORDER_CALLER;
cursor = get_tls_callchain_cursor();
err = thread__resolve_callchain(thread, cursor, evsel,
sample, NULL, NULL, PERF_MAX_STACK_DEPTH); if (err) {
callchain_param.order = saved_order; return NULL;
}
callchain_cursor_commit(cursor);
node = callchain_cursor_current(cursor); if (!node) break;
/* * Handle export of symbol and dso for this node by * constructing an addr_location struct and then passing it to * db_ids_from_al() to perform the export.
*/
addr_location__init(&al);
al.sym = node->ms.sym;
al.map = map__get(node->ms.map);
al.maps = maps__get(thread__maps(thread));
al.addr = node->ip;
al.thread = thread__get(thread);
if (al.map && !al.sym)
al.sym = dso__find_symbol(map__dso(al.map), al.addr);
/* Reset the callchain order to its prior value. */
callchain_param.order = saved_order;
if (current == &dbe->cpr->call_path) { /* Bail because the callchain was empty. */ return NULL;
}
return current;
}
int db_export__branch_type(struct db_export *dbe, u32 branch_type, constchar *name)
{ if (dbe->export_branch_type) return dbe->export_branch_type(dbe, branch_type, name);
return 0;
}
staticint db_export__threads(struct db_export *dbe, struct thread *thread, struct thread *main_thread, struct machine *machine, struct comm **comm_ptr)
{ struct comm *comm = NULL; struct comm *curr_comm; int err;
if (main_thread) { /* * A thread has a reference to the main thread, so export the * main thread first.
*/
err = db_export__thread(dbe, main_thread, machine, main_thread); if (err) return err; /* * Export comm before exporting the non-main thread because * db_export__comm_thread() can be called further below.
*/
comm = machine__thread_exec_comm(machine, main_thread); if (comm) {
err = db_export__exec_comm(dbe, comm, main_thread); if (err) return err;
*comm_ptr = comm;
}
}
if (thread != main_thread) { /* * For a non-main thread, db_export__comm_thread() must be * called only if thread has not previously been exported.
*/ bool export_comm_thread = comm && !thread__db_id(thread);
err = db_export__thread(dbe, thread, machine, main_thread); if (err) return err;
if (export_comm_thread) {
err = db_export__comm_thread(dbe, comm, thread); if (err) return err;
}
}
curr_comm = thread__comm(thread); if (curr_comm) return db_export__comm(dbe, curr_comm, thread);
/* * Do not export if both threads are unknown (i.e. not being traced), * or one is unknown and the other is the idle task.
*/ if ((!th_a_id || is_idle_a) && (!th_b_id || is_idle_b)) return 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.