X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Flttv%2Fmodules%2Fgui%2Fcontrolflow%2Fprocesslist.c;h=4ecef3d2cb452dbca8e44f35efe53287144ab2a4;hb=4e4d11b3b1db254446f6cad04b3c3fa9b574851f;hp=93e730aeae5e20ee3772b22d93d0aaeaa58b919e;hpb=e8d11122b46e7e2922e65825623c760f84a4d34f;p=lttv.git diff --git a/ltt/branches/poly/lttv/modules/gui/controlflow/processlist.c b/ltt/branches/poly/lttv/modules/gui/controlflow/processlist.c index 93e730ae..4ecef3d2 100644 --- a/ltt/branches/poly/lttv/modules/gui/controlflow/processlist.c +++ b/ltt/branches/poly/lttv/modules/gui/controlflow/processlist.c @@ -16,255 +16,295 @@ * MA 02111-1307, USA. */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include #include +#include #include "processlist.h" +#include "drawing.h" #include "drawitem.h" #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format) #define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format) +/* Preallocated Size of the index_to_pixmap array */ +#define ALLOCATE_PROCESSES 1000 /***************************************************************************** * Methods to synchronize process list * *****************************************************************************/ -//static inline guint get_cpu_number_from_name(GQuark name); - -/* Enumeration of the columns */ -enum -{ - PROCESS_COLUMN, - PID_COLUMN, - PPID_COLUMN, - CPU_COLUMN, - BIRTH_S_COLUMN, - BIRTH_NS_COLUMN, - TRACE_COLUMN, - N_COLUMNS -}; - gint process_sort_func ( GtkTreeModel *model, GtkTreeIter *it_a, GtkTreeIter *it_b, gpointer user_data) { - GValue a, b; + gchar *a_name; + guint a_pid, a_ppid, a_cpu; + gulong a_birth_s, a_birth_ns; + gulong a_trace; + + gchar *b_name; + guint b_pid, b_ppid, b_cpu; + gulong b_birth_s, b_birth_ns; + gulong b_trace; + + gtk_tree_model_get(model, + it_a, + 0, &a_name, + 1, &a_pid, + 2, &a_ppid, + 3, &a_cpu, + 4, &a_birth_s, + 5, &a_birth_ns, + 6, &a_trace, + -1); + + gtk_tree_model_get(model, + it_b, + 0, &b_name, + 1, &b_pid, + 2, &b_ppid, + 3, &b_cpu, + 4, &b_birth_s, + 5, &b_birth_ns, + 6, &b_trace, + -1); - memset(&a, 0, sizeof(GValue)); - memset(&b, 0, sizeof(GValue)); /* Order by PID */ - gtk_tree_model_get_value( model, - it_a, - PID_COLUMN, - &a); - - gtk_tree_model_get_value( model, - it_b, - PID_COLUMN, - &b); - - if(G_VALUE_TYPE(&a) == G_TYPE_UINT - && G_VALUE_TYPE(&b) == G_TYPE_UINT ) - { - { + if(a_pid == 0 && b_pid == 0) { + /* If 0, order by CPU */ + if(a_cpu > b_cpu) return 1; + if(a_cpu < b_cpu) return -1; - if(g_value_get_uint(&a) == 0 && g_value_get_uint(&b) == 0) { + } else { /* if not 0, order by pid */ - GValue cpua, cpub; + if(a_pid > b_pid) return 1; + if(a_pid < b_pid) return -1; + } - memset(&cpua, 0, sizeof(GValue)); - memset(&cpub, 0, sizeof(GValue)); - - /* If 0, order by CPU */ - gtk_tree_model_get_value( model, - it_a, - CPU_COLUMN, - &cpua); + /* Order by birth second */ - gtk_tree_model_get_value( model, - it_b, - CPU_COLUMN, - &cpub); - - if(G_VALUE_TYPE(&cpua) == G_TYPE_UINT - && G_VALUE_TYPE(&cpub) == G_TYPE_UINT ) - { - if(g_value_get_uint(&cpua) > g_value_get_uint(&cpub)) - { - g_value_unset(&cpua); - g_value_unset(&cpub); - return 1; - } - if(g_value_get_uint(&cpua) < g_value_get_uint(&cpub)) - { - g_value_unset(&cpua); - g_value_unset(&cpub); - return 0; - } - } - - g_value_unset(&cpua); - g_value_unset(&cpub); - - } else { /* if not 0, order by pid */ - - if(g_value_get_uint(&a) > g_value_get_uint(&b)) - { - g_value_unset(&a); - g_value_unset(&b); - return 1; - } - if(g_value_get_uint(&a) < g_value_get_uint(&b)) - { - g_value_unset(&a); - g_value_unset(&b); - return 0; - } - } - } - } + if(a_birth_s > b_birth_s) return 1; + if(a_birth_s < b_birth_s) return -1; + - g_value_unset(&a); - g_value_unset(&b); + /* Order by birth nanosecond */ + if(a_birth_ns > b_birth_ns) return 1; + if(a_birth_ns < b_birth_ns) return -1; + + /* Order by trace_num */ + if(a_trace > b_trace) return 1; + if(a_trace < b_trace) return -1; + return 0; - /* Order by birth second */ - gtk_tree_model_get_value( model, - it_a, - BIRTH_S_COLUMN, - &a); +} - gtk_tree_model_get_value( model, - it_b, - BIRTH_S_COLUMN, - &b); +static guint process_list_hash_fct(gconstpointer key) +{ + guint pid = ((const ProcessInfo*)key)->pid; + return ((pid>>8 ^ pid>>4 ^ pid>>2 ^ pid) ^ ((const ProcessInfo*)key)->cpu); +} +/* If hash is good, should be different */ +static gboolean process_list_equ_fct(gconstpointer a, gconstpointer b) +{ + const ProcessInfo *pa = (const ProcessInfo*)a; + const ProcessInfo *pb = (const ProcessInfo*)b; + + gboolean ret = TRUE; + + if(likely(pa->pid != pb->pid)) + ret = FALSE; + else if(likely((pa->pid == 0 && (pa->cpu != pb->cpu)))) + ret = FALSE; + else if(unlikely(ltt_time_compare(pa->birth, pb->birth) != 0)) + ret = FALSE; + else if(unlikely(pa->trace_num != pb->trace_num)) + ret = FALSE; + + return ret; +} - if(G_VALUE_TYPE(&a) == G_TYPE_ULONG - && G_VALUE_TYPE(&b) == G_TYPE_ULONG ) - { - if(g_value_get_ulong(&a) > g_value_get_ulong(&b)) - { - g_value_unset(&a); - g_value_unset(&b); - return 1; - } - if(g_value_get_ulong(&a) < g_value_get_ulong(&b)) - { - g_value_unset(&a); - g_value_unset(&b); - return 0; - } +void destroy_hash_key(gpointer key); - } +void destroy_hash_data(gpointer data); - g_value_unset(&a); - g_value_unset(&b); - /* Order by birth nanosecond */ - gtk_tree_model_get_value( model, - it_a, - BIRTH_NS_COLUMN, - &a); +static void update_index_to_pixmap_each(ProcessInfo *key, + HashedProcessData *value, + ProcessList *process_list) +{ + guint array_index = processlist_get_index_from_data(process_list, value); + + g_assert(array_index < process_list->index_to_pixmap->len); - gtk_tree_model_get_value( model, - it_b, - BIRTH_NS_COLUMN, - &b); + GdkPixmap **pixmap = + (GdkPixmap**)&g_ptr_array_index(process_list->index_to_pixmap, array_index); + *pixmap = value->pixmap; +} - if(G_VALUE_TYPE(&a) == G_TYPE_ULONG - && G_VALUE_TYPE(&b) == G_TYPE_ULONG ) - { - if(g_value_get_ulong(&a) > g_value_get_ulong(&b)) - { - g_value_unset(&a); - g_value_unset(&b); - return 1; - } - if(g_value_get_ulong(&a) < g_value_get_ulong(&b)) - { - g_value_unset(&a); - g_value_unset(&b); - return 0; - } - } - - g_value_unset(&a); - g_value_unset(&b); +void update_index_to_pixmap(ProcessList *process_list) +{ + g_ptr_array_set_size(process_list->index_to_pixmap, + g_hash_table_size(process_list->process_hash)); + g_hash_table_foreach(process_list->process_hash, + (GHFunc)update_index_to_pixmap_each, + process_list); +} - /* Order by trace_num */ - gtk_tree_model_get_value( model, - it_a, - TRACE_COLUMN, - &a); - - gtk_tree_model_get_value( model, - it_b, - TRACE_COLUMN, - &b); - - if(G_VALUE_TYPE(&a) == G_TYPE_ULONG - && G_VALUE_TYPE(&b) == G_TYPE_ULONG ) - { - if(g_value_get_ulong(&a) > g_value_get_ulong(&b)) - { - g_value_unset(&a); - g_value_unset(&b); - return 1; - } - if(g_value_get_ulong(&a) < g_value_get_ulong(&b)) - { - g_value_unset(&a); - g_value_unset(&b); - return 0; - } - } +static void update_pixmap_size_each(ProcessInfo *key, + HashedProcessData *value, + guint width) +{ + GdkPixmap *old_pixmap = value->pixmap; - return 0; + value->pixmap = + gdk_pixmap_new(old_pixmap, + width, + value->height, + -1); + gdk_pixmap_unref(old_pixmap); } -static guint process_list_hash_fct(gconstpointer key) + +void update_pixmap_size(ProcessList *process_list, guint width) { - guint pid = ((ProcessInfo*)key)->pid; - return ((pid>>8 ^ pid>>4 ^ pid>>2 ^ pid) ^ ((ProcessInfo*)key)->cpu); + g_hash_table_foreach(process_list->process_hash, + (GHFunc)update_pixmap_size_each, + (gpointer)width); } -static gboolean process_list_equ_fct(gconstpointer a, gconstpointer b) + +typedef struct _CopyPixmap { + GdkDrawable *dest; + GdkGC *gc; + GdkDrawable *src; + gint xsrc, ysrc, xdest, ydest, width, height; +} CopyPixmap; + +static void copy_pixmap_region_each(ProcessInfo *key, + HashedProcessData *value, + CopyPixmap *cp) { - const ProcessInfo *pa = (const ProcessInfo*)a; - const ProcessInfo *pb = (const ProcessInfo*)b; + GdkPixmap *src = cp->src; + GdkPixmap *dest = cp->dest; - if(pa->pid != pb->pid) - return 0; + if(dest == NULL) + dest = value->pixmap; + if(src == NULL) + src = value->pixmap; + + gdk_draw_drawable (dest, + cp->gc, + src, + cp->xsrc, cp->ysrc, + cp->xdest, cp->ydest, + cp->width, cp->height); +} + + - if((pa->pid == 0 && (pa->cpu != pb->cpu))) - return 0; - if(pa->birth.tv_sec != pb->birth.tv_sec) - return 0; +void copy_pixmap_region(ProcessList *process_list, GdkDrawable *dest, + GdkGC *gc, GdkDrawable *src, + gint xsrc, gint ysrc, + gint xdest, gint ydest, gint width, gint height) +{ + CopyPixmap cp = { dest, gc, src, xsrc, ysrc, xdest, ydest, width, height }; + + g_hash_table_foreach(process_list->process_hash, + (GHFunc)copy_pixmap_region_each, + &cp); +} + - if(pa->birth.tv_nsec != pb->birth.tv_nsec) - return 0; - if(pa->trace_num != pb->trace_num) - return 0; +typedef struct _RectanglePixmap { + gboolean filled; + gint x, y, width, height; + GdkGC *gc; +} RectanglePixmap; - return 1; +static void rectangle_pixmap_each(ProcessInfo *key, + HashedProcessData *value, + RectanglePixmap *rp) +{ + if(rp->height == -1) + rp->height = value->height; + + gdk_draw_rectangle (value->pixmap, + rp->gc, + rp->filled, + rp->x, rp->y, + rp->width, rp->height); } -void destroy_hash_key(gpointer key); -void destroy_hash_data(gpointer data); + + +void rectangle_pixmap(ProcessList *process_list, GdkGC *gc, + gboolean filled, gint x, gint y, gint width, gint height) +{ + RectanglePixmap rp = { filled, x, y, width, height, gc }; + + g_hash_table_foreach(process_list->process_hash, + (GHFunc)rectangle_pixmap_each, + &rp); +} + + +/* Renders each pixmaps into on big drawable */ +void copy_pixmap_to_screen(ProcessList *process_list, + GdkDrawable *dest, + GdkGC *gc, + gint x, gint y, + gint width, gint height) +{ + if(process_list->index_to_pixmap->len == 0) return; + guint cell_height = process_list->cell_height; + + /* Get indexes */ + gint begin = floor(y/(double)cell_height); + gint end = MIN(ceil((y+height)/(double)cell_height), + process_list->index_to_pixmap->len); + gint i; + + for(i=begin; iindex_to_pixmap->len); + /* Render the pixmap to the screen */ + GdkPixmap *pixmap = + (GdkPixmap*)g_ptr_array_index(process_list->index_to_pixmap, i); + + gdk_draw_drawable (dest, + gc, + pixmap, + x, 0, + x, i*cell_height, + width, cell_height); + + } + + +} + + + + + @@ -277,7 +317,6 @@ ProcessList *processlist_construct(void) ProcessList* process_list = g_new(ProcessList,1); process_list->number_of_process = 0; - process_list->cell_height_cache = -1; process_list->current_hash_data = NULL; @@ -295,20 +334,22 @@ ProcessList *processlist_construct(void) process_list->process_list_widget = gtk_tree_view_new_with_model (GTK_TREE_MODEL (process_list->list_store)); + g_object_unref (G_OBJECT (process_list->list_store)); - gtk_tree_sortable_set_sort_func( + gtk_tree_sortable_set_default_sort_func( GTK_TREE_SORTABLE(process_list->list_store), - PID_COLUMN, process_sort_func, NULL, NULL); - + + gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE(process_list->list_store), - PID_COLUMN, + GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING); - + + process_list->process_hash = g_hash_table_new_full( process_list_hash_fct, process_list_equ_fct, destroy_hash_key, destroy_hash_data @@ -322,6 +363,21 @@ ProcessList *processlist_construct(void) * cell_renderer to the first column of the model */ /* Columns alignment : 0.0 : Left 0.5 : Center 1.0 : Right */ renderer = gtk_cell_renderer_text_new (); + process_list->renderer = renderer; + + gtk_cell_renderer_get_size(renderer, + GTK_WIDGET(process_list->process_list_widget), + NULL, + NULL, + NULL, + NULL, + &process_list->cell_height); + + guint ypad; + g_object_get(G_OBJECT(renderer), "ypad", &ypad, NULL); + + process_list->cell_height += ypad; + column = gtk_tree_view_column_new_with_attributes ( "Process", renderer, "text", @@ -393,6 +449,8 @@ ProcessList *processlist_construct(void) process_list, (GDestroyNotify)processlist_destroy); + process_list->index_to_pixmap = g_ptr_array_sized_new(ALLOCATE_PROCESSES); + return process_list; } @@ -401,6 +459,7 @@ void processlist_destroy(ProcessList *process_list) g_debug("processlist_destroy %p", process_list); g_hash_table_destroy(process_list->process_hash); process_list->process_hash = NULL; + g_ptr_array_free(process_list->index_to_pixmap, TRUE); g_free(process_list); g_debug("processlist_destroy end"); @@ -415,10 +474,11 @@ static gboolean remove_hash_item(ProcessInfo *process_info, iter = hashed_process_data->y_iter; gtk_list_store_remove (process_list->list_store, &iter); + gdk_pixmap_unref(hashed_process_data->pixmap); - if(process_list->current_hash_data != NULL) { - if(hashed_process_data == - process_list->current_hash_data[process_info->cpu]) + if(likely(process_list->current_hash_data != NULL)) { + if(likely(hashed_process_data == + process_list->current_hash_data[process_info->cpu])) process_list->current_hash_data[process_info->cpu] = NULL; } return TRUE; /* remove the element from the hash table */ @@ -432,6 +492,7 @@ void processlist_clear(ProcessList *process_list) (GHRFunc)remove_hash_item, (gpointer)process_list); process_list->number_of_process = 0; + update_index_to_pixmap(process_list); } @@ -452,6 +513,7 @@ void destroy_hash_data(gpointer data) } int processlist_add( ProcessList *process_list, + Drawing_t *drawing, guint pid, guint cpu, guint ppid, @@ -492,7 +554,7 @@ int processlist_add( ProcessList *process_list, hashed_process_data->x.under_used = FALSE; hashed_process_data->x.under_marked = FALSE; hashed_process_data->next_good_time = ltt_time_zero; - + /* Add a new row to the model */ gtk_list_store_append ( process_list->list_store, &hashed_process_data->y_iter); @@ -506,27 +568,39 @@ int processlist_add( ProcessList *process_list, BIRTH_NS_COLUMN, birth->tv_nsec, TRACE_COLUMN, trace_num, -1); -#if 0 - hashed_process_data->row_ref = gtk_tree_row_reference_new ( - GTK_TREE_MODEL(process_list->list_store), - gtk_tree_model_get_path( - GTK_TREE_MODEL(process_list->list_store), - &iter)); -#endif //0 + //gtk_tree_view_set_model(GTK_TREE_VIEW(process_list->process_list_widget), + // GTK_TREE_MODEL(process_list->list_store)); + //gtk_container_resize_children(GTK_CONTAINER(process_list->process_list_widget)); + g_hash_table_insert(process_list->process_hash, (gpointer)Process_Info, (gpointer)hashed_process_data); - //g_critical ( "iter after : %s", gtk_tree_path_to_string ( - // gtk_tree_model_get_path ( - // GTK_TREE_MODEL(process_list->list_store), - // &iter))); process_list->number_of_process++; - *height = get_cell_height(process_list, - GTK_TREE_VIEW(process_list->process_list_widget)) - * process_list->number_of_process ; + hashed_process_data->height = process_list->cell_height; + + g_assert(hashed_process_data->height != 0); + + *height = hashed_process_data->height * process_list->number_of_process; + + hashed_process_data->pixmap = + gdk_pixmap_new(drawing->drawing_area->window, + drawing->alloc_width, + hashed_process_data->height, + -1); + // Clear the image + gdk_draw_rectangle (hashed_process_data->pixmap, + drawing->drawing_area->style->black_gc, + TRUE, + 0, 0, + drawing->alloc_width, + hashed_process_data->height); + + update_index_to_pixmap(process_list); + + return 0; } @@ -537,7 +611,6 @@ int processlist_remove( ProcessList *process_list, guint trace_num) { ProcessInfo process_info; - gint *path_indices; HashedProcessData *hashed_process_data; GtkTreeIter iter; @@ -550,10 +623,11 @@ int processlist_remove( ProcessList *process_list, process_info.trace_num = trace_num; - if(hashed_process_data = + hashed_process_data = (HashedProcessData*)g_hash_table_lookup( process_list->process_hash, - &process_info)) + &process_info); + if(likely(hashed_process_data != NULL)) { iter = hashed_process_data->y_iter; @@ -562,11 +636,16 @@ int processlist_remove( ProcessList *process_list, g_hash_table_remove(process_list->process_hash, &process_info); - if(process_list->current_hash_data != NULL) { - if(hashed_process_data == process_list->current_hash_data[cpu]) { + if(likely(process_list->current_hash_data != NULL)) { + if(likely(hashed_process_data == process_list->current_hash_data[cpu])) { process_list->current_hash_data[cpu] = NULL; } } + + gdk_pixmap_unref(hashed_process_data->pixmap); + + update_index_to_pixmap(process_list); + process_list->number_of_process--; return 0;