* 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., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
+ * 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.
*/
#define _GNU_SOURCE
#include <babeltrace/babeltrace.h>
#include <babeltrace/ctf/events.h>
#include <babeltrace/ctf/callbacks.h>
+#include <babeltrace/ctf/iterator.h>
#include <fcntl.h>
#include <pthread.h>
#include <popt.h>
#include <errno.h>
#include <sys/types.h>
#include <fts.h>
+#include <assert.h>
#include "lttngtoptypes.h"
#include "cputop.h"
void *refresh_thread(void *p)
{
while (1) {
+ if (quit)
+ return NULL;
sem_wait(&pause_sem);
sem_post(&pause_sem);
sem_post(&timer);
sem_wait(&pause_sem);
copy = g_ptr_array_index(copies, current_display_index);
- if (copy)
- display(current_display_index++);
+ assert(copy);
+ display(current_display_index++);
sem_post(&goodtoupdate);
sem_post(&pause_sem);
if (ret)
goto end;
- ret = malloc(sizeof(struct perfcounter));
- memset(ret, 0, sizeof(struct perfcounter));
+ ret = g_new0(struct perfcounter, 1);
/* by default, make it visible in the UI */
ret->visible = 1;
- g_hash_table_insert(table, (gpointer) name, ret);
+ g_hash_table_insert(table, (gpointer) strdup(name), ret);
global = g_hash_table_lookup(lttngtop.perf_list, (gpointer) name);
if (!global) {
- global = malloc(sizeof(struct perfcounter));
- memset(global, 0, sizeof(struct perfcounter));
+ global = g_new0(struct perfcounter, 1);
memcpy(global, ret, sizeof(struct perfcounter));
/* by default, sort on the first perf context */
if (g_hash_table_size(lttngtop.perf_list) == 0)
global->sort = 1;
- g_hash_table_insert(lttngtop.perf_list, (gpointer) name, global);
+ g_hash_table_insert(lttngtop.perf_list, (gpointer) strdup(name), global);
}
end:
}
}
-void extract_perf_counter_scope(struct bt_ctf_event *event,
- struct definition *scope,
+void extract_perf_counter_scope(const struct bt_ctf_event *event,
+ const struct definition *scope,
struct processtop *proc,
struct cputime *cpu)
{
for (i = 0; i < count; i++) {
const char *name = bt_ctf_field_name(list[i]);
- if (strncmp(name, "_perf_", 6) == 0) {
+ if (strncmp(name, "perf_", 5) == 0) {
int value = bt_ctf_get_uint64(list[i]);
if (bt_ctf_field_get_error())
continue;
return;
}
-void update_perf_counter(struct processtop *proc, struct bt_ctf_event *event)
+void update_perf_counter(struct processtop *proc, const struct bt_ctf_event *event)
{
- struct definition *scope;
- uint64_t cpu_id;
struct cputime *cpu;
+ const struct definition *scope;
- scope = bt_ctf_get_top_level_scope(event, BT_STREAM_PACKET_CONTEXT);
- cpu_id = bt_ctf_get_uint64(bt_ctf_get_field(event, scope, "cpu_id"));
- if (bt_ctf_field_get_error()) {
- fprintf(stderr, "[error] get cpu_id\n");
- goto end;
- }
- cpu = get_cpu(cpu_id);
+ cpu = get_cpu(get_cpu_id(event));
scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
extract_perf_counter_scope(event, scope, proc, cpu);
scope = bt_ctf_get_top_level_scope(event, BT_EVENT_CONTEXT);
extract_perf_counter_scope(event, scope, proc, cpu);
-
-end:
- return;
}
enum bt_cb_ret fix_process_table(struct bt_ctf_event *call_data,
int pid, tid, ppid;
char *comm;
struct processtop *parent, *child;
- struct definition *scope;
unsigned long timestamp;
- /* FIXME : check context pid, tid, ppid and comm */
+ /* FIXME : display nice error when missing context pid, tid, ppid and comm */
timestamp = bt_ctf_get_timestamp(call_data);
if (timestamp == -1ULL)
goto error;
- scope = bt_ctf_get_top_level_scope(call_data, BT_STREAM_EVENT_CONTEXT);
-
- pid = bt_ctf_get_int64(bt_ctf_get_field(call_data, scope, "_pid"));
- if (bt_ctf_field_get_error()) {
+ pid = get_context_pid(call_data);
+ if (pid == -1ULL) {
// fprintf(stderr, "Missing pid context info\n");
goto error;
}
- tid = bt_ctf_get_int64(bt_ctf_get_field(call_data, scope, "_tid"));
- if (bt_ctf_field_get_error()) {
+ tid = get_context_tid(call_data);
+ if (tid == -1ULL) {
// fprintf(stderr, "Missing tid context info\n");
goto error;
}
- ppid = bt_ctf_get_int64(bt_ctf_get_field(call_data, scope, "_ppid"));
- if (bt_ctf_field_get_error()) {
+ ppid = get_context_ppid(call_data);
+ if (ppid == -1ULL) {
// fprintf(stderr, "Missing ppid context info\n");
goto error;
}
- comm = bt_ctf_get_char_array(bt_ctf_get_field(call_data, scope, "_procname"));
- if (bt_ctf_field_get_error()) {
+ comm = get_context_comm(call_data);
+ if (!comm) {
// fprintf(stderr, "Missing procname context info\n");
goto error;
}
void init_lttngtop()
{
copies = g_ptr_array_new();
- lttngtop.perf_list = g_hash_table_new(g_direct_hash, g_direct_equal);
+ lttngtop.perf_list = g_hash_table_new(g_str_hash, g_str_equal);
sem_init(&goodtodisplay, 0, 0);
sem_init(&goodtoupdate, 0, 1);
sem_init(&pause_sem, 0, 1);
sem_init(&end_trace_sem, 0, 0);
+ reset_global_counters();
+ lttngtop.nbproc = 0;
+ lttngtop.nbthreads = 0;
+ lttngtop.nbfiles = 0;
+
lttngtop.process_table = g_ptr_array_new();
lttngtop.files_table = g_ptr_array_new();
lttngtop.cpu_table = g_ptr_array_new();
}
-void usage(FILE *fd)
+void usage(FILE *fp)
{
-
+ fprintf(fp, "LTTngTop %s\n\n", VERSION);
+ fprintf(fp, "Usage : lttngtop /path/to/trace\n");
}
/*
{
struct bt_ctf_iter *iter;
struct bt_iter_pos begin_pos;
- struct bt_ctf_event *event;
+ const struct bt_ctf_event *event;
int ret = 0;
begin_pos.type = BT_SEEK_BEGIN;
bt_ctf_iter_add_callback(iter,
g_quark_from_static_string("sched_process_free"),
NULL, 0, handle_sched_process_free, NULL, NULL, NULL);
+ /* to get all the process from the statedumps */
+ bt_ctf_iter_add_callback(iter,
+ g_quark_from_static_string(
+ "lttng_statedump_process_state"),
+ NULL, 0, handle_statedump_process_state,
+ NULL, NULL, NULL);
/* for IO top */
bt_ctf_iter_add_callback(iter,
bt_ctf_iter_add_callback(iter,
g_quark_from_static_string("sys_read"),
NULL, 0, handle_sys_read, NULL, NULL, NULL);
+ bt_ctf_iter_add_callback(iter,
+ g_quark_from_static_string("sys_open"),
+ NULL, 0, handle_sys_open, NULL, NULL, NULL);
+ bt_ctf_iter_add_callback(iter,
+ g_quark_from_static_string("sys_close"),
+ NULL, 0, handle_sys_close, NULL, NULL, NULL);
+ bt_ctf_iter_add_callback(iter,
+ g_quark_from_static_string(
+ "lttng_statedump_file_descriptor"),
+ NULL, 0, handle_statedump_file_descriptor,
+ NULL, NULL, NULL);
+
while ((event = bt_ctf_iter_read_event(iter)) != NULL) {
ret = bt_iter_next(bt_ctf_get_iter(iter));
if (ret < 0)
sem_wait(&end_trace_sem);
end_iter:
- bt_iter_destroy(bt_ctf_get_iter(iter));
+ bt_ctf_iter_destroy(iter);
}
/*
quit = 1;
pthread_join(display_thread, NULL);
+ pthread_join(timer_thread, NULL);
end:
+ bt_context_put(bt_ctx);
return 0;
}