state.c: track softirq raises
[lttv.git] / ltt / branches / poly / lttv / modules / gui / resourceview / eventhooks.c
CommitLineData
9e01e6d4 1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19
20/*****************************************************************************
21 * Hooks to be called by the main window *
22 *****************************************************************************/
23
24
25/* Event hooks are the drawing hooks called during traceset read. They draw the
26 * icons, text, lines and background color corresponding to the events read.
27 *
28 * Two hooks are used for drawing : before_schedchange and after_schedchange hooks. The
29 * before_schedchange is called before the state update that occurs with an event and
30 * the after_schedchange hook is called after this state update.
31 *
32 * The before_schedchange hooks fulfill the task of drawing the visible objects that
33 * corresponds to the data accumulated by the after_schedchange hook.
34 *
35 * The after_schedchange hook accumulates the data that need to be shown on the screen
36 * (items) into a queue. Then, the next before_schedchange hook will draw what that
37 * queue contains. That's the Right Way (TM) of drawing items on the screen,
38 * because we need to draw the background first (and then add icons, text, ...
39 * over it), but we only know the length of a background region once the state
40 * corresponding to it is over, which happens to be at the next before_schedchange
41 * hook.
42 *
43 * We also have a hook called at the end of a chunk to draw the information left
44 * undrawn in each process queue. We use the current time as end of
45 * line/background.
46 */
47
48#ifdef HAVE_CONFIG_H
49#include <config.h>
50#endif
51
52//#define PANGO_ENABLE_BACKEND
53#include <gtk/gtk.h>
54#include <gdk/gdk.h>
55#include <glib.h>
56#include <assert.h>
57#include <string.h>
58#include <stdio.h>
59
60//#include <pango/pango.h>
61
62#include <ltt/event.h>
63#include <ltt/time.h>
9e01e6d4 64#include <ltt/trace.h>
65
66#include <lttv/lttv.h>
67#include <lttv/hook.h>
68#include <lttv/state.h>
69#include <lttvwindow/lttvwindow.h>
70#include <lttvwindow/lttvwindowtraces.h>
71#include <lttvwindow/support.h>
72
73
74#include "eventhooks.h"
75#include "cfv.h"
76#include "processlist.h"
77#include "drawing.h"
78
79
80#define MAX_PATH_LEN 256
81#define STATE_LINE_WIDTH 4
82#define COLLISION_POSITION(height) (((height - STATE_LINE_WIDTH)/2) -3)
83
84extern GSList *g_legend_list;
85
86
87/* Action to do when background computation completed.
88 *
89 * Wait for all the awaited computations to be over.
90 */
91
92static gint background_ready(void *hook_data, void *call_data)
93{
67f72973 94 ControlFlowData *resourceview_data = (ControlFlowData *)hook_data;
9e01e6d4 95 LttvTrace *trace = (LttvTrace*)call_data;
96
67f72973 97 resourceview_data->background_info_waiting--;
9e01e6d4 98
67f72973 99 if(resourceview_data->background_info_waiting == 0) {
9e01e6d4 100 g_message("control flow viewer : background computation data ready.");
101
67f72973 102 drawing_clear(resourceview_data->drawing);
103 processlist_clear(resourceview_data->process_list);
9e01e6d4 104 gtk_widget_set_size_request(
67f72973 105 resourceview_data->drawing->drawing_area,
106 -1, processlist_get_height(resourceview_data->process_list));
107 redraw_notify(resourceview_data, NULL);
9e01e6d4 108 }
109
110 return 0;
111}
112
113
114/* Request background computation. Verify if it is in progress or ready first.
115 * Only for each trace in the tab's traceset.
116 */
67f72973 117static void request_background_data(ControlFlowData *resourceview_data)
9e01e6d4 118{
119 LttvTracesetContext * tsc =
67f72973 120 lttvwindow_get_traceset_context(resourceview_data->tab);
9e01e6d4 121 gint num_traces = lttv_traceset_number(tsc->ts);
122 gint i;
123 LttvTrace *trace;
124 LttvTraceState *tstate;
125
126 LttvHooks *background_ready_hook =
127 lttv_hooks_new();
67f72973 128 lttv_hooks_add(background_ready_hook, background_ready, resourceview_data,
9e01e6d4 129 LTTV_PRIO_DEFAULT);
67f72973 130 resourceview_data->background_info_waiting = 0;
9e01e6d4 131
132 for(i=0;i<num_traces;i++) {
133 trace = lttv_traceset_get(tsc->ts, i);
134 tstate = LTTV_TRACE_STATE(tsc->traces[i]);
135
136 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE
137 && !tstate->has_precomputed_states) {
138
139 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
140 trace) == FALSE) {
141 /* We first remove requests that could have been done for the same
142 * information. Happens when two viewers ask for it before servicing
143 * starts.
144 */
145 if(!lttvwindowtraces_background_request_find(trace, "state"))
146 lttvwindowtraces_background_request_queue(
67f72973 147 main_window_get_widget(resourceview_data->tab), trace, "state");
148 lttvwindowtraces_background_notify_queue(resourceview_data,
9e01e6d4 149 trace,
150 ltt_time_infinite,
151 NULL,
152 background_ready_hook);
67f72973 153 resourceview_data->background_info_waiting++;
9e01e6d4 154 } else { /* in progress */
155
67f72973 156 lttvwindowtraces_background_notify_current(resourceview_data,
9e01e6d4 157 trace,
158 ltt_time_infinite,
159 NULL,
160 background_ready_hook);
67f72973 161 resourceview_data->background_info_waiting++;
9e01e6d4 162 }
163 } else {
164 /* Data ready. By its nature, this viewer doesn't need to have
165 * its data ready hook called there, because a background
166 * request is always linked with a redraw.
167 */
168 }
9e01e6d4 169 }
170
171 lttv_hooks_destroy(background_ready_hook);
172}
173
174
9e01e6d4 175/**
176 * Event Viewer's constructor hook
177 *
178 * This constructor is given as a parameter to the menuitem and toolbar button
179 * registration. It creates the list.
180 * @param tab A pointer to the parent tab.
181 * @return The widget created.
182 */
183GtkWidget *
58a9b31b 184h_resourceview(LttvPlugin *plugin)
9e01e6d4 185{
186 LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
187 Tab *tab = ptab->tab;
188 g_info("h_guicontrolflow, %p", tab);
67f72973 189 ControlFlowData *resourceview_data = resourceview(ptab);
9e01e6d4 190
67f72973 191 resourceview_data->tab = tab;
9e01e6d4 192
193 // Unreg done in the GuiControlFlow_Destructor
194 lttvwindow_register_traceset_notify(tab,
195 traceset_notify,
67f72973 196 resourceview_data);
9e01e6d4 197
198 lttvwindow_register_time_window_notify(tab,
199 update_time_window_hook,
67f72973 200 resourceview_data);
9e01e6d4 201 lttvwindow_register_current_time_notify(tab,
202 update_current_time_hook,
67f72973 203 resourceview_data);
9e01e6d4 204 lttvwindow_register_redraw_notify(tab,
205 redraw_notify,
67f72973 206 resourceview_data);
9e01e6d4 207 lttvwindow_register_continue_notify(tab,
208 continue_notify,
67f72973 209 resourceview_data);
210 request_background_data(resourceview_data);
9e01e6d4 211
212
67f72973 213 return guicontrolflow_get_widget(resourceview_data) ;
9e01e6d4 214
215}
216
217void legend_destructor(GtkWindow *legend)
218{
219 g_legend_list = g_slist_remove(g_legend_list, legend);
220}
221
222/* Create a popup legend */
223GtkWidget *
224h_legend(LttvPlugin *plugin)
225{
226 LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
227 Tab *tab = ptab->tab;
228 g_info("h_legend, %p", tab);
229
230 GtkWindow *legend = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
231
232 g_legend_list = g_slist_append(
233 g_legend_list,
234 legend);
235
236 g_object_set_data_full(
237 G_OBJECT(legend),
238 "legend",
239 legend,
240 (GDestroyNotify)legend_destructor);
241
242 gtk_window_set_title(legend, "Control Flow View Legend");
243
244 GtkWidget *pixmap = create_pixmap(GTK_WIDGET(legend), "lttv-color-list.png");
245
9e01e6d4 246 gtk_container_add(GTK_CONTAINER(legend), GTK_WIDGET(pixmap));
247
248 gtk_widget_show(GTK_WIDGET(pixmap));
249 gtk_widget_show(GTK_WIDGET(legend));
250
251
252 return NULL; /* This is a popup window */
253}
254
255
256int event_selected_hook(void *hook_data, void *call_data)
257{
67f72973 258 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
9e01e6d4 259 guint *event_number = (guint*) call_data;
260
261 g_debug("DEBUG : event selected by main window : %u", *event_number);
262
263 return 0;
264}
265
d3d99fde 266static void cpu_set_line_color(PropertiesLine *prop_line, LttvCPUState *s)
598026ba 267{
1b171947 268 GQuark present_state;
269
270 if(s->mode_stack->len == 0)
271 present_state = LTTV_CPU_UNKNOWN;
272 else
273 present_state = ((GQuark*)s->mode_stack->data)[s->mode_stack->len-1];
d3d99fde 274
201fcc15 275 if(present_state == LTTV_CPU_IDLE) {
598026ba 276 prop_line->color = drawing_colors_cpu[COL_CPU_IDLE];
277 }
278 else if(present_state == LTTV_CPU_BUSY) {
279 prop_line->color = drawing_colors_cpu[COL_CPU_BUSY];
280 }
281 else if(present_state == LTTV_CPU_IRQ) {
282 prop_line->color = drawing_colors_cpu[COL_CPU_IRQ];
283 }
d34141ca 284 else if(present_state == LTTV_CPU_SOFT_IRQ) {
285 prop_line->color = drawing_colors_cpu[COL_CPU_SOFT_IRQ];
286 }
d3d99fde 287 else if(present_state == LTTV_CPU_TRAP) {
288 prop_line->color = drawing_colors_cpu[COL_CPU_TRAP];
201fcc15 289 } else {
290 prop_line->color = drawing_colors_cpu[COL_CPU_UNKNOWN];
d3d99fde 291 }
598026ba 292}
9e01e6d4 293
8743690d 294static void irq_set_line_color(PropertiesLine *prop_line, LttvIRQState *s)
295{
1b171947 296 GQuark present_state;
297 if(s->mode_stack->len == 0)
298 present_state = LTTV_IRQ_UNKNOWN;
299 else
300 present_state = ((GQuark*)s->mode_stack->data)[s->mode_stack->len-1];
8743690d 301
1b171947 302 if(present_state == LTTV_IRQ_IDLE) {
8743690d 303 prop_line->color = drawing_colors_irq[COL_IRQ_IDLE];
304 }
305 else if(present_state == LTTV_IRQ_BUSY) {
306 prop_line->color = drawing_colors_irq[COL_IRQ_BUSY];
307 }
1b171947 308 else {
309 prop_line->color = drawing_colors_irq[COL_IRQ_UNKNOWN];
310 }
8743690d 311}
312
0305fe77 313static void soft_irq_set_line_color(PropertiesLine *prop_line, LttvSoftIRQState *s)
314{
315 GQuark present_state;
316 if(s->running == 0)
317 prop_line->color = drawing_colors_soft_irq[COL_SOFT_IRQ_IDLE];
318 else
319 prop_line->color = drawing_colors_soft_irq[COL_SOFT_IRQ_BUSY];
320}
321
38726a78 322static void trap_set_line_color(PropertiesLine *prop_line, LttvTrapState *s)
323{
324 GQuark present_state;
325 if(s->running == 0)
326 prop_line->color = drawing_colors_trap[COL_TRAP_IDLE];
327 else
328 prop_line->color = drawing_colors_trap[COL_TRAP_BUSY];
329}
330
20d16f82 331static void bdev_set_line_color(PropertiesLine *prop_line, LttvBdevState *s)
332{
1b171947 333 GQuark present_state;
23e59a12 334 if(s == 0 || s->mode_stack->len == 0)
1b171947 335 present_state = LTTV_BDEV_UNKNOWN;
336 else
337 present_state = ((GQuark*)s->mode_stack->data)[s->mode_stack->len-1];
20d16f82 338
1b171947 339 if(present_state == LTTV_BDEV_IDLE) {
20d16f82 340 prop_line->color = drawing_colors_bdev[COL_BDEV_IDLE];
341 }
342 else if(present_state == LTTV_BDEV_BUSY_READING) {
343 prop_line->color = drawing_colors_bdev[COL_BDEV_BUSY_READING];
344 }
345 else if(present_state == LTTV_BDEV_BUSY_WRITING) {
346 prop_line->color = drawing_colors_bdev[COL_BDEV_BUSY_WRITING];
347 }
1b171947 348 else {
349 prop_line->color = drawing_colors_bdev[COL_BDEV_UNKNOWN];
350 }
20d16f82 351}
352
9e01e6d4 353/* before_schedchange_hook
354 *
355 * This function basically draw lines and icons. Two types of lines are drawn :
356 * one small (3 pixels?) representing the state of the process and the second
357 * type is thicker (10 pixels?) representing on which CPU a process is running
358 * (and this only in running state).
359 *
360 * Extremums of the lines :
361 * x_min : time of the last event context for this process kept in memory.
362 * x_max : time of the current event.
363 * y : middle of the process in the process list. The process is found in the
364 * list, therefore is it's position in pixels.
365 *
366 * The choice of lines'color is defined by the context of the last event for this
367 * process.
368 */
369
370
371int before_schedchange_hook(void *hook_data, void *call_data)
372{
dd455fb8 373 LttvTraceHook *th = (LttvTraceHook*)hook_data;
374 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 375 ControlFlowData *resourceview_data = events_request->viewer_data;
9e01e6d4 376
377 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
378
379 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
380 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
381
382 LttEvent *e;
383 e = ltt_tracefile_get_event(tfc->tf);
384 gint target_pid_saved = tfc->target_pid;
385
386 LttTime evtime = ltt_event_time(e);
67f72973 387 LttvFilter *filter = resourceview_data->filter;
58a9b31b 388
9e01e6d4 389 /* we are in a schedchange, before the state update. We must draw the
390 * items corresponding to the state before it changes : now is the right
391 * time to do it.
392 */
393
394 guint pid_out;
395 guint pid_in;
ca5c76ed 396 pid_out = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
397 pid_in = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
67f72973 398// TODO: can't we reenable this? pmf
44ffb95f 399// if(pid_in != 0 && pid_out != 0) {
400// /* not a transition to/from idle */
401// return 0;
402// }
c4e6f4dc 403
9e01e6d4 404 tfc->target_pid = pid_out;
58a9b31b 405
67f72973 406 guint cpu = tfs->cpu;
9e01e6d4 407
67f72973 408 guint trace_num = ts->parent.index;
409 /* Add process to process list (if not present) */
410 guint pl_height = 0;
411 HashedResourceData *hashed_process_data = NULL;
412 ProcessList *process_list = resourceview_data->process_list;
9e01e6d4 413
67f72973 414 hashed_process_data = resourcelist_obtain_cpu(resourceview_data, trace_num, cpu);
415
416 /* Now, the process is in the state hash and our own process hash.
417 * We definitely can draw the items related to the ending state.
418 */
419
420 if(ltt_time_compare(hashed_process_data->next_good_time,
421 evtime) > 0)
422 {
423 if(hashed_process_data->x.middle_marked == FALSE) {
424
425 TimeWindow time_window =
426 lttvwindow_get_time_window(resourceview_data->tab);
9e01e6d4 427#ifdef EXTRA_CHECK
67f72973 428 if(ltt_time_compare(evtime, time_window.start_time) == -1
429 || ltt_time_compare(evtime, time_window.end_time) == 1)
430 return;
9e01e6d4 431#endif //EXTRA_CHECK
67f72973 432 Drawing_t *drawing = resourceview_data->drawing;
433 guint width = drawing->width;
434 guint x;
435 convert_time_to_pixels(
436 time_window,
437 evtime,
438 width,
439 &x);
440
441 /* Draw collision indicator */
442 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
443 gdk_draw_point(hashed_process_data->pixmap,
444 drawing->gc,
445 x,
446 COLLISION_POSITION(hashed_process_data->height));
447 hashed_process_data->x.middle_marked = TRUE;
448 }
449 } else {
450 TimeWindow time_window =
451 lttvwindow_get_time_window(resourceview_data->tab);
9e01e6d4 452#ifdef EXTRA_CHECK
67f72973 453 if(ltt_time_compare(evtime, time_window.start_time) == -1
9e01e6d4 454 || ltt_time_compare(evtime, time_window.end_time) == 1)
67f72973 455 return;
9e01e6d4 456#endif //EXTRA_CHECK
67f72973 457 Drawing_t *drawing = resourceview_data->drawing;
458 guint width = drawing->width;
459 guint x;
460 convert_time_to_pixels(
461 time_window,
462 evtime,
463 width,
464 &x);
9e01e6d4 465
67f72973 466 /* Jump over draw if we are at the same x position */
467 if(x == hashed_process_data->x.middle &&
468 hashed_process_data->x.middle_used)
469 {
470 if(hashed_process_data->x.middle_marked == FALSE) {
471 /* Draw collision indicator */
472 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
473 gdk_draw_point(hashed_process_data->pixmap,
474 drawing->gc,
475 x,
476 COLLISION_POSITION(hashed_process_data->height));
477 hashed_process_data->x.middle_marked = TRUE;
58a9b31b 478 }
67f72973 479 /* jump */
480 } else {
481 DrawContext draw_context;
9e01e6d4 482
67f72973 483 /* Now create the drawing context that will be used to draw
484 * items related to the last state. */
485 draw_context.drawable = hashed_process_data->pixmap;
486 draw_context.gc = drawing->gc;
487 draw_context.pango_layout = drawing->pango_layout;
488 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
489 draw_context.drawinfo.end.x = x;
9e01e6d4 490
67f72973 491 draw_context.drawinfo.y.over = 1;
492 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
493 draw_context.drawinfo.y.under = hashed_process_data->height;
9e01e6d4 494
67f72973 495 draw_context.drawinfo.start.offset.over = 0;
496 draw_context.drawinfo.start.offset.middle = 0;
497 draw_context.drawinfo.start.offset.under = 0;
498 draw_context.drawinfo.end.offset.over = 0;
499 draw_context.drawinfo.end.offset.middle = 0;
500 draw_context.drawinfo.end.offset.under = 0;
9e01e6d4 501
67f72973 502 {
503 /* Draw the line */
504 //PropertiesLine prop_line = prepare_s_e_line(process);
505 PropertiesLine prop_line;
506 prop_line.line_width = STATE_LINE_WIDTH;
507 prop_line.style = GDK_LINE_SOLID;
508 prop_line.y = MIDDLE;
509 cpu_set_line_color(&prop_line, tfs->cpu_state);
510 draw_line((void*)&prop_line, (void*)&draw_context);
9e01e6d4 511
67f72973 512 }
513 /* become the last x position */
514 hashed_process_data->x.middle = x;
515 hashed_process_data->x.middle_used = TRUE;
516 hashed_process_data->x.middle_marked = FALSE;
9e01e6d4 517
67f72973 518 /* Calculate the next good time */
519 convert_pixels_to_time(width, x+1, time_window,
520 &hashed_process_data->next_good_time);
521 }
9e01e6d4 522 }
523
67f72973 524 return 0;
9e01e6d4 525}
526
58a9b31b 527/* after_schedchange_hook
528 *
529 * The draw after hook is called by the reading API to have a
530 * particular event drawn on the screen.
531 * @param hook_data ControlFlowData structure of the viewer.
532 * @param call_data Event context.
533 *
534 * This function adds items to be drawn in a queue for each process.
535 *
536 */
537int after_schedchange_hook(void *hook_data, void *call_data)
9e01e6d4 538{
dd455fb8 539 LttvTraceHook *th = (LttvTraceHook*)hook_data;
540 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 541 ControlFlowData *resourceview_data = events_request->viewer_data;
44ffb95f 542 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
44ffb95f 543 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
44ffb95f 544 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
44ffb95f 545 LttEvent *e;
67f72973 546
44ffb95f 547 e = ltt_tracefile_get_event(tfc->tf);
548
67f72973 549 LttvFilter *filter = resourceview_data->filter;
44ffb95f 550 if(filter != NULL && filter->head != NULL)
551 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
552 tfc->t_context->t,tfc,NULL,NULL))
553 return FALSE;
554
555 LttTime evtime = ltt_event_time(e);
556
44ffb95f 557 /* Add process to process list (if not present) */
558 LttvProcessState *process_in;
559 LttTime birth;
560 guint pl_height = 0;
561 HashedResourceData *hashed_process_data_in = NULL;
562
67f72973 563 ProcessList *process_list = resourceview_data->process_list;
44ffb95f 564
565 guint pid_in;
566 {
567 guint pid_out;
ca5c76ed 568 pid_out = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
569 pid_in = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
44ffb95f 570 }
571
572
573 /* Find process pid_in in the list... */
574 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
575 //process_in = tfs->process;
576 guint cpu = tfs->cpu;
44ffb95f 577 guint trace_num = ts->parent.index;
578 process_in = ts->running_process[cpu];
579 /* It should exist, because we are after the state update. */
580#ifdef EXTRA_CHECK
581 g_assert(process_in != NULL);
582#endif //EXTRA_CHECK
583 birth = process_in->creation_time;
584
67f72973 585 //hashed_process_data_in = processlist_get_process_data(process_list, cpuq, trace_num);
586 hashed_process_data_in = resourcelist_obtain_cpu(resourceview_data, trace_num, cpu);
587
44ffb95f 588 /* Set the current process */
589 process_list->current_hash_data[trace_num][process_in->cpu] =
590 hashed_process_data_in;
591
592 if(ltt_time_compare(hashed_process_data_in->next_good_time,
593 evtime) <= 0)
594 {
595 TimeWindow time_window =
67f72973 596 lttvwindow_get_time_window(resourceview_data->tab);
44ffb95f 597
598#ifdef EXTRA_CHECK
599 if(ltt_time_compare(evtime, time_window.start_time) == -1
600 || ltt_time_compare(evtime, time_window.end_time) == 1)
601 return;
602#endif //EXTRA_CHECK
67f72973 603 Drawing_t *drawing = resourceview_data->drawing;
44ffb95f 604 guint width = drawing->width;
605 guint new_x;
606
607 convert_time_to_pixels(
608 time_window,
609 evtime,
610 width,
611 &new_x);
612
613 if(hashed_process_data_in->x.middle != new_x) {
614 hashed_process_data_in->x.middle = new_x;
615 hashed_process_data_in->x.middle_used = FALSE;
616 hashed_process_data_in->x.middle_marked = FALSE;
617 }
618 }
58a9b31b 619 return 0;
620}
9e01e6d4 621
58a9b31b 622/* before_execmode_hook
623 *
624 * This function basically draw lines and icons. Two types of lines are drawn :
625 * one small (3 pixels?) representing the state of the process and the second
626 * type is thicker (10 pixels?) representing on which CPU a process is running
627 * (and this only in running state).
628 *
629 * Extremums of the lines :
630 * x_min : time of the last event context for this process kept in memory.
631 * x_max : time of the current event.
632 * y : middle of the process in the process list. The process is found in the
633 * list, therefore is it's position in pixels.
634 *
635 * The choice of lines'color is defined by the context of the last event for this
636 * process.
637 */
9e01e6d4 638
598026ba 639int before_execmode_hook(void *hook_data, void *call_data)
640{
dd455fb8 641 LttvTraceHook *th = (LttvTraceHook*)hook_data;
642 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 643 ControlFlowData *resourceview_data = events_request->viewer_data;
598026ba 644
645 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
646
647 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
648 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
649
650 LttEvent *e;
651 e = ltt_tracefile_get_event(tfc->tf);
652
653 LttTime evtime = ltt_event_time(e);
654
8743690d 655 before_execmode_hook_irq(hook_data, call_data);
0305fe77 656 before_execmode_hook_soft_irq(hook_data, call_data);
38726a78 657 before_execmode_hook_trap(hook_data, call_data);
8743690d 658
598026ba 659 /* we are in a execmode, before the state update. We must draw the
660 * items corresponding to the state before it changes : now is the right
661 * time to do it.
662 */
663 /* For the pid */
598026ba 664 guint cpu = tfs->cpu;
67f72973 665
598026ba 666 guint trace_num = ts->parent.index;
667 LttvProcessState *process = ts->running_process[cpu];
668 g_assert(process != NULL);
669
598026ba 670 /* Well, the process_out existed : we must get it in the process hash
671 * or add it, and draw its items.
672 */
673 /* Add process to process list (if not present) */
674 guint pl_height = 0;
675 HashedResourceData *hashed_process_data = NULL;
67f72973 676 ProcessList *process_list = resourceview_data->process_list;
677
598026ba 678 LttTime birth = process->creation_time;
679
680 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
681 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
682 } else {
67f72973 683 hashed_process_data = resourcelist_obtain_cpu(resourceview_data, trace_num, cpu);
684
598026ba 685 /* Set the current process */
686 process_list->current_hash_data[trace_num][process->cpu] =
687 hashed_process_data;
688 }
689
690 /* Now, the process is in the state hash and our own process hash.
691 * We definitely can draw the items related to the ending state.
692 */
693
694 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
695 evtime) > 0))
696 {
697 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
698 TimeWindow time_window =
67f72973 699 lttvwindow_get_time_window(resourceview_data->tab);
598026ba 700
701#ifdef EXTRA_CHECK
702 if(ltt_time_compare(evtime, time_window.start_time) == -1
703 || ltt_time_compare(evtime, time_window.end_time) == 1)
704 return;
705#endif //EXTRA_CHECK
67f72973 706 Drawing_t *drawing = resourceview_data->drawing;
598026ba 707 guint width = drawing->width;
708 guint x;
709 convert_time_to_pixels(
710 time_window,
711 evtime,
712 width,
713 &x);
714
715 /* Draw collision indicator */
716 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
717 gdk_draw_point(hashed_process_data->pixmap,
718 drawing->gc,
719 x,
720 COLLISION_POSITION(hashed_process_data->height));
721 hashed_process_data->x.middle_marked = TRUE;
722 }
d3d99fde 723 }
724 else {
598026ba 725 TimeWindow time_window =
67f72973 726 lttvwindow_get_time_window(resourceview_data->tab);
598026ba 727
728#ifdef EXTRA_CHECK
729 if(ltt_time_compare(evtime, time_window.start_time) == -1
730 || ltt_time_compare(evtime, time_window.end_time) == 1)
731 return;
732#endif //EXTRA_CHECK
67f72973 733 Drawing_t *drawing = resourceview_data->drawing;
598026ba 734 guint width = drawing->width;
735 guint x;
736
737 convert_time_to_pixels(
738 time_window,
739 evtime,
740 width,
741 &x);
742
743
744 /* Jump over draw if we are at the same x position */
745 if(unlikely(x == hashed_process_data->x.middle &&
746 hashed_process_data->x.middle_used))
747 {
748 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
749 /* Draw collision indicator */
750 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
751 gdk_draw_point(hashed_process_data->pixmap,
752 drawing->gc,
753 x,
754 COLLISION_POSITION(hashed_process_data->height));
755 hashed_process_data->x.middle_marked = TRUE;
756 }
757 /* jump */
d3d99fde 758 }
759 else {
598026ba 760
761 DrawContext draw_context;
762 /* Now create the drawing context that will be used to draw
763 * items related to the last state. */
764 draw_context.drawable = hashed_process_data->pixmap;
765 draw_context.gc = drawing->gc;
766 draw_context.pango_layout = drawing->pango_layout;
767 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
768 draw_context.drawinfo.end.x = x;
769
770 draw_context.drawinfo.y.over = 1;
771 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
772 draw_context.drawinfo.y.under = hashed_process_data->height;
773
774 draw_context.drawinfo.start.offset.over = 0;
775 draw_context.drawinfo.start.offset.middle = 0;
776 draw_context.drawinfo.start.offset.under = 0;
777 draw_context.drawinfo.end.offset.over = 0;
778 draw_context.drawinfo.end.offset.middle = 0;
779 draw_context.drawinfo.end.offset.under = 0;
780
781 {
782 /* Draw the line */
783 PropertiesLine prop_line;
d3d99fde 784 prop_line.line_width = STATE_LINE_WIDTH;
785 prop_line.style = GDK_LINE_SOLID;
786 prop_line.y = MIDDLE;
787 cpu_set_line_color(&prop_line, tfs->cpu_state);
598026ba 788 draw_line((void*)&prop_line, (void*)&draw_context);
789 }
790 /* become the last x position */
791 hashed_process_data->x.middle = x;
792 hashed_process_data->x.middle_used = TRUE;
793 hashed_process_data->x.middle_marked = FALSE;
794
795 /* Calculate the next good time */
796 convert_pixels_to_time(width, x+1, time_window,
797 &hashed_process_data->next_good_time);
798 }
799 }
800
801 return 0;
802}
9e01e6d4 803
8743690d 804int before_execmode_hook_irq(void *hook_data, void *call_data)
805{
dd455fb8 806 LttvTraceHook *th = (LttvTraceHook*)hook_data;
807 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 808 ControlFlowData *resourceview_data = events_request->viewer_data;
8743690d 809
810 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
811
812 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
813 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
814
815 LttEvent *e;
816 e = ltt_tracefile_get_event(tfc->tf);
817
818 LttTime evtime = ltt_event_time(e);
819
ca5c76ed 820 LttTrace *trace = tfc->t_context->t;
821
8743690d 822 /* we are in a execmode, before the state update. We must draw the
823 * items corresponding to the state before it changes : now is the right
824 * time to do it.
825 */
826 /* For the pid */
827
828 guint64 irq;
829 guint cpu = tfs->cpu;
830
ca5c76ed 831 guint16 ev_id_entry = marker_get_id_from_info(trace, marker_get_info_from_name(trace, lttv_merge_facility_event_name(LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_ENTRY)));
832 guint16 ev_id_exit = marker_get_id_from_info(trace, marker_get_info_from_name(trace, lttv_merge_facility_event_name(LTT_FACILITY_KERNEL, LTT_EVENT_IRQ_EXIT)));
833 if(ev_id_entry == e->event_id) {
834 irq = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
8743690d 835 }
ca5c76ed 836 else if(ev_id_exit == e->event_id) {
8743690d 837 irq = ts->cpu_states[cpu].last_irq;
838 }
839 else {
840 return 0;
841 }
842
8743690d 843 guint trace_num = ts->parent.index;
844
8743690d 845 /* Well, the process_out existed : we must get it in the process hash
846 * or add it, and draw its items.
847 */
848 /* Add process to process list (if not present) */
849 guint pl_height = 0;
850 HashedResourceData *hashed_process_data = NULL;
67f72973 851 ProcessList *process_list = resourceview_data->process_list;
852
853 hashed_process_data = resourcelist_obtain_irq(resourceview_data, trace_num, irq);
671c625b 854 // TODO: fix this, it's ugly and slow:
855 GQuark name;
856 {
857 gchar *str;
858 str = g_strdup_printf("IRQ %llu [%s]", irq, (char*)g_quark_to_string(ts->irq_names[irq]));
859 name = g_quark_from_string(str);
860 g_free(str);
861 }
862 gtk_tree_store_set(resourceview_data->process_list->list_store, &hashed_process_data->y_iter, NAME_COLUMN, g_quark_to_string(name), -1);
8743690d 863
864 /* Now, the process is in the state hash and our own process hash.
865 * We definitely can draw the items related to the ending state.
866 */
867
868 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
869 evtime) > 0))
870 {
871 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
872 TimeWindow time_window =
67f72973 873 lttvwindow_get_time_window(resourceview_data->tab);
8743690d 874
875#ifdef EXTRA_CHECK
876 if(ltt_time_compare(evtime, time_window.start_time) == -1
877 || ltt_time_compare(evtime, time_window.end_time) == 1)
878 return;
879#endif //EXTRA_CHECK
67f72973 880 Drawing_t *drawing = resourceview_data->drawing;
8743690d 881 guint width = drawing->width;
882 guint x;
883 convert_time_to_pixels(
884 time_window,
885 evtime,
886 width,
887 &x);
888
889 /* Draw collision indicator */
890 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
891 gdk_draw_point(hashed_process_data->pixmap,
892 drawing->gc,
893 x,
894 COLLISION_POSITION(hashed_process_data->height));
895 hashed_process_data->x.middle_marked = TRUE;
896 }
897 }
898 else {
899 TimeWindow time_window =
67f72973 900 lttvwindow_get_time_window(resourceview_data->tab);
8743690d 901
902#ifdef EXTRA_CHECK
903 if(ltt_time_compare(evtime, time_window.start_time) == -1
904 || ltt_time_compare(evtime, time_window.end_time) == 1)
905 return;
906#endif //EXTRA_CHECK
67f72973 907 Drawing_t *drawing = resourceview_data->drawing;
8743690d 908 guint width = drawing->width;
909 guint x;
910
911 convert_time_to_pixels(
912 time_window,
913 evtime,
914 width,
915 &x);
916
917
918 /* Jump over draw if we are at the same x position */
919 if(unlikely(x == hashed_process_data->x.middle &&
920 hashed_process_data->x.middle_used))
921 {
922 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
923 /* Draw collision indicator */
924 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
925 gdk_draw_point(hashed_process_data->pixmap,
926 drawing->gc,
927 x,
928 COLLISION_POSITION(hashed_process_data->height));
929 hashed_process_data->x.middle_marked = TRUE;
930 }
931 /* jump */
932 }
933 else {
934
935 DrawContext draw_context;
936 /* Now create the drawing context that will be used to draw
937 * items related to the last state. */
938 draw_context.drawable = hashed_process_data->pixmap;
939 draw_context.gc = drawing->gc;
940 draw_context.pango_layout = drawing->pango_layout;
941 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
942 draw_context.drawinfo.end.x = x;
943
944 draw_context.drawinfo.y.over = 1;
945 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
946 draw_context.drawinfo.y.under = hashed_process_data->height;
947
948 draw_context.drawinfo.start.offset.over = 0;
949 draw_context.drawinfo.start.offset.middle = 0;
950 draw_context.drawinfo.start.offset.under = 0;
951 draw_context.drawinfo.end.offset.over = 0;
952 draw_context.drawinfo.end.offset.middle = 0;
953 draw_context.drawinfo.end.offset.under = 0;
954
955 {
956 /* Draw the line */
957 PropertiesLine prop_line;
958 prop_line.line_width = STATE_LINE_WIDTH;
959 prop_line.style = GDK_LINE_SOLID;
960 prop_line.y = MIDDLE;
961 irq_set_line_color(&prop_line, &ts->irq_states[irq]);
962 draw_line((void*)&prop_line, (void*)&draw_context);
963 }
964 /* become the last x position */
965 hashed_process_data->x.middle = x;
966 hashed_process_data->x.middle_used = TRUE;
967 hashed_process_data->x.middle_marked = FALSE;
968
969 /* Calculate the next good time */
970 convert_pixels_to_time(width, x+1, time_window,
971 &hashed_process_data->next_good_time);
972 }
973 }
974
975 return 0;
976}
977
0305fe77 978int before_execmode_hook_soft_irq(void *hook_data, void *call_data)
979{
980 LttvTraceHook *th = (LttvTraceHook*)hook_data;
981 EventsRequest *events_request = (EventsRequest*)th->hook_data;
982 ControlFlowData *resourceview_data = events_request->viewer_data;
983
984 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
985
986 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
987 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
988
989 LttEvent *e;
990 e = ltt_tracefile_get_event(tfc->tf);
991
992 LttTime evtime = ltt_event_time(e);
993
994 LttTrace *trace = tfc->t_context->t;
995
996 /* we are in a execmode, before the state update. We must draw the
997 * items corresponding to the state before it changes : now is the right
998 * time to do it.
999 */
1000 /* For the pid */
1001
1002 guint64 softirq;
1003 guint cpu = tfs->cpu;
1004
1005 guint16 ev_id_entry = marker_get_id_from_info(trace, marker_get_info_from_name(trace, lttv_merge_facility_event_name(LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_ENTRY)));
1006 guint16 ev_id_exit = marker_get_id_from_info(trace, marker_get_info_from_name(trace, lttv_merge_facility_event_name(LTT_FACILITY_KERNEL, LTT_EVENT_SOFT_IRQ_EXIT)));
1007 if(ev_id_entry == e->event_id) {
1008 softirq = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
1009 }
1010 else if(ev_id_exit == e->event_id) {
1011 softirq = ts->cpu_states[cpu].last_soft_irq;
1012 }
1013 else {
1014 return 0;
1015 }
1016
1017 guint trace_num = ts->parent.index;
1018
1019 /* Well, the process_out existed : we must get it in the process hash
1020 * or add it, and draw its items.
1021 */
1022 /* Add process to process list (if not present) */
1023 guint pl_height = 0;
1024 HashedResourceData *hashed_process_data = NULL;
1025 ProcessList *process_list = resourceview_data->process_list;
1026
1027 hashed_process_data = resourcelist_obtain_soft_irq(resourceview_data, trace_num, softirq);
1028
1029 /* Now, the process is in the state hash and our own process hash.
1030 * We definitely can draw the items related to the ending state.
1031 */
1032
1033 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1034 evtime) > 0))
1035 {
1036 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1037 TimeWindow time_window =
1038 lttvwindow_get_time_window(resourceview_data->tab);
1039
1040#ifdef EXTRA_CHECK
1041 if(ltt_time_compare(evtime, time_window.start_time) == -1
1042 || ltt_time_compare(evtime, time_window.end_time) == 1)
1043 return;
1044#endif //EXTRA_CHECK
1045 Drawing_t *drawing = resourceview_data->drawing;
1046 guint width = drawing->width;
1047 guint x;
1048 convert_time_to_pixels(
1049 time_window,
1050 evtime,
1051 width,
1052 &x);
1053
1054 /* Draw collision indicator */
1055 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1056 gdk_draw_point(hashed_process_data->pixmap,
1057 drawing->gc,
1058 x,
1059 COLLISION_POSITION(hashed_process_data->height));
1060 hashed_process_data->x.middle_marked = TRUE;
1061 }
1062 }
1063 else {
1064 TimeWindow time_window =
1065 lttvwindow_get_time_window(resourceview_data->tab);
1066
1067#ifdef EXTRA_CHECK
1068 if(ltt_time_compare(evtime, time_window.start_time) == -1
1069 || ltt_time_compare(evtime, time_window.end_time) == 1)
1070 return;
1071#endif //EXTRA_CHECK
1072 Drawing_t *drawing = resourceview_data->drawing;
1073 guint width = drawing->width;
1074 guint x;
1075
1076 convert_time_to_pixels(
1077 time_window,
1078 evtime,
1079 width,
1080 &x);
1081
1082
1083 /* Jump over draw if we are at the same x position */
1084 if(unlikely(x == hashed_process_data->x.middle &&
1085 hashed_process_data->x.middle_used))
1086 {
1087 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1088 /* Draw collision indicator */
1089 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1090 gdk_draw_point(hashed_process_data->pixmap,
1091 drawing->gc,
1092 x,
1093 COLLISION_POSITION(hashed_process_data->height));
1094 hashed_process_data->x.middle_marked = TRUE;
1095 }
1096 /* jump */
1097 }
1098 else {
1099
1100 DrawContext draw_context;
1101 /* Now create the drawing context that will be used to draw
1102 * items related to the last state. */
1103 draw_context.drawable = hashed_process_data->pixmap;
1104 draw_context.gc = drawing->gc;
1105 draw_context.pango_layout = drawing->pango_layout;
1106 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1107 draw_context.drawinfo.end.x = x;
1108
1109 draw_context.drawinfo.y.over = 1;
1110 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1111 draw_context.drawinfo.y.under = hashed_process_data->height;
1112
1113 draw_context.drawinfo.start.offset.over = 0;
1114 draw_context.drawinfo.start.offset.middle = 0;
1115 draw_context.drawinfo.start.offset.under = 0;
1116 draw_context.drawinfo.end.offset.over = 0;
1117 draw_context.drawinfo.end.offset.middle = 0;
1118 draw_context.drawinfo.end.offset.under = 0;
1119
1120 {
1121 /* Draw the line */
1122 PropertiesLine prop_line;
1123 prop_line.line_width = STATE_LINE_WIDTH;
1124 prop_line.style = GDK_LINE_SOLID;
1125 prop_line.y = MIDDLE;
1126 soft_irq_set_line_color(&prop_line, &ts->soft_irq_states[softirq]);
1127 draw_line((void*)&prop_line, (void*)&draw_context);
1128 }
1129 /* become the last x position */
1130 hashed_process_data->x.middle = x;
1131 hashed_process_data->x.middle_used = TRUE;
1132 hashed_process_data->x.middle_marked = FALSE;
1133
1134 /* Calculate the next good time */
1135 convert_pixels_to_time(width, x+1, time_window,
1136 &hashed_process_data->next_good_time);
1137 }
1138 }
1139
1140 return 0;
1141}
1142
38726a78 1143int before_execmode_hook_trap(void *hook_data, void *call_data)
1144{
1145 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1146 EventsRequest *events_request = (EventsRequest*)th->hook_data;
1147 ControlFlowData *resourceview_data = events_request->viewer_data;
1148
1149 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1150
1151 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1152 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1153
1154 LttEvent *e;
1155 e = ltt_tracefile_get_event(tfc->tf);
1156
1157 LttTime evtime = ltt_event_time(e);
1158
1159 LttTrace *trace = tfc->t_context->t;
1160
1161 /* we are in a execmode, before the state update. We must draw the
1162 * items corresponding to the state before it changes : now is the right
1163 * time to do it.
1164 */
1165 /* For the pid */
1166
1167 guint64 trap;
1168 guint cpu = tfs->cpu;
1169
a81d2a59 1170 guint16 ev_id_entry = marker_get_id_from_info(trace, marker_get_info_from_name(trace, lttv_merge_facility_event_name(LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_TRAP_ENTRY)));
1171 guint16 ev_id_exit = marker_get_id_from_info(trace, marker_get_info_from_name(trace, lttv_merge_facility_event_name(LTT_FACILITY_KERNEL_ARCH, LTT_EVENT_TRAP_EXIT)));
38726a78 1172 if(ev_id_entry == e->event_id) {
1173 trap = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
1174 }
1175 else if(ev_id_exit == e->event_id) {
1176 trap = ts->cpu_states[cpu].last_trap;
1177 }
1178 else {
1179 return 0;
1180 }
1181
1182 guint trace_num = ts->parent.index;
1183
1184 /* Well, the process_out existed : we must get it in the process hash
1185 * or add it, and draw its items.
1186 */
1187 /* Add process to process list (if not present) */
1188 guint pl_height = 0;
1189 HashedResourceData *hashed_process_data = NULL;
1190 ProcessList *process_list = resourceview_data->process_list;
1191
1192 hashed_process_data = resourcelist_obtain_trap(resourceview_data, trace_num, trap);
1193
1194 /* Now, the process is in the state hash and our own process hash.
1195 * We definitely can draw the items related to the ending state.
1196 */
1197
1198 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1199 evtime) > 0))
1200 {
1201 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1202 TimeWindow time_window =
1203 lttvwindow_get_time_window(resourceview_data->tab);
1204
1205#ifdef EXTRA_CHECK
1206 if(ltt_time_compare(evtime, time_window.start_time) == -1
1207 || ltt_time_compare(evtime, time_window.end_time) == 1)
1208 return;
1209#endif //EXTRA_CHECK
1210 Drawing_t *drawing = resourceview_data->drawing;
1211 guint width = drawing->width;
1212 guint x;
1213 convert_time_to_pixels(
1214 time_window,
1215 evtime,
1216 width,
1217 &x);
1218
1219 /* Draw collision indicator */
1220 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1221 gdk_draw_point(hashed_process_data->pixmap,
1222 drawing->gc,
1223 x,
1224 COLLISION_POSITION(hashed_process_data->height));
1225 hashed_process_data->x.middle_marked = TRUE;
1226 }
1227 }
1228 else {
1229 TimeWindow time_window =
1230 lttvwindow_get_time_window(resourceview_data->tab);
1231
1232#ifdef EXTRA_CHECK
1233 if(ltt_time_compare(evtime, time_window.start_time) == -1
1234 || ltt_time_compare(evtime, time_window.end_time) == 1)
1235 return;
1236#endif //EXTRA_CHECK
1237 Drawing_t *drawing = resourceview_data->drawing;
1238 guint width = drawing->width;
1239 guint x;
1240
1241 convert_time_to_pixels(
1242 time_window,
1243 evtime,
1244 width,
1245 &x);
1246
1247
1248 /* Jump over draw if we are at the same x position */
1249 if(unlikely(x == hashed_process_data->x.middle &&
1250 hashed_process_data->x.middle_used))
1251 {
1252 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1253 /* Draw collision indicator */
1254 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1255 gdk_draw_point(hashed_process_data->pixmap,
1256 drawing->gc,
1257 x,
1258 COLLISION_POSITION(hashed_process_data->height));
1259 hashed_process_data->x.middle_marked = TRUE;
1260 }
1261 /* jump */
1262 }
1263 else {
1264
1265 DrawContext draw_context;
1266 /* Now create the drawing context that will be used to draw
1267 * items related to the last state. */
1268 draw_context.drawable = hashed_process_data->pixmap;
1269 draw_context.gc = drawing->gc;
1270 draw_context.pango_layout = drawing->pango_layout;
1271 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1272 draw_context.drawinfo.end.x = x;
1273
1274 draw_context.drawinfo.y.over = 1;
1275 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1276 draw_context.drawinfo.y.under = hashed_process_data->height;
1277
1278 draw_context.drawinfo.start.offset.over = 0;
1279 draw_context.drawinfo.start.offset.middle = 0;
1280 draw_context.drawinfo.start.offset.under = 0;
1281 draw_context.drawinfo.end.offset.over = 0;
1282 draw_context.drawinfo.end.offset.middle = 0;
1283 draw_context.drawinfo.end.offset.under = 0;
1284
1285 {
1286 /* Draw the line */
1287 PropertiesLine prop_line;
1288 prop_line.line_width = STATE_LINE_WIDTH;
1289 prop_line.style = GDK_LINE_SOLID;
1290 prop_line.y = MIDDLE;
1291 trap_set_line_color(&prop_line, &ts->trap_states[trap]);
1292 draw_line((void*)&prop_line, (void*)&draw_context);
1293 }
1294 /* become the last x position */
1295 hashed_process_data->x.middle = x;
1296 hashed_process_data->x.middle_used = TRUE;
1297 hashed_process_data->x.middle_marked = FALSE;
1298
1299 /* Calculate the next good time */
1300 convert_pixels_to_time(width, x+1, time_window,
1301 &hashed_process_data->next_good_time);
1302 }
1303 }
1304
1305 return 0;
1306}
1307
0305fe77 1308
20d16f82 1309int before_bdev_event_hook(void *hook_data, void *call_data)
1310{
dd455fb8 1311 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1312 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 1313 ControlFlowData *resourceview_data = events_request->viewer_data;
20d16f82 1314
1315 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1316
1317 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1318 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1319
1320 LttEvent *e;
1321 e = ltt_tracefile_get_event(tfc->tf);
1322
1323 LttTime evtime = ltt_event_time(e);
1324
20d16f82 1325 /* we are in a execmode, before the state update. We must draw the
1326 * items corresponding to the state before it changes : now is the right
1327 * time to do it.
1328 */
1329 /* For the pid */
1330
1331 guint cpu = tfs->cpu;
ca5c76ed 1332 guint8 major = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
1333 guint8 minor = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
1334 guint oper = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 2));
20d16f82 1335 gint devcode_gint = MKDEV(major,minor);
1336
20d16f82 1337 guint trace_num = ts->parent.index;
1338
1339 LttvBdevState *bdev = g_hash_table_lookup(ts->bdev_states, &devcode_gint);
23e59a12 1340 /* the result of the lookup might be NULL. that's ok, the rest of the function
1341 should understand it was not found and that its state is unknown */
20d16f82 1342
20d16f82 1343 /* Well, the process_out existed : we must get it in the process hash
1344 * or add it, and draw its items.
1345 */
1346 /* Add process to process list (if not present) */
1347 guint pl_height = 0;
1348 HashedResourceData *hashed_process_data = NULL;
67f72973 1349 ProcessList *process_list = resourceview_data->process_list;
20d16f82 1350// LttTime birth = process->creation_time;
1351
1352// if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1353// hashed_process_data = process_list->current_hash_data[trace_num][cpu];
1354// } else {
67f72973 1355 hashed_process_data = resourcelist_obtain_bdev(resourceview_data, trace_num, devcode_gint);
1356 ////hashed_process_data = processlist_get_process_data(process_list, resourceq, trace_num);
20d16f82 1357// hashed_process_data = processlist_get_process_data(process_list,
1358// pid,
1359// process->cpu,
1360// &birth,
1361// trace_num);
67f72973 1362//
20d16f82 1363 /* Set the current process */
1364// process_list->current_hash_data[trace_num][process->cpu] =
1365// hashed_process_data;
1366// }
1367
1368 /* Now, the process is in the state hash and our own process hash.
1369 * We definitely can draw the items related to the ending state.
1370 */
1371
1372 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1373 evtime) > 0))
1374 {
1375 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1376 TimeWindow time_window =
67f72973 1377 lttvwindow_get_time_window(resourceview_data->tab);
20d16f82 1378
1379#ifdef EXTRA_CHECK
1380 if(ltt_time_compare(evtime, time_window.start_time) == -1
1381 || ltt_time_compare(evtime, time_window.end_time) == 1)
1382 return;
1383#endif //EXTRA_CHECK
67f72973 1384 Drawing_t *drawing = resourceview_data->drawing;
20d16f82 1385 guint width = drawing->width;
1386 guint x;
1387 convert_time_to_pixels(
1388 time_window,
1389 evtime,
1390 width,
1391 &x);
1392
1393 /* Draw collision indicator */
1394 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1395 gdk_draw_point(hashed_process_data->pixmap,
1396 drawing->gc,
1397 x,
1398 COLLISION_POSITION(hashed_process_data->height));
1399 hashed_process_data->x.middle_marked = TRUE;
1400 }
1401 }
1402 else {
1403 TimeWindow time_window =
67f72973 1404 lttvwindow_get_time_window(resourceview_data->tab);
20d16f82 1405
1406#ifdef EXTRA_CHECK
1407 if(ltt_time_compare(evtime, time_window.start_time) == -1
1408 || ltt_time_compare(evtime, time_window.end_time) == 1)
1409 return;
1410#endif //EXTRA_CHECK
67f72973 1411 Drawing_t *drawing = resourceview_data->drawing;
20d16f82 1412 guint width = drawing->width;
1413 guint x;
1414
1415 convert_time_to_pixels(
1416 time_window,
1417 evtime,
1418 width,
1419 &x);
1420
1421
1422 /* Jump over draw if we are at the same x position */
1423 if(unlikely(x == hashed_process_data->x.middle &&
1424 hashed_process_data->x.middle_used))
1425 {
1426 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1427 /* Draw collision indicator */
1428 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1429 gdk_draw_point(hashed_process_data->pixmap,
1430 drawing->gc,
1431 x,
1432 COLLISION_POSITION(hashed_process_data->height));
1433 hashed_process_data->x.middle_marked = TRUE;
1434 }
1435 /* jump */
1436 }
1437 else {
1438
1439 DrawContext draw_context;
1440 /* Now create the drawing context that will be used to draw
1441 * items related to the last state. */
1442 draw_context.drawable = hashed_process_data->pixmap;
1443 draw_context.gc = drawing->gc;
1444 draw_context.pango_layout = drawing->pango_layout;
1445 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1446 draw_context.drawinfo.end.x = x;
1447
1448 draw_context.drawinfo.y.over = 1;
1449 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1450 draw_context.drawinfo.y.under = hashed_process_data->height;
1451
1452 draw_context.drawinfo.start.offset.over = 0;
1453 draw_context.drawinfo.start.offset.middle = 0;
1454 draw_context.drawinfo.start.offset.under = 0;
1455 draw_context.drawinfo.end.offset.over = 0;
1456 draw_context.drawinfo.end.offset.middle = 0;
1457 draw_context.drawinfo.end.offset.under = 0;
1458
1459 {
1460 /* Draw the line */
1461 PropertiesLine prop_line;
1462 prop_line.line_width = STATE_LINE_WIDTH;
1463 prop_line.style = GDK_LINE_SOLID;
1464 prop_line.y = MIDDLE;
1465 bdev_set_line_color(&prop_line, bdev);
1466 draw_line((void*)&prop_line, (void*)&draw_context);
1467 }
1468 /* become the last x position */
1469 hashed_process_data->x.middle = x;
1470 hashed_process_data->x.middle_used = TRUE;
1471 hashed_process_data->x.middle_marked = FALSE;
1472
1473 /* Calculate the next good time */
1474 convert_pixels_to_time(width, x+1, time_window,
1475 &hashed_process_data->next_good_time);
1476 }
1477 }
1478
1479 return 0;
1480}
1481
9e01e6d4 1482gint update_time_window_hook(void *hook_data, void *call_data)
1483{
67f72973 1484 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1485 Drawing_t *drawing = resourceview_data->drawing;
1486 ProcessList *process_list = resourceview_data->process_list;
9e01e6d4 1487
1488 const TimeWindowNotifyData *time_window_nofify_data =
1489 ((const TimeWindowNotifyData *)call_data);
1490
1491 TimeWindow *old_time_window =
1492 time_window_nofify_data->old_time_window;
1493 TimeWindow *new_time_window =
1494 time_window_nofify_data->new_time_window;
1495
1496 /* Update the ruler */
67f72973 1497 drawing_update_ruler(resourceview_data->drawing,
9e01e6d4 1498 new_time_window);
1499
1500
1501 /* Two cases : zoom in/out or scrolling */
1502
1503 /* In order to make sure we can reuse the old drawing, the scale must
1504 * be the same and the new time interval being partly located in the
1505 * currently shown time interval. (reuse is only for scrolling)
1506 */
1507
1508 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
1509 old_time_window->start_time.tv_sec,
1510 old_time_window->start_time.tv_nsec,
1511 old_time_window->time_width.tv_sec,
1512 old_time_window->time_width.tv_nsec);
1513
1514 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
1515 new_time_window->start_time.tv_sec,
1516 new_time_window->start_time.tv_nsec,
1517 new_time_window->time_width.tv_sec,
1518 new_time_window->time_width.tv_nsec);
1519
1520 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
1521 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
1522 {
1523 /* Same scale (scrolling) */
1524 g_info("scrolling");
1525 LttTime *ns = &new_time_window->start_time;
1526 LttTime *nw = &new_time_window->time_width;
1527 LttTime *os = &old_time_window->start_time;
1528 LttTime *ow = &old_time_window->time_width;
1529 LttTime old_end = old_time_window->end_time;
1530 LttTime new_end = new_time_window->end_time;
1531 //if(ns<os+w<ns+w)
1532 //if(ns<os+w && os+w<ns+w)
1533 //if(ns<old_end && os<ns)
1534 if(ltt_time_compare(*ns, old_end) == -1
1535 && ltt_time_compare(*os, *ns) == -1)
1536 {
1537 g_info("scrolling near right");
1538 /* Scroll right, keep right part of the screen */
1539 guint x = 0;
67f72973 1540 guint width = resourceview_data->drawing->width;
9e01e6d4 1541 convert_time_to_pixels(
1542 *old_time_window,
1543 *ns,
1544 width,
1545 &x);
1546
1547 /* Copy old data to new location */
1548 copy_pixmap_region(process_list,
1549 NULL,
67f72973 1550 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1551 NULL,
1552 x, 0,
1553 0, 0,
67f72973 1554 resourceview_data->drawing->width-x+SAFETY, -1);
9e01e6d4 1555
1556 if(drawing->damage_begin == drawing->damage_end)
67f72973 1557 drawing->damage_begin = resourceview_data->drawing->width-x;
9e01e6d4 1558 else
1559 drawing->damage_begin = 0;
1560
67f72973 1561 drawing->damage_end = resourceview_data->drawing->width;
9e01e6d4 1562
1563 /* Clear the data request background, but not SAFETY */
1564 rectangle_pixmap(process_list,
67f72973 1565 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1566 TRUE,
1567 drawing->damage_begin+SAFETY, 0,
1568 drawing->damage_end - drawing->damage_begin, // do not overlap
1569 -1);
1570 gtk_widget_queue_draw(drawing->drawing_area);
9e01e6d4 1571
1572 /* Get new data for the rest. */
67f72973 1573 drawing_data_request(resourceview_data->drawing,
9e01e6d4 1574 drawing->damage_begin, 0,
1575 drawing->damage_end - drawing->damage_begin,
67f72973 1576 resourceview_data->drawing->height);
9e01e6d4 1577 } else {
9e01e6d4 1578 if(ltt_time_compare(*ns,*os) == -1
1579 && ltt_time_compare(*os,new_end) == -1)
1580 {
1581 g_info("scrolling near left");
1582 /* Scroll left, keep left part of the screen */
1583 guint x = 0;
67f72973 1584 guint width = resourceview_data->drawing->width;
9e01e6d4 1585 convert_time_to_pixels(
1586 *new_time_window,
1587 *os,
1588 width,
1589 &x);
1590
1591 /* Copy old data to new location */
1592 copy_pixmap_region (process_list,
1593 NULL,
67f72973 1594 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1595 NULL,
1596 0, 0,
1597 x, 0,
1598 -1, -1);
1599
1600 if(drawing->damage_begin == drawing->damage_end)
1601 drawing->damage_end = x;
1602 else
1603 drawing->damage_end =
67f72973 1604 resourceview_data->drawing->width;
9e01e6d4 1605
1606 drawing->damage_begin = 0;
1607
1608 rectangle_pixmap (process_list,
67f72973 1609 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1610 TRUE,
1611 drawing->damage_begin, 0,
1612 drawing->damage_end - drawing->damage_begin, // do not overlap
1613 -1);
1614
1615 gtk_widget_queue_draw(drawing->drawing_area);
9e01e6d4 1616
1617 /* Get new data for the rest. */
67f72973 1618 drawing_data_request(resourceview_data->drawing,
9e01e6d4 1619 drawing->damage_begin, 0,
1620 drawing->damage_end - drawing->damage_begin,
67f72973 1621 resourceview_data->drawing->height);
9e01e6d4 1622
1623 } else {
1624 if(ltt_time_compare(*ns,*os) == 0)
1625 {
1626 g_info("not scrolling");
1627 } else {
1628 g_info("scrolling far");
1629 /* Cannot reuse any part of the screen : far jump */
1630
1631
1632 rectangle_pixmap (process_list,
67f72973 1633 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1634 TRUE,
1635 0, 0,
67f72973 1636 resourceview_data->drawing->width+SAFETY, // do not overlap
9e01e6d4 1637 -1);
1638
9e01e6d4 1639 gtk_widget_queue_draw(drawing->drawing_area);
1640
1641 drawing->damage_begin = 0;
67f72973 1642 drawing->damage_end = resourceview_data->drawing->width;
9e01e6d4 1643
67f72973 1644 drawing_data_request(resourceview_data->drawing,
9e01e6d4 1645 0, 0,
67f72973 1646 resourceview_data->drawing->width,
1647 resourceview_data->drawing->height);
9e01e6d4 1648
1649 }
1650 }
1651 }
1652 } else {
1653 /* Different scale (zoom) */
1654 g_info("zoom");
1655
1656 rectangle_pixmap (process_list,
67f72973 1657 resourceview_data->drawing->drawing_area->style->black_gc,
9e01e6d4 1658 TRUE,
1659 0, 0,
67f72973 1660 resourceview_data->drawing->width+SAFETY, // do not overlap
9e01e6d4 1661 -1);
1662
9e01e6d4 1663 gtk_widget_queue_draw(drawing->drawing_area);
1664
1665 drawing->damage_begin = 0;
67f72973 1666 drawing->damage_end = resourceview_data->drawing->width;
9e01e6d4 1667
67f72973 1668 drawing_data_request(resourceview_data->drawing,
9e01e6d4 1669 0, 0,
67f72973 1670 resourceview_data->drawing->width,
1671 resourceview_data->drawing->height);
9e01e6d4 1672 }
1673
1674 /* Update directly when scrolling */
67f72973 1675 gdk_window_process_updates(resourceview_data->drawing->drawing_area->window,
9e01e6d4 1676 TRUE);
1677
1678 return 0;
1679}
1680
1681gint traceset_notify(void *hook_data, void *call_data)
1682{
67f72973 1683 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1684 Drawing_t *drawing = resourceview_data->drawing;
9e01e6d4 1685
1686 if(unlikely(drawing->gc == NULL)) {
1687 return FALSE;
1688 }
1689 if(drawing->dotted_gc == NULL) {
1690 return FALSE;
1691 }
1692
67f72973 1693 drawing_clear(resourceview_data->drawing);
1694 processlist_clear(resourceview_data->process_list);
9e01e6d4 1695 gtk_widget_set_size_request(
67f72973 1696 resourceview_data->drawing->drawing_area,
1697 -1, processlist_get_height(resourceview_data->process_list));
1698 redraw_notify(resourceview_data, NULL);
9e01e6d4 1699
67f72973 1700 request_background_data(resourceview_data);
9e01e6d4 1701
1702 return FALSE;
1703}
1704
1705gint redraw_notify(void *hook_data, void *call_data)
1706{
67f72973 1707 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1708 Drawing_t *drawing = resourceview_data->drawing;
9e01e6d4 1709 GtkWidget *widget = drawing->drawing_area;
1710
1711 drawing->damage_begin = 0;
1712 drawing->damage_end = drawing->width;
1713
1714 /* fun feature, to be separated someday... */
67f72973 1715 drawing_clear(resourceview_data->drawing);
1716 processlist_clear(resourceview_data->process_list);
9e01e6d4 1717 gtk_widget_set_size_request(
67f72973 1718 resourceview_data->drawing->drawing_area,
1719 -1, processlist_get_height(resourceview_data->process_list));
9e01e6d4 1720 // Clear the images
67f72973 1721 rectangle_pixmap (resourceview_data->process_list,
9e01e6d4 1722 widget->style->black_gc,
1723 TRUE,
1724 0, 0,
1725 drawing->alloc_width,
1726 -1);
1727
1728 gtk_widget_queue_draw(drawing->drawing_area);
1729
1730 if(drawing->damage_begin < drawing->damage_end)
1731 {
1732 drawing_data_request(drawing,
1733 drawing->damage_begin,
1734 0,
1735 drawing->damage_end-drawing->damage_begin,
1736 drawing->height);
1737 }
1738
9e01e6d4 1739 return FALSE;
1740
1741}
1742
1743
1744gint continue_notify(void *hook_data, void *call_data)
1745{
67f72973 1746 ControlFlowData *resourceview_data = (ControlFlowData*) hook_data;
1747 Drawing_t *drawing = resourceview_data->drawing;
9e01e6d4 1748
1749 if(drawing->damage_begin < drawing->damage_end)
1750 {
1751 drawing_data_request(drawing,
1752 drawing->damage_begin,
1753 0,
1754 drawing->damage_end-drawing->damage_begin,
1755 drawing->height);
1756 }
1757
1758 return FALSE;
1759}
1760
1761
1762gint update_current_time_hook(void *hook_data, void *call_data)
1763{
67f72973 1764 ControlFlowData *resourceview_data = (ControlFlowData*)hook_data;
1765 Drawing_t *drawing = resourceview_data->drawing;
9e01e6d4 1766
1767 LttTime current_time = *((LttTime*)call_data);
1768
1769 TimeWindow time_window =
67f72973 1770 lttvwindow_get_time_window(resourceview_data->tab);
9e01e6d4 1771
1772 LttTime time_begin = time_window.start_time;
1773 LttTime width = time_window.time_width;
1774 LttTime half_width;
1775 {
1776 guint64 time_ll = ltt_time_to_uint64(width);
1777 time_ll = time_ll >> 1; /* divide by two */
1778 half_width = ltt_time_from_uint64(time_ll);
1779 }
1780 LttTime time_end = ltt_time_add(time_begin, width);
1781
1782 LttvTracesetContext * tsc =
67f72973 1783 lttvwindow_get_traceset_context(resourceview_data->tab);
9e01e6d4 1784
1785 LttTime trace_start = tsc->time_span.start_time;
1786 LttTime trace_end = tsc->time_span.end_time;
1787
1788 g_info("New current time HOOK : %lu, %lu", current_time.tv_sec,
1789 current_time.tv_nsec);
9e01e6d4 1790
1791 /* If current time is inside time interval, just move the highlight
1792 * bar */
1793
1794 /* Else, we have to change the time interval. We have to tell it
1795 * to the main window. */
1796 /* The time interval change will take care of placing the current
1797 * time at the center of the visible area, or nearest possible if we are
1798 * at one end of the trace. */
1799
1800
1801 if(ltt_time_compare(current_time, time_begin) < 0)
1802 {
1803 TimeWindow new_time_window;
1804
1805 if(ltt_time_compare(current_time,
1806 ltt_time_add(trace_start,half_width)) < 0)
1807 time_begin = trace_start;
1808 else
1809 time_begin = ltt_time_sub(current_time,half_width);
1810
1811 new_time_window.start_time = time_begin;
1812 new_time_window.time_width = width;
1813 new_time_window.time_width_double = ltt_time_to_double(width);
1814 new_time_window.end_time = ltt_time_add(time_begin, width);
1815
67f72973 1816 lttvwindow_report_time_window(resourceview_data->tab, new_time_window);
9e01e6d4 1817 }
1818 else if(ltt_time_compare(current_time, time_end) > 0)
1819 {
1820 TimeWindow new_time_window;
1821
1822 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) > 0)
1823 time_begin = ltt_time_sub(trace_end,width);
1824 else
1825 time_begin = ltt_time_sub(current_time,half_width);
1826
1827 new_time_window.start_time = time_begin;
1828 new_time_window.time_width = width;
1829 new_time_window.time_width_double = ltt_time_to_double(width);
1830 new_time_window.end_time = ltt_time_add(time_begin, width);
1831
67f72973 1832 lttvwindow_report_time_window(resourceview_data->tab, new_time_window);
9e01e6d4 1833
1834 }
67f72973 1835 gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
9e01e6d4 1836
1837 /* Update directly when scrolling */
67f72973 1838 gdk_window_process_updates(resourceview_data->drawing->drawing_area->window,
9e01e6d4 1839 TRUE);
1840
1841 return 0;
1842}
1843
1844typedef struct _ClosureData {
1845 EventsRequest *events_request;
1846 LttvTracesetState *tss;
1847 LttTime end_time;
1848 guint x_end;
1849} ClosureData;
1850
58a9b31b 1851/* Draw line until end of the screen */
9e01e6d4 1852
1853void draw_closure(gpointer key, gpointer value, gpointer user_data)
1854{
67f72973 1855 ResourceUniqueNumeric *process_info = (ResourceUniqueNumeric*)key;
44ffb95f 1856 HashedResourceData *hashed_process_data = (HashedResourceData*)value;
1857 ClosureData *closure_data = (ClosureData*)user_data;
1858
1859 EventsRequest *events_request = closure_data->events_request;
67f72973 1860 ControlFlowData *resourceview_data = events_request->viewer_data;
44ffb95f 1861
1862 LttvTracesetState *tss = closure_data->tss;
1863 LttvTracesetContext *tsc = (LttvTracesetContext*)tss;
1864
1865 LttTime evtime = closure_data->end_time;
1866
1867 gboolean dodraw = TRUE;
1868
67f72973 1869 if(hashed_process_data->type == RV_RESOURCE_MACHINE)
1870 return;
1871
44ffb95f 1872 {
1873 /* For the process */
1874 /* First, check if the current process is in the state computation
1875 * process list. If it is there, that means we must add it right now and
1876 * draw items from the beginning of the read for it. If it is not
1877 * present, it's a new process and it was not present : it will
1878 * be added after the state update. */
1879#ifdef EXTRA_CHECK
1880 g_assert(lttv_traceset_number(tsc->ts) > 0);
1881#endif //EXTRA_CHECK
1882 LttvTraceContext *tc = tsc->traces[process_info->trace_num];
1883 LttvTraceState *ts = (LttvTraceState*)tc;
1884
67f72973 1885 /* Only draw for processes that are currently in the trace states */
44ffb95f 1886
67f72973 1887 ProcessList *process_list = resourceview_data->process_list;
44ffb95f 1888#ifdef EXTRA_CHECK
67f72973 1889 /* Should be alike when background info is ready */
1890 if(resourceview_data->background_info_waiting==0)
44ffb95f 1891 g_assert(ltt_time_compare(process->creation_time,
1892 process_info->birth) == 0);
1893#endif //EXTRA_CHECK
1894
67f72973 1895 /* Now, the process is in the state hash and our own process hash.
1896 * We definitely can draw the items related to the ending state.
1897 */
1898
1899 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
1900 evtime) <= 0))
1901 {
1902 TimeWindow time_window =
1903 lttvwindow_get_time_window(resourceview_data->tab);
44ffb95f 1904
1905#ifdef EXTRA_CHECK
67f72973 1906 if(ltt_time_compare(evtime, time_window.start_time) == -1
1907 || ltt_time_compare(evtime, time_window.end_time) == 1)
1908 return;
44ffb95f 1909#endif //EXTRA_CHECK
67f72973 1910 Drawing_t *drawing = resourceview_data->drawing;
1911 guint width = drawing->width;
1912
1913 guint x = closure_data->x_end;
1914
1915 DrawContext draw_context;
1916
1917 /* Now create the drawing context that will be used to draw
1918 * items related to the last state. */
1919 draw_context.drawable = hashed_process_data->pixmap;
1920 draw_context.gc = drawing->gc;
1921 draw_context.pango_layout = drawing->pango_layout;
1922 draw_context.drawinfo.end.x = x;
1923
1924 draw_context.drawinfo.y.over = 1;
1925 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1926 draw_context.drawinfo.y.under = hashed_process_data->height;
1927
1928 draw_context.drawinfo.start.offset.over = 0;
1929 draw_context.drawinfo.start.offset.middle = 0;
1930 draw_context.drawinfo.start.offset.under = 0;
1931 draw_context.drawinfo.end.offset.over = 0;
1932 draw_context.drawinfo.end.offset.middle = 0;
1933 draw_context.drawinfo.end.offset.under = 0;
44ffb95f 1934#if 0
67f72973 1935 /* Jump over draw if we are at the same x position */
1936 if(x == hashed_process_data->x.over)
1937 {
1938 /* jump */
1939 } else {
1940 draw_context.drawinfo.start.x = hashed_process_data->x.over;
1941 /* Draw the line */
1942 PropertiesLine prop_line = prepare_execmode_line(process);
1943 draw_line((void*)&prop_line, (void*)&draw_context);
44ffb95f 1944
67f72973 1945 hashed_process_data->x.over = x;
1946 }
44ffb95f 1947#endif //0
1948
67f72973 1949 if(unlikely(x == hashed_process_data->x.middle &&
1950 hashed_process_data->x.middle_used)) {
44ffb95f 1951#if 0 /* do not mark closure : not missing information */
67f72973 1952 if(hashed_process_data->x.middle_marked == FALSE) {
1953 /* Draw collision indicator */
1954 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1955 gdk_draw_point(drawing->pixmap,
1956 drawing->gc,
1957 x,
1958 y+(height/2)-3);
1959 hashed_process_data->x.middle_marked = TRUE;
1960 }
44ffb95f 1961#endif //0
67f72973 1962 /* Jump */
1963 } else {
1964 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1965 /* Draw the line */
1966 if(dodraw) {
1967 PropertiesLine prop_line;
1968 prop_line.line_width = STATE_LINE_WIDTH;
1969 prop_line.style = GDK_LINE_SOLID;
1970 prop_line.y = MIDDLE;
1971 if(hashed_process_data->type == RV_RESOURCE_CPU)
1972 cpu_set_line_color(&prop_line, &ts->cpu_states[process_info->id]);
1973 else if(hashed_process_data->type == RV_RESOURCE_IRQ)
1974 irq_set_line_color(&prop_line, &ts->irq_states[process_info->id]);
0305fe77 1975 else if(hashed_process_data->type == RV_RESOURCE_SOFT_IRQ)
1976 soft_irq_set_line_color(&prop_line, &ts->soft_irq_states[process_info->id]);
38726a78 1977 else if(hashed_process_data->type == RV_RESOURCE_TRAP)
1978 trap_set_line_color(&prop_line, &ts->trap_states[process_info->id]);
67f72973 1979 else if(hashed_process_data->type == RV_RESOURCE_BDEV) {
1980 gint devcode_gint = process_info->id;
1981 LttvBdevState *bdev = g_hash_table_lookup(ts->bdev_states, &devcode_gint);
1982 // the lookup may return null; bdev_set_line_color must act appropriately
1983 bdev_set_line_color(&prop_line, bdev);
44ffb95f 1984 }
67f72973 1985
1986 draw_line((void*)&prop_line, (void*)&draw_context);
1987 }
44ffb95f 1988
67f72973 1989 /* become the last x position */
1990 if(likely(x != hashed_process_data->x.middle)) {
1991 hashed_process_data->x.middle = x;
1992 /* but don't use the pixel */
1993 hashed_process_data->x.middle_used = FALSE;
44ffb95f 1994
67f72973 1995 /* Calculate the next good time */
1996 convert_pixels_to_time(width, x+1, time_window,
1997 &hashed_process_data->next_good_time);
44ffb95f 1998 }
1999 }
67f72973 2000 }
44ffb95f 2001 }
9e01e6d4 2002}
2003
2004int before_chunk(void *hook_data, void *call_data)
2005{
2006 EventsRequest *events_request = (EventsRequest*)hook_data;
2007 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2008 ControlFlowData *cfd = (ControlFlowData*)events_request->viewer_data;
2009#if 0
67f72973 2010 /* Deactivate sort */
9e01e6d4 2011 gtk_tree_sortable_set_sort_column_id(
2012 GTK_TREE_SORTABLE(cfd->process_list->list_store),
2013 TRACE_COLUMN,
2014 GTK_SORT_ASCENDING);
2015#endif //0
2016 drawing_chunk_begin(events_request, tss);
2017
2018 return 0;
2019}
2020
2021int before_request(void *hook_data, void *call_data)
2022{
2023 EventsRequest *events_request = (EventsRequest*)hook_data;
2024 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2025
2026 drawing_data_request_begin(events_request, tss);
2027
2028 return 0;
2029}
2030
2031
2032/*
2033 * after request is necessary in addition of after chunk in order to draw
2034 * lines until the end of the screen. after chunk just draws lines until
2035 * the last event.
2036 *
2037 * for each process
2038 * draw closing line
2039 * expose
2040 */
2041int after_request(void *hook_data, void *call_data)
2042{
67f72973 2043 guint i;
2044 EventsRequest *events_request = (EventsRequest*)hook_data;
2045 ControlFlowData *resourceview_data = events_request->viewer_data;
2046 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2047
2048 ProcessList *process_list = resourceview_data->process_list;
2049 LttTime end_time = events_request->end_time;
2050
2051 ClosureData closure_data;
2052 closure_data.events_request = (EventsRequest*)hook_data;
2053 closure_data.tss = tss;
2054 closure_data.end_time = end_time;
2055
2056 TimeWindow time_window =
2057 lttvwindow_get_time_window(resourceview_data->tab);
2058 guint width = resourceview_data->drawing->width;
2059 convert_time_to_pixels(
2060 time_window,
2061 end_time,
2062 width,
2063 &closure_data.x_end);
2064
2065
2066 /* Draw last items */
2067 for(i=0; i<RV_RESOURCE_COUNT; i++) {
2068 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data, i), draw_closure,
2069 (void*)&closure_data);
2070 }
2071
2072 /* Request expose */
2073 drawing_request_expose(events_request, tss, end_time);
9e01e6d4 2074 return 0;
2075}
2076
2077/*
2078 * for each process
2079 * draw closing line
2080 * expose
2081 */
2082int after_chunk(void *hook_data, void *call_data)
2083{
2084 EventsRequest *events_request = (EventsRequest*)hook_data;
67f72973 2085 ControlFlowData *resourceview_data = events_request->viewer_data;
9e01e6d4 2086 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2087 LttvTracesetContext *tsc = (LttvTracesetContext*)call_data;
2088 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
2089 LttTime end_time;
2090
67f72973 2091 ProcessList *process_list = resourceview_data->process_list;
9e01e6d4 2092 guint i;
2093 LttvTraceset *traceset = tsc->ts;
2094 guint nb_trace = lttv_traceset_number(traceset);
2095
2096 /* Only execute when called for the first trace's events request */
2097 if(!process_list->current_hash_data) return;
2098
2099 for(i = 0 ; i < nb_trace ; i++) {
2100 g_free(process_list->current_hash_data[i]);
2101 }
2102 g_free(process_list->current_hash_data);
2103 process_list->current_hash_data = NULL;
2104
2105 if(tfc != NULL)
2106 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
2107 else /* end of traceset, or position now out of request : end */
2108 end_time = events_request->end_time;
2109
2110 ClosureData closure_data;
2111 closure_data.events_request = (EventsRequest*)hook_data;
2112 closure_data.tss = tss;
2113 closure_data.end_time = end_time;
2114
2115 TimeWindow time_window =
67f72973 2116 lttvwindow_get_time_window(resourceview_data->tab);
2117 guint width = resourceview_data->drawing->width;
9e01e6d4 2118 convert_time_to_pixels(
2119 time_window,
2120 end_time,
2121 width,
2122 &closure_data.x_end);
2123
2124 /* Draw last items */
67f72973 2125 for(i=0; i<RV_RESOURCE_COUNT; i++) {
2126 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data, i), draw_closure,
9e01e6d4 2127 (void*)&closure_data);
67f72973 2128 }
9e01e6d4 2129#if 0
2130 /* Reactivate sort */
2131 gtk_tree_sortable_set_sort_column_id(
67f72973 2132 GTK_TREE_SORTABLE(resourceview_data->process_list->list_store),
9e01e6d4 2133 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2134 GTK_SORT_ASCENDING);
2135
67f72973 2136 update_index_to_pixmap(resourceview_data->process_list);
9e01e6d4 2137 /* Request a full expose : drawing scrambled */
67f72973 2138 gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
9e01e6d4 2139#endif //0
2140 /* Request expose (updates damages zone also) */
2141 drawing_request_expose(events_request, tss, end_time);
2142
2143 return 0;
2144}
2145
2146/* after_statedump_end
2147 *
2148 * @param hook_data ControlFlowData structure of the viewer.
2149 * @param call_data Event context.
2150 *
2151 * This function adds items to be drawn in a queue for each process.
2152 *
2153 */
2154int before_statedump_end(void *hook_data, void *call_data)
2155{
67f72973 2156 gint i;
2157
dd455fb8 2158 LttvTraceHook *th = (LttvTraceHook*)hook_data;
2159 EventsRequest *events_request = (EventsRequest*)th->hook_data;
67f72973 2160 ControlFlowData *resourceview_data = events_request->viewer_data;
9e01e6d4 2161
2162 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2163
2164 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
2165
2166 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
2167
2168 LttvTracesetState *tss = (LttvTracesetState*)tfc->t_context->ts_context;
67f72973 2169 ProcessList *process_list = resourceview_data->process_list;
9e01e6d4 2170
2171 LttEvent *e;
2172 e = ltt_tracefile_get_event(tfc->tf);
2173
67f72973 2174 LttvFilter *filter = resourceview_data->filter;
9e01e6d4 2175 if(filter != NULL && filter->head != NULL)
2176 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
2177 tfc->t_context->t,tfc,NULL,NULL))
2178 return FALSE;
2179
2180 LttTime evtime = ltt_event_time(e);
2181
2182 ClosureData closure_data;
2183 closure_data.events_request = events_request;
2184 closure_data.tss = tss;
2185 closure_data.end_time = evtime;
2186
2187 TimeWindow time_window =
67f72973 2188 lttvwindow_get_time_window(resourceview_data->tab);
2189 guint width = resourceview_data->drawing->width;
9e01e6d4 2190 convert_time_to_pixels(
2191 time_window,
2192 evtime,
2193 width,
2194 &closure_data.x_end);
2195
2196 /* Draw last items */
67f72973 2197
2198 for(i=0; i<RV_RESOURCE_COUNT; i++) {
2199 g_hash_table_foreach(resourcelist_get_resource_hash_table(resourceview_data, i), draw_closure,
9e01e6d4 2200 (void*)&closure_data);
67f72973 2201 }
9e01e6d4 2202#if 0
2203 /* Reactivate sort */
2204 gtk_tree_sortable_set_sort_column_id(
67f72973 2205 GTK_TREE_SORTABLE(resourceview_data->process_list->list_store),
9e01e6d4 2206 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2207 GTK_SORT_ASCENDING);
2208
67f72973 2209 update_index_to_pixmap(resourceview_data->process_list);
9e01e6d4 2210 /* Request a full expose : drawing scrambled */
67f72973 2211 gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
9e01e6d4 2212#endif //0
2213 /* Request expose (updates damages zone also) */
2214 drawing_request_expose(events_request, tss, evtime);
2215
2216 return 0;
2217}
This page took 0.123189 seconds and 4 git commands to generate.