No more build dependency on the babeltrace tree.
Perf counters handling redesigned to suit the new API.
Signed-off-by: Julien Desfossez <julien.desfossez@efficios.com>
newproc->birth = timestamp;
newproc->process_files_table = g_ptr_array_new();
newproc->threads = g_ptr_array_new();
- newproc->perf = g_hash_table_new(g_direct_hash, g_direct_equal);
+ newproc->perf = g_hash_table_new(g_str_hash, g_str_equal);
newproc->iostream = g_new0(struct iostream, 1);
newproc->iostream->ret_read = 0;
newproc->iostream->ret_write = 0;
newcpu = g_new0(struct cputime, 1);
newcpu->id = cpu;
newcpu->current_task = NULL;
- newcpu->perf = g_hash_table_new(g_direct_hash, g_direct_equal);
+ newcpu->perf = g_hash_table_new(g_str_hash, g_str_equal);
g_ptr_array_add(lttngtop.cpu_table, newcpu);
newperf->count = ((struct perfcounter *) value)->count;
newperf->visible = ((struct perfcounter *) value)->visible;
newperf->sort = ((struct perfcounter *) value)->sort;
- g_hash_table_insert((GHashTable *) new_table, key, newperf);
+ g_hash_table_insert((GHashTable *) new_table, strdup(key), newperf);
}
void rotate_perfcounter() {
dst->process_table = g_ptr_array_new();
dst->files_table = g_ptr_array_new();
dst->cpu_table = g_ptr_array_new();
- dst->perf_list = g_hash_table_new(g_direct_hash, g_direct_equal);
+ dst->perf_list = g_hash_table_new(g_str_hash, g_str_equal);
rotate_cputime(end);
new->threads = g_ptr_array_new();
new->comm = strdup(tmp->comm);
new->process_files_table = g_ptr_array_new();
- new->perf = g_hash_table_new(g_direct_hash, g_direct_equal);
+ new->perf = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_foreach(tmp->perf, copy_perf_counter, new->perf);
new->iostream = g_new0(struct iostream, 1);
memcpy(new->iostream, tmp->iostream, sizeof(struct iostream));
/* compute the stream speed */
- if (end - start != 0)
- {
- time = (end - start)/NSEC_PER_SEC;
- new->iostream->ret_read = new->iostream->ret_read/(time);
- new->iostream->ret_write = new->iostream->ret_write/(time);
+ if (end - start != 0) {
+ time = (end - start) / NSEC_PER_SEC;
+ new->iostream->ret_read = new->iostream->ret_read / time;
+ new->iostream->ret_write = new->iostream->ret_write / time;
}
for (j = 0; j < tmp->process_files_table->len; j++) {
*/
if (tmp->death > 0 && tmp->death < end) {
g_ptr_array_remove(lttngtop.process_table, tmp);
+ /* FIXME : TRUE does not mean clears the object in it */
g_ptr_array_free(tmp->threads, TRUE);
free(tmp->comm);
g_ptr_array_free(tmp->process_files_table, TRUE);
+ /* FIXME : clear elements */
g_hash_table_destroy(tmp->perf);
g_free(tmp);
}
tmpcpu = g_ptr_array_index(lttngtop.cpu_table, i);
newcpu = g_new0(struct cputime, 1);
memcpy(newcpu, tmpcpu, sizeof(struct cputime));
- newcpu->perf = g_hash_table_new(g_direct_hash, g_direct_equal);
+ newcpu->perf = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_foreach(tmpcpu->perf, copy_perf_counter, newcpu->perf);
/*
* note : we don't care about the current process pointer in the copy
*/
g_ptr_array_add(dst->cpu_table, newcpu);
}
+ /* FIXME : better algo */
/* create the threads index if required */
for (i = 0; i < dst->process_table->len; i++) {
tmp = g_ptr_array_index(dst->process_table, i);
int header_offset = 2;
int perf_row = 40;
struct perfcounter *perfn1, *perfn2;
- GList *perflist;
char *perf_key = NULL;
int value;
+ GHashTableIter iter;
+ gpointer key;
set_window_title(center, "Perf Top");
wattron(center, A_BOLD);
mvwprintw(center, 1, 22, "NAME");
perf_row = 40;
- perflist = g_list_first(g_hash_table_get_keys(data->perf_list));
- while (perflist) {
- perfn1 = g_hash_table_lookup(data->perf_list, perflist->data);
- /* + 6 to strip the "_perf_" prefix */
+ g_hash_table_iter_init(&iter, data->perf_list);
+ while (g_hash_table_iter_next (&iter, &key, (gpointer) &perfn1)) {
if (perfn1->visible) {
+ /* + 6 to strip the "_perf_" prefix */
mvwprintw(center, 1, perf_row, "%s",
- (char *) perflist->data + 6);
+ (char *) key + 6);
perf_row += 20;
}
if (perfn1->sort) {
- perf_key = (char *) perflist->data;
+ perf_key = (char *) key;
}
- perflist = g_list_next(perflist);
}
+
wattroff(center, A_BOLD);
g_ptr_array_sort_with_data(data->process_table, sort_perf, perf_key);
+
for (i = 0; i < data->process_table->len &&
nblinedisplayed < max_center_lines; i++) {
- GList *perf_keys;
tmp = g_ptr_array_index(data->process_table, i);
if (current_line == selected_line) {
mvwprintw(center, current_line + header_offset, 11, "%d", tmp->tid);
mvwprintw(center, current_line + header_offset, 22, "%s", tmp->comm);
- /* FIXME : sometimes there is a segfault here, I have no idea why :-( */
- perf_keys = g_hash_table_get_keys(data->perf_list);
- if (perf_keys)
- perflist = g_list_first(perf_keys);
- else
- perflist = NULL;
+ g_hash_table_iter_init(&iter, data->perf_list);
perf_row = 40;
- j = 0;
- while (perflist) {
- j++;
- perfn1 = g_hash_table_lookup(data->perf_list, perflist->data);
- if (!perfn1) {
- perflist = g_list_next(perflist);
- continue;
- }
+ while (g_hash_table_iter_next (&iter, &key, (gpointer) &perfn1)) {
if (perfn1->visible) {
- perfn2 = g_hash_table_lookup(tmp->perf, perflist->data);
+ perfn2 = g_hash_table_lookup(tmp->perf, (char *) key);
if (perfn2)
value = perfn2->count;
else
mvwprintw(center, current_line + header_offset, perf_row, "%d", value);
perf_row += 20;
}
- perflist = g_list_next(perflist);
}
wattroff(center, COLOR_PAIR(5));
#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);
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) {
/* 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:
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)
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);
quit = 1;
pthread_join(display_thread, NULL);
+ pthread_join(timer_thread, NULL);
end:
+ bt_context_put(bt_ctx);
return 0;
}
};
struct iostream {
- struct syscalls *syscall_info; /* NULL if there is no waiting for an exit_syscall */
- unsigned long ret_read; /* value returned by an I/O syscall_exit for a sys_read*/
- unsigned long ret_write; /* value returned by an I/O syscall_exit for a sys_write*/
- unsigned long ret_total;
+ struct syscalls *syscall_info; /* NULL if there is no waiting for an exit_syscall */
+ unsigned long ret_read; /* value returned by an I/O syscall_exit for a sys_read*/
+ unsigned long ret_write; /* value returned by an I/O syscall_exit for a sys_write*/
+ unsigned long ret_total;
};
#endif /* LTTNGTOPTYPES_H */