X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=src%2Fcputop.cpp;fp=src%2Fcputop.cpp;h=4fde9a807c8d3613d954588f50f81ad45b443329;hb=715cf83c121d2aeac7ae030d49ff5a31bd6b9ac5;hp=0000000000000000000000000000000000000000;hpb=62895477c7e60525e63e9e5117f92b34d467d0e6;p=lttngtop.git diff --git a/src/cputop.cpp b/src/cputop.cpp new file mode 100644 index 0000000..4fde9a8 --- /dev/null +++ b/src/cputop.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2011-2012 Julien Desfossez + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +extern "C" { +#include +} + +#include "lttngtoptypes.h" +#include "common.h" +#include "cputop.h" + +void update_cputop_data(unsigned long timestamp, int64_t cpu, + int prev_pid, int next_pid, char *prev_comm, char *next_comm) +{ + Quark cpu_quark; + Quark current_task_quark; + bool current_task_found; + int current_task_pid; + int current_task_tid; + unsigned long elapsed; + unsigned long task_start; + bool current_task_threadparent_found; + Quark current_task_threadparent; + + cpu_quark = get_cpu(cpu, timestamp); + current_task_found = get_current_attribute_value_quark(&cpu_quark, + "current_task", current_task_quark); + + if (current_task_found) { + get_current_attribute_value_int(¤t_task_quark, "pid", + current_task_pid); + if (current_task_pid == prev_pid) { + get_current_attribute_value_ulong(&cpu_quark, + "task_start", task_start); + elapsed = timestamp - task_start; + increase_attribute(timestamp, ¤t_task_quark, + "totalcpunsec", elapsed); + increase_attribute(timestamp, ¤t_task_quark, + "threadstotalcpunsec", elapsed); + get_current_attribute_value_int(¤t_task_quark, + "tid", current_task_tid); + if (current_task_tid != current_task_pid) { + current_task_threadparent_found = + get_current_attribute_value_quark( + ¤t_task_quark, + "threadparent", + current_task_threadparent); + if (current_task_threadparent_found) + increase_attribute(timestamp, + ¤t_task_threadparent, + "threadstotalcpuns", elapsed); + } + } + } + + if (next_pid != 0) + modify_attribute(timestamp, &cpu_quark, "current_task", + get_proc(next_pid, next_comm, timestamp)); + else + nullify_attribute(timestamp, &cpu_quark, "current_task"); + + modify_attribute(timestamp, &cpu_quark, "task_start", timestamp); +} + +enum bt_cb_ret handle_sched_switch(struct bt_ctf_event *call_data, + void *private_data) +{ + const struct definition *scope; + unsigned long timestamp; + uint64_t cpu_id; + char *prev_comm, *next_comm; + int prev_tid, next_tid; + + timestamp = bt_ctf_get_timestamp(call_data); + if (timestamp == -1ULL) + goto error; + + scope = bt_ctf_get_top_level_scope(call_data, + BT_EVENT_FIELDS); + prev_comm = bt_ctf_get_char_array(bt_ctf_get_field(call_data, + scope, "_prev_comm")); + if (bt_ctf_field_get_error()) { + fprintf(stderr, "Missing prev_comm context info\n"); + goto error; + } + + next_comm = bt_ctf_get_char_array(bt_ctf_get_field(call_data, + scope, "_next_comm")); + if (bt_ctf_field_get_error()) { + fprintf(stderr, "Missing next_comm context info\n"); + goto error; + } + + prev_tid = bt_ctf_get_int64(bt_ctf_get_field(call_data, + scope, "_prev_tid")); + if (bt_ctf_field_get_error()) { + fprintf(stderr, "Missing prev_tid context info\n"); + goto error; + } + + next_tid = bt_ctf_get_int64(bt_ctf_get_field(call_data, + scope, "_next_tid")); + if (bt_ctf_field_get_error()) { + fprintf(stderr, "Missing next_tid context info\n"); + goto error; + } + + cpu_id = get_cpu_id(call_data); + + update_cputop_data(timestamp, cpu_id, prev_tid, next_tid, + prev_comm, next_comm); + + return BT_CB_OK; + +error: + return BT_CB_ERROR_STOP; +} + +enum bt_cb_ret handle_sched_process_free(struct bt_ctf_event *call_data, + void *private_data) +{ + const struct definition *scope; + unsigned long timestamp; + char *comm; + int tid; + + timestamp = bt_ctf_get_timestamp(call_data); + if (timestamp == -1ULL) + goto error; + + scope = bt_ctf_get_top_level_scope(call_data, + BT_EVENT_FIELDS); + comm = bt_ctf_get_char_array(bt_ctf_get_field(call_data, + scope, "_comm")); + if (bt_ctf_field_get_error()) { + fprintf(stderr, "Missing procname context info\n"); + goto error; + } + + tid = bt_ctf_get_int64(bt_ctf_get_field(call_data, + scope, "_tid")); + if (bt_ctf_field_get_error()) { + fprintf(stderr, "Missing tid field\n"); + goto error; + } + + death_proc(tid, comm, timestamp); + + return BT_CB_OK; + +error: + return BT_CB_ERROR_STOP; + +} +