Fix state.c handling of state dump thread state
[lttv.git] / lttv / modules / gui / controlflow / eventhooks.c
CommitLineData
ce0214a6 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
f0d936c0 20/*****************************************************************************
21 * Hooks to be called by the main window *
22 *****************************************************************************/
23
f0d936c0 24
b9a010a2 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 *
e92eabaf 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.
b9a010a2 31 *
e92eabaf 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.
b9a010a2 34 *
e92eabaf 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
b9a010a2 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
e92eabaf 40 * corresponding to it is over, which happens to be at the next before_schedchange
b9a010a2 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
4e4d11b3 48#ifdef HAVE_CONFIG_H
49#include <config.h>
50#endif
b9a010a2 51
cf6cb7e0 52//#define PANGO_ENABLE_BACKEND
558aa013 53#include <gtk/gtk.h>
54#include <gdk/gdk.h>
5f16133f 55#include <glib.h>
80a52ff8 56#include <assert.h>
50439712 57#include <string.h>
319e9d81 58#include <stdio.h>
5f16133f 59
cf6cb7e0 60//#include <pango/pango.h>
61
80a52ff8 62#include <ltt/event.h>
4ba42155 63#include <ltt/time.h>
2c82c4dc 64#include <ltt/trace.h>
80a52ff8 65
2a2fa4f0 66#include <lttv/lttv.h>
558aa013 67#include <lttv/hook.h>
80a52ff8 68#include <lttv/state.h>
2d262115 69#include <lttvwindow/lttvwindow.h>
6395d57c 70#include <lttvwindow/lttvwindowtraces.h>
0de51231 71#include <lttvwindow/support.h>
80a52ff8 72
f0d936c0 73
a117e3f7 74#include "eventhooks.h"
75#include "cfv.h"
76#include "processlist.h"
77#include "drawing.h"
5f16133f 78
80a52ff8 79
1a31868c 80#define MAX_PATH_LEN 256
3d27be8a 81#define STATE_LINE_WIDTH 6
5bb606ce 82#define COLLISION_POSITION(height) (((height - STATE_LINE_WIDTH)/2) -3)
1a31868c 83
0de51231 84extern GSList *g_legend_list;
85
b9a010a2 86
6395d57c 87/* Action to do when background computation completed.
88 *
e800cf84 89 * Wait for all the awaited computations to be over.
6395d57c 90 */
91
703b25fa 92static gint background_ready(void *hook_data, void *call_data)
6395d57c 93{
94 ControlFlowData *control_flow_data = (ControlFlowData *)hook_data;
6395d57c 95
e800cf84 96 control_flow_data->background_info_waiting--;
97
98 if(control_flow_data->background_info_waiting == 0) {
4a24fa1f 99 g_message("control flow viewer : background computation data ready.");
6395d57c 100
e800cf84 101 drawing_clear(control_flow_data->drawing);
102 processlist_clear(control_flow_data->process_list);
07390ec1 103 gtk_widget_set_size_request(
104 control_flow_data->drawing->drawing_area,
105 -1, processlist_get_height(control_flow_data->process_list));
e800cf84 106 redraw_notify(control_flow_data, NULL);
b9a010a2 107 }
6395d57c 108
109 return 0;
110}
111
112
113/* Request background computation. Verify if it is in progress or ready first.
e800cf84 114 * Only for each trace in the tab's traceset.
6395d57c 115 */
3f7f592e 116static void request_background_data(ControlFlowData *control_flow_data)
6395d57c 117{
e800cf84 118 LttvTracesetContext * tsc =
119 lttvwindow_get_traceset_context(control_flow_data->tab);
120 gint num_traces = lttv_traceset_number(tsc->ts);
6395d57c 121 gint i;
122 LttvTrace *trace;
7df20ca4 123 LttvTraceState *tstate;
6395d57c 124
125 LttvHooks *background_ready_hook =
126 lttv_hooks_new();
127 lttv_hooks_add(background_ready_hook, background_ready, control_flow_data,
128 LTTV_PRIO_DEFAULT);
e800cf84 129 control_flow_data->background_info_waiting = 0;
6395d57c 130
131 for(i=0;i<num_traces;i++) {
e800cf84 132 trace = lttv_traceset_get(tsc->ts, i);
7df20ca4 133 tstate = LTTV_TRACE_STATE(tsc->traces[i]);
6395d57c 134
7df20ca4 135 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE
136 && !tstate->has_precomputed_states) {
6395d57c 137
138 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
139 trace) == FALSE) {
140 /* We first remove requests that could have been done for the same
141 * information. Happens when two viewers ask for it before servicing
142 * starts.
143 */
93ac601b 144 if(!lttvwindowtraces_background_request_find(trace, "state"))
b5e17af5 145 lttvwindowtraces_background_request_queue(
146 main_window_get_widget(control_flow_data->tab), trace, "state");
6395d57c 147 lttvwindowtraces_background_notify_queue(control_flow_data,
148 trace,
149 ltt_time_infinite,
150 NULL,
151 background_ready_hook);
e800cf84 152 control_flow_data->background_info_waiting++;
6395d57c 153 } else { /* in progress */
154
155 lttvwindowtraces_background_notify_current(control_flow_data,
156 trace,
157 ltt_time_infinite,
158 NULL,
159 background_ready_hook);
e800cf84 160 control_flow_data->background_info_waiting++;
6395d57c 161 }
4368b993 162 } else {
7df20ca4 163 /* Data ready. By its nature, this viewer doesn't need to have
618fbcc1 164 * its data ready hook called there, because a background
4368b993 165 * request is always linked with a redraw.
166 */
6395d57c 167 }
4368b993 168
6395d57c 169 }
170
171 lttv_hooks_destroy(background_ready_hook);
172}
173
174
175
176
f0d936c0 177/**
178 * Event Viewer's constructor hook
179 *
180 * This constructor is given as a parameter to the menuitem and toolbar button
181 * registration. It creates the list.
ca0f8a8e 182 * @param tab A pointer to the parent tab.
f0d936c0 183 * @return The widget created.
184 */
185GtkWidget *
e433e6d6 186h_guicontrolflow(LttvPlugin *plugin)
f0d936c0 187{
e433e6d6 188 LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
189 Tab *tab = ptab->tab;
d47b33d2 190 g_info("h_guicontrolflow, %p", tab);
e433e6d6 191 ControlFlowData *control_flow_data = guicontrolflow(ptab);
a56a1ba4 192
ca0f8a8e 193 control_flow_data->tab = tab;
a56a1ba4 194
a56a1ba4 195 // Unreg done in the GuiControlFlow_Destructor
6395d57c 196 lttvwindow_register_traceset_notify(tab,
197 traceset_notify,
198 control_flow_data);
199
ca0f8a8e 200 lttvwindow_register_time_window_notify(tab,
224446ce 201 update_time_window_hook,
202 control_flow_data);
ca0f8a8e 203 lttvwindow_register_current_time_notify(tab,
224446ce 204 update_current_time_hook,
205 control_flow_data);
ca0f8a8e 206 lttvwindow_register_redraw_notify(tab,
207 redraw_notify,
208 control_flow_data);
209 lttvwindow_register_continue_notify(tab,
210 continue_notify,
211 control_flow_data);
667ca2a0 212 request_background_data(control_flow_data);
6395d57c 213
ca0f8a8e 214
68997a22 215 return guicontrolflow_get_widget(control_flow_data) ;
a56a1ba4 216
f0d936c0 217}
218
3cff8cc1 219int event_selected_hook(void *hook_data, void *call_data)
f0d936c0 220{
14963be0 221 guint *event_number = (guint*) call_data;
f0d936c0 222
2a2fa4f0 223 g_debug("DEBUG : event selected by main window : %u", *event_number);
a56a1ba4 224
2eef04b5 225 return 0;
f0d936c0 226}
227
9a1ec01b 228/* Function that selects the color of status&exemode line */
6550d711 229static inline PropertiesLine prepare_s_e_line(LttvProcessState *process)
9a1ec01b 230{
231 PropertiesLine prop_line;
5bb606ce 232 prop_line.line_width = STATE_LINE_WIDTH;
9a1ec01b 233 prop_line.style = GDK_LINE_SOLID;
234 prop_line.y = MIDDLE;
235 //GdkColormap *colormap = gdk_colormap_get_system();
236
9a1ec01b 237 if(process->state->s == LTTV_STATE_RUN) {
238 if(process->state->t == LTTV_STATE_USER_MODE)
239 prop_line.color = drawing_colors[COL_RUN_USER_MODE];
240 else if(process->state->t == LTTV_STATE_SYSCALL)
241 prop_line.color = drawing_colors[COL_RUN_SYSCALL];
242 else if(process->state->t == LTTV_STATE_TRAP)
243 prop_line.color = drawing_colors[COL_RUN_TRAP];
244 else if(process->state->t == LTTV_STATE_IRQ)
245 prop_line.color = drawing_colors[COL_RUN_IRQ];
faf074a3 246 else if(process->state->t == LTTV_STATE_SOFT_IRQ)
247 prop_line.color = drawing_colors[COL_RUN_SOFT_IRQ];
f044974e
MD
248 else if(process->state->t == LTTV_STATE_MAYBE_SYSCALL)
249 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
250 else if(process->state->t == LTTV_STATE_MAYBE_USER_MODE)
251 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
252 else if(process->state->t == LTTV_STATE_MAYBE_TRAP)
253 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
9a1ec01b 254 else if(process->state->t == LTTV_STATE_MODE_UNKNOWN)
255 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
256 else
257 g_assert(FALSE); /* RUNNING MODE UNKNOWN */
258 } else if(process->state->s == LTTV_STATE_WAIT) {
259 /* We don't show if we wait while in user mode, trap, irq or syscall */
260 prop_line.color = drawing_colors[COL_WAIT];
261 } else if(process->state->s == LTTV_STATE_WAIT_CPU) {
262 /* We don't show if we wait for CPU while in user mode, trap, irq
263 * or syscall */
264 prop_line.color = drawing_colors[COL_WAIT_CPU];
265 } else if(process->state->s == LTTV_STATE_ZOMBIE) {
266 prop_line.color = drawing_colors[COL_ZOMBIE];
267 } else if(process->state->s == LTTV_STATE_WAIT_FORK) {
268 prop_line.color = drawing_colors[COL_WAIT_FORK];
269 } else if(process->state->s == LTTV_STATE_EXIT) {
270 prop_line.color = drawing_colors[COL_EXIT];
271 } else if(process->state->s == LTTV_STATE_UNNAMED) {
272 prop_line.color = drawing_colors[COL_UNNAMED];
c7620c79 273 } else if(process->state->s == LTTV_STATE_DEAD) {
274 prop_line.color = drawing_colors[COL_DEAD];
b3fd4c02 275 } else {
276 g_critical("unknown state : %s", g_quark_to_string(process->state->s));
9a1ec01b 277 g_assert(FALSE); /* UNKNOWN STATE */
b3fd4c02 278 }
9a1ec01b 279
280 return prop_line;
281
282}
283
068572ab
CS
284/* Before try-wake-up hook. A process is being woken; we need to draw its line up to this point in time
285 in that colour. This is basically like exec-state, but the change applies to a process other than that
286 which is currently running. */
287
288int before_trywakeup_hook(void *hook_data, void *call_data)
289{
290 LttvTraceHook *th = (LttvTraceHook*)hook_data;
291 EventsRequest *events_request = (EventsRequest*)th->hook_data;
292 ControlFlowData *control_flow_data = events_request->viewer_data;
293
294 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
295
068572ab
CS
296 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
297
298 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
299 gint target_pid_saved = tfc->target_pid;
300
301 LttTime evtime = ltt_event_time(e);
302 LttvFilter *filter = control_flow_data->filter;
303
304 guint woken_pid;
305 gint woken_cpu;
306
307 woken_pid = ltt_event_get_int(e, lttv_trace_get_hook_field(th, 0));
308 woken_cpu = ltt_event_get_unsigned(e, lttv_trace_get_hook_field(th, 1));
309
310 tfc->target_pid = woken_pid;
311 if(!filter || !filter->head ||
312 lttv_filter_tree_parse(filter->head,e,tfc->tf,
313 tfc->t_context->t,tfc,NULL,NULL)) {
314
315 /* First, check if the woken process is in the state computation
316 * process list. If it is there, that means we must add it right now and
317 * draw items from the beginning of the read for it. If it is not
318 * present, it's a new process and it was not present : it will
319 * be added after the state update. TOCHECK: What does that last para mean? */
068572ab
CS
320 guint trace_num = ts->parent.index;
321 LttvProcessState *process = lttv_state_find_process(ts, woken_cpu, woken_pid);
322
323 if(process != NULL) {
324 /* Well, the woken process existed : we must get it in the process hash
325 * or add it, and draw its items.
326 */
327 /* Add process to process list (if not present) */
328 guint pl_height = 0;
329 HashedProcessData *hashed_process_data = NULL;
330 ProcessList *process_list = control_flow_data->process_list;
331 LttTime birth = process->creation_time;
332
333 hashed_process_data = processlist_get_process_data(process_list,
334 woken_pid,
335 process->cpu,
336 &birth,
337 trace_num);
338 if(hashed_process_data == NULL)
339 {
340 g_assert(woken_pid != process->ppid);
341 /* Process not present */
342 ProcessInfo *process_info;
343 Drawing_t *drawing = control_flow_data->drawing;
344 processlist_add(process_list,
345 drawing,
346 woken_pid,
347 process->tgid,
348 process->cpu,
349 process->ppid,
350 &birth,
351 trace_num,
352 process->name,
353 process->brand,
354 &pl_height,
355 &process_info,
356 &hashed_process_data);
357 gtk_widget_set_size_request(drawing->drawing_area,
358 -1,
359 pl_height);
360 gtk_widget_queue_draw(drawing->drawing_area);
361
362 }
363
364 /* Now, the process is in the state hash and our own process hash.
365 * We definitely can draw the items related to the ending state.
366 */
367
368 if(ltt_time_compare(hashed_process_data->next_good_time,
369 evtime) > 0)
370 {
371 if(hashed_process_data->x.middle_marked == FALSE) {
372
373 TimeWindow time_window =
374 lttvwindow_get_time_window(control_flow_data->tab);
375#ifdef EXTRA_CHECK
376 if(ltt_time_compare(evtime, time_window.start_time) == -1
377 || ltt_time_compare(evtime, time_window.end_time) == 1)
378 return FALSE;
379#endif //EXTRA_CHECK
380 Drawing_t *drawing = control_flow_data->drawing;
381 guint width = drawing->width;
382 guint x;
383 convert_time_to_pixels(
384 time_window,
385 evtime,
386 width,
387 &x);
388
389 /* Draw collision indicator */
390 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
391 gdk_draw_point(hashed_process_data->pixmap,
392 drawing->gc,
393 x,
394 COLLISION_POSITION(hashed_process_data->height));
395 hashed_process_data->x.middle_marked = TRUE;
396 }
397 } else {
398 TimeWindow time_window =
399 lttvwindow_get_time_window(control_flow_data->tab);
400#ifdef EXTRA_CHECK
401 if(ltt_time_compare(evtime, time_window.start_time) == -1
402 || ltt_time_compare(evtime, time_window.end_time) == 1)
403 return FALSE;
404#endif //EXTRA_CHECK
405 Drawing_t *drawing = control_flow_data->drawing;
406 guint width = drawing->width;
407 guint x;
408 convert_time_to_pixels(
409 time_window,
410 evtime,
411 width,
412 &x);
413
414
415 /* Jump over draw if we are at the same x position */
416 if(x == hashed_process_data->x.middle &&
417 hashed_process_data->x.middle_used)
418 {
419 if(hashed_process_data->x.middle_marked == FALSE) {
420 /* Draw collision indicator */
421 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
422 gdk_draw_point(hashed_process_data->pixmap,
423 drawing->gc,
424 x,
425 COLLISION_POSITION(hashed_process_data->height));
426 hashed_process_data->x.middle_marked = TRUE;
427 }
428 /* jump */
429 } else {
430 DrawContext draw_context;
431
432 /* Now create the drawing context that will be used to draw
433 * items related to the last state. */
434 draw_context.drawable = hashed_process_data->pixmap;
435 draw_context.gc = drawing->gc;
436 draw_context.pango_layout = drawing->pango_layout;
437 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
438 draw_context.drawinfo.end.x = x;
439
440 draw_context.drawinfo.y.over = 1;
441 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
442 draw_context.drawinfo.y.under = hashed_process_data->height;
443
444 draw_context.drawinfo.start.offset.over = 0;
445 draw_context.drawinfo.start.offset.middle = 0;
446 draw_context.drawinfo.start.offset.under = 0;
447 draw_context.drawinfo.end.offset.over = 0;
448 draw_context.drawinfo.end.offset.middle = 0;
449 draw_context.drawinfo.end.offset.under = 0;
450
451 {
452 /* Draw the line */
453 PropertiesLine prop_line = prepare_s_e_line(process);
454 draw_line((void*)&prop_line, (void*)&draw_context);
455
456 }
457 /* become the last x position */
458 hashed_process_data->x.middle = x;
459 hashed_process_data->x.middle_used = TRUE;
460 hashed_process_data->x.middle_marked = FALSE;
461
462 /* Calculate the next good time */
463 convert_pixels_to_time(width, x+1, time_window,
464 &hashed_process_data->next_good_time);
465 }
466 }
467 }
468 }
469
470 tfc->target_pid = target_pid_saved;
471
472 return 0;
473
474}
c8bba5fa 475
e92eabaf 476/* before_schedchange_hook
b9a010a2 477 *
f0d936c0 478 * This function basically draw lines and icons. Two types of lines are drawn :
479 * one small (3 pixels?) representing the state of the process and the second
480 * type is thicker (10 pixels?) representing on which CPU a process is running
481 * (and this only in running state).
482 *
483 * Extremums of the lines :
484 * x_min : time of the last event context for this process kept in memory.
485 * x_max : time of the current event.
486 * y : middle of the process in the process list. The process is found in the
487 * list, therefore is it's position in pixels.
488 *
489 * The choice of lines'color is defined by the context of the last event for this
490 * process.
491 */
b9a010a2 492
493
e92eabaf 494int before_schedchange_hook(void *hook_data, void *call_data)
f0d936c0 495{
dd455fb8 496 LttvTraceHook *th = (LttvTraceHook*)hook_data;
497 EventsRequest *events_request = (EventsRequest*)th->hook_data;
b9a010a2 498 ControlFlowData *control_flow_data = events_request->viewer_data;
499
500 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
501
502 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
348c6ba8 503 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
b9a010a2 504
505 LttEvent *e;
2c82c4dc 506 e = ltt_tracefile_get_event(tfc->tf);
e38d9ea0 507 gint target_pid_saved = tfc->target_pid;
b9a010a2 508
509 LttTime evtime = ltt_event_time(e);
e38d9ea0 510 LttvFilter *filter = control_flow_data->filter;
fd22065b 511
10a1069a 512 /* we are in a schedchange, before the state update. We must draw the
513 * items corresponding to the state before it changes : now is the right
514 * time to do it.
515 */
b9a010a2 516
10a1069a 517 guint pid_out;
518 guint pid_in;
c7620c79 519 guint state_out;
10a1069a 520 {
04348950 521 pid_out = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
522 pid_in = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
c7620c79 523 state_out = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 2));
10a1069a 524 }
525
e38d9ea0 526 tfc->target_pid = pid_out;
527 if(!filter || !filter->head ||
528 lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 529 tfc->t_context->t,tfc,NULL,NULL)) {
10a1069a 530 /* For the pid_out */
531 /* First, check if the current process is in the state computation
532 * process list. If it is there, that means we must add it right now and
533 * draw items from the beginning of the read for it. If it is not
534 * present, it's a new process and it was not present : it will
535 * be added after the state update. */
ae3d0f50 536 guint cpu = tfs->cpu;
0f090e21 537 guint trace_num = ts->parent.index;
348c6ba8 538 LttvProcessState *process = ts->running_process[cpu];
40debf7b 539 /* unknown state, bad current pid */
348c6ba8 540 if(process->pid != pid_out)
800aa029 541 process = lttv_state_find_process(ts,
ae3d0f50 542 tfs->cpu, pid_out);
b9a010a2 543
10a1069a 544 if(process != NULL) {
545 /* Well, the process_out existed : we must get it in the process hash
546 * or add it, and draw its items.
547 */
548 /* Add process to process list (if not present) */
1c736ed5 549 guint pl_height = 0;
10a1069a 550 HashedProcessData *hashed_process_data = NULL;
5c230fc4 551 ProcessList *process_list = control_flow_data->process_list;
10a1069a 552 LttTime birth = process->creation_time;
b9a010a2 553
ac4e21cf 554 hashed_process_data = processlist_get_process_data(process_list,
10a1069a 555 pid_out,
348c6ba8 556 process->cpu,
10a1069a 557 &birth,
0f090e21 558 trace_num);
ac4e21cf 559 if(hashed_process_data == NULL)
10a1069a 560 {
561 g_assert(pid_out == 0 || pid_out != process->ppid);
562 /* Process not present */
4e86ae2e 563 ProcessInfo *process_info;
1c736ed5 564 Drawing_t *drawing = control_flow_data->drawing;
10a1069a 565 processlist_add(process_list,
1c736ed5 566 drawing,
10a1069a 567 pid_out,
fcc08e1e 568 process->tgid,
348c6ba8 569 process->cpu,
10a1069a 570 process->ppid,
571 &birth,
0f090e21 572 trace_num,
f4b88a7d 573 process->name,
7b5f6cf1 574 process->brand,
10a1069a 575 &pl_height,
4e86ae2e 576 &process_info,
10a1069a 577 &hashed_process_data);
1c736ed5 578 gtk_widget_set_size_request(drawing->drawing_area,
579 -1,
580 pl_height);
581 gtk_widget_queue_draw(drawing->drawing_area);
582
10a1069a 583 }
ac4e21cf 584
10a1069a 585 /* Now, the process is in the state hash and our own process hash.
586 * We definitely can draw the items related to the ending state.
587 */
e800cf84 588
b2743953 589 if(ltt_time_compare(hashed_process_data->next_good_time,
590 evtime) > 0)
10a1069a 591 {
b2743953 592 if(hashed_process_data->x.middle_marked == FALSE) {
ac4e21cf 593
fd22065b 594 TimeWindow time_window =
595 lttvwindow_get_time_window(control_flow_data->tab);
596#ifdef EXTRA_CHECK
597 if(ltt_time_compare(evtime, time_window.start_time) == -1
598 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 599 return FALSE;
fd22065b 600#endif //EXTRA_CHECK
d6fef890 601 Drawing_t *drawing = control_flow_data->drawing;
96947fcf 602 guint width = drawing->width;
b2743953 603 guint x;
604 convert_time_to_pixels(
605 time_window,
606 evtime,
607 width,
608 &x);
609
610 /* Draw collision indicator */
611 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1c736ed5 612 gdk_draw_point(hashed_process_data->pixmap,
b2743953 613 drawing->gc,
614 x,
5bb606ce 615 COLLISION_POSITION(hashed_process_data->height));
b2743953 616 hashed_process_data->x.middle_marked = TRUE;
617 }
618 } else {
ac4e21cf 619 TimeWindow time_window =
620 lttvwindow_get_time_window(control_flow_data->tab);
fd22065b 621#ifdef EXTRA_CHECK
ac4e21cf 622 if(ltt_time_compare(evtime, time_window.start_time) == -1
623 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 624 return FALSE;
fd22065b 625#endif //EXTRA_CHECK
d6fef890 626 Drawing_t *drawing = control_flow_data->drawing;
96947fcf 627 guint width = drawing->width;
10a1069a 628 guint x;
10a1069a 629 convert_time_to_pixels(
a18124ff 630 time_window,
4b7dc462 631 evtime,
632 width,
633 &x);
10a1069a 634
10a1069a 635
4b7dc462 636 /* Jump over draw if we are at the same x position */
e72908ed 637 if(x == hashed_process_data->x.middle &&
638 hashed_process_data->x.middle_used)
e800cf84 639 {
e72908ed 640 if(hashed_process_data->x.middle_marked == FALSE) {
641 /* Draw collision indicator */
642 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1c736ed5 643 gdk_draw_point(hashed_process_data->pixmap,
e72908ed 644 drawing->gc,
645 x,
5bb606ce 646 COLLISION_POSITION(hashed_process_data->height));
de4ea1ad 647 hashed_process_data->x.middle_marked = TRUE;
e72908ed 648 }
4b7dc462 649 /* jump */
650 } else {
651 DrawContext draw_context;
10a1069a 652
4b7dc462 653 /* Now create the drawing context that will be used to draw
654 * items related to the last state. */
1c736ed5 655 draw_context.drawable = hashed_process_data->pixmap;
4b7dc462 656 draw_context.gc = drawing->gc;
657 draw_context.pango_layout = drawing->pango_layout;
658 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
659 draw_context.drawinfo.end.x = x;
660
1c736ed5 661 draw_context.drawinfo.y.over = 1;
662 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
663 draw_context.drawinfo.y.under = hashed_process_data->height;
4b7dc462 664
665 draw_context.drawinfo.start.offset.over = 0;
666 draw_context.drawinfo.start.offset.middle = 0;
667 draw_context.drawinfo.start.offset.under = 0;
668 draw_context.drawinfo.end.offset.over = 0;
669 draw_context.drawinfo.end.offset.middle = 0;
670 draw_context.drawinfo.end.offset.under = 0;
671
672 {
673 /* Draw the line */
9a1ec01b 674 PropertiesLine prop_line = prepare_s_e_line(process);
4b7dc462 675 draw_line((void*)&prop_line, (void*)&draw_context);
676
677 }
678 /* become the last x position */
679 hashed_process_data->x.middle = x;
e72908ed 680 hashed_process_data->x.middle_used = TRUE;
681 hashed_process_data->x.middle_marked = FALSE;
b2743953 682
683 /* Calculate the next good time */
684 convert_pixels_to_time(width, x+1, time_window,
685 &hashed_process_data->next_good_time);
e800cf84 686 }
687 }
688 }
10a1069a 689 }
e800cf84 690
e38d9ea0 691 tfc->target_pid = pid_in;
692 if(!filter || !filter->head ||
693 lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 694 tfc->t_context->t,tfc,NULL,NULL)) {
10a1069a 695 /* For the pid_in */
696 /* First, check if the current process is in the state computation
697 * process list. If it is there, that means we must add it right now and
698 * draw items from the beginning of the read for it. If it is not
699 * present, it's a new process and it was not present : it will
700 * be added after the state update. */
701 LttvProcessState *process;
800aa029 702 process = lttv_state_find_process(ts,
ae3d0f50 703 tfs->cpu, pid_in);
0f090e21 704 guint trace_num = ts->parent.index;
10a1069a 705
706 if(process != NULL) {
800aa029 707 /* Well, the process existed : we must get it in the process hash
10a1069a 708 * or add it, and draw its items.
709 */
710 /* Add process to process list (if not present) */
1c736ed5 711 guint pl_height = 0;
10a1069a 712 HashedProcessData *hashed_process_data = NULL;
5c230fc4 713 ProcessList *process_list = control_flow_data->process_list;
10a1069a 714 LttTime birth = process->creation_time;
e800cf84 715
ac4e21cf 716 hashed_process_data = processlist_get_process_data(process_list,
10a1069a 717 pid_in,
ae3d0f50 718 tfs->cpu,
10a1069a 719 &birth,
0f090e21 720 trace_num);
ac4e21cf 721 if(hashed_process_data == NULL)
10a1069a 722 {
723 g_assert(pid_in == 0 || pid_in != process->ppid);
724 /* Process not present */
4e86ae2e 725 ProcessInfo *process_info;
1c736ed5 726 Drawing_t *drawing = control_flow_data->drawing;
10a1069a 727 processlist_add(process_list,
1c736ed5 728 drawing,
10a1069a 729 pid_in,
fcc08e1e 730 process->tgid,
ae3d0f50 731 tfs->cpu,
10a1069a 732 process->ppid,
733 &birth,
0f090e21 734 trace_num,
f4b88a7d 735 process->name,
7b5f6cf1 736 process->brand,
10a1069a 737 &pl_height,
4e86ae2e 738 &process_info,
10a1069a 739 &hashed_process_data);
1c736ed5 740 gtk_widget_set_size_request(drawing->drawing_area,
741 -1,
742 pl_height);
743 gtk_widget_queue_draw(drawing->drawing_area);
744
10a1069a 745 }
40debf7b 746 //We could set the current process and hash here, but will be done
747 //by after schedchange hook
10a1069a 748
749 /* Now, the process is in the state hash and our own process hash.
750 * We definitely can draw the items related to the ending state.
751 */
b9a010a2 752
b2743953 753 if(ltt_time_compare(hashed_process_data->next_good_time,
754 evtime) > 0)
10a1069a 755 {
b2743953 756 if(hashed_process_data->x.middle_marked == FALSE) {
ac4e21cf 757
fd22065b 758 TimeWindow time_window =
759 lttvwindow_get_time_window(control_flow_data->tab);
760#ifdef EXTRA_CHECK
761 if(ltt_time_compare(evtime, time_window.start_time) == -1
762 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 763 return FALSE;
fd22065b 764#endif //EXTRA_CHECK
d6fef890 765 Drawing_t *drawing = control_flow_data->drawing;
96947fcf 766 guint width = drawing->width;
b2743953 767 guint x;
768 convert_time_to_pixels(
769 time_window,
770 evtime,
771 width,
772 &x);
773
774 /* Draw collision indicator */
775 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1c736ed5 776 gdk_draw_point(hashed_process_data->pixmap,
b2743953 777 drawing->gc,
778 x,
5bb606ce 779 COLLISION_POSITION(hashed_process_data->height));
b2743953 780 hashed_process_data->x.middle_marked = TRUE;
781 }
782 } else {
fd22065b 783 TimeWindow time_window =
784 lttvwindow_get_time_window(control_flow_data->tab);
785#ifdef EXTRA_CHECK
786 if(ltt_time_compare(evtime, time_window.start_time) == -1
787 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 788 return FALSE;
fd22065b 789#endif //EXTRA_CHECK
d6fef890 790 Drawing_t *drawing = control_flow_data->drawing;
96947fcf 791 guint width = drawing->width;
10a1069a 792 guint x;
10a1069a 793
794 convert_time_to_pixels(
a18124ff 795 time_window,
4b7dc462 796 evtime,
797 width,
798 &x);
10a1069a 799
10a1069a 800
4b7dc462 801 /* Jump over draw if we are at the same x position */
e72908ed 802 if(x == hashed_process_data->x.middle &&
803 hashed_process_data->x.middle_used)
4b7dc462 804 {
e72908ed 805 if(hashed_process_data->x.middle_marked == FALSE) {
806 /* Draw collision indicator */
807 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1c736ed5 808 gdk_draw_point(hashed_process_data->pixmap,
e72908ed 809 drawing->gc,
810 x,
5bb606ce 811 COLLISION_POSITION(hashed_process_data->height));
de4ea1ad 812 hashed_process_data->x.middle_marked = TRUE;
e72908ed 813 }
4b7dc462 814 /* jump */
815 } else {
816 DrawContext draw_context;
10a1069a 817
4b7dc462 818 /* Now create the drawing context that will be used to draw
819 * items related to the last state. */
1c736ed5 820 draw_context.drawable = hashed_process_data->pixmap;
4b7dc462 821 draw_context.gc = drawing->gc;
822 draw_context.pango_layout = drawing->pango_layout;
823 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
824 draw_context.drawinfo.end.x = x;
10a1069a 825
1c736ed5 826 draw_context.drawinfo.y.over = 1;
827 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
828 draw_context.drawinfo.y.under = hashed_process_data->height;
10a1069a 829
4b7dc462 830 draw_context.drawinfo.start.offset.over = 0;
831 draw_context.drawinfo.start.offset.middle = 0;
832 draw_context.drawinfo.start.offset.under = 0;
833 draw_context.drawinfo.end.offset.over = 0;
834 draw_context.drawinfo.end.offset.middle = 0;
835 draw_context.drawinfo.end.offset.under = 0;
836
837 {
838 /* Draw the line */
9a1ec01b 839 PropertiesLine prop_line = prepare_s_e_line(process);
4b7dc462 840 draw_line((void*)&prop_line, (void*)&draw_context);
841 }
842
843
844 /* become the last x position */
845 hashed_process_data->x.middle = x;
e72908ed 846 hashed_process_data->x.middle_used = TRUE;
847 hashed_process_data->x.middle_marked = FALSE;
b2743953 848
849 /* Calculate the next good time */
850 convert_pixels_to_time(width, x+1, time_window,
851 &hashed_process_data->next_good_time);
4b7dc462 852 }
c8bba5fa 853 }
8e680509 854 } else
855 g_warning("Cannot find pin_in in schedchange %u", pid_in);
b9a010a2 856 }
e38d9ea0 857 tfc->target_pid = target_pid_saved;
b9a010a2 858 return 0;
859
860
b9a010a2 861
a56a1ba4 862
51705146 863 /* Text dump */
80a52ff8 864#ifdef DONTSHOW
a56a1ba4 865 GString *string = g_string_new("");;
866 gboolean field_names = TRUE, state = TRUE;
80a52ff8 867
e9a9c513 868 lttv_event_to_string(e, tfc->tf, string, TRUE, field_names, tfs);
869 g_string_append_printf(string,"\n");
870
871 if(state) {
872 g_string_append_printf(string, " %s",
873 g_quark_to_string(tfs->process->state->s));
874 }
875
876 g_info("%s",string->str);
877
a56a1ba4 878 g_string_free(string, TRUE);
879
880 /* End of text dump */
80a52ff8 881#endif //DONTSHOW
50439712 882
f0d936c0 883}
884
e92eabaf 885/* after_schedchange_hook
b9a010a2 886 *
887 * The draw after hook is called by the reading API to have a
888 * particular event drawn on the screen.
889 * @param hook_data ControlFlowData structure of the viewer.
890 * @param call_data Event context.
891 *
892 * This function adds items to be drawn in a queue for each process.
893 *
894 */
e92eabaf 895int after_schedchange_hook(void *hook_data, void *call_data)
f0d936c0 896{
dd455fb8 897 LttvTraceHook *th = (LttvTraceHook*)hook_data;
898 EventsRequest *events_request = (EventsRequest*)th->hook_data;
ca0f8a8e 899 ControlFlowData *control_flow_data = events_request->viewer_data;
50439712 900
a56a1ba4 901 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
50439712 902
903 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
904
348c6ba8 905 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
906
b9a010a2 907 LttEvent *e;
2c82c4dc 908 e = ltt_tracefile_get_event(tfc->tf);
b9a010a2 909
e38d9ea0 910 LttvFilter *filter = control_flow_data->filter;
b9a010a2 911 LttTime evtime = ltt_event_time(e);
b9a010a2 912
10a1069a 913 /* Add process to process list (if not present) */
2eef04b5 914 LttvProcessState *process_in;
10a1069a 915 LttTime birth;
1c736ed5 916 guint pl_height = 0;
10a1069a 917 HashedProcessData *hashed_process_data_in = NULL;
b9a010a2 918
5c230fc4 919 ProcessList *process_list = control_flow_data->process_list;
10a1069a 920
921 guint pid_in;
922 {
923 guint pid_out;
04348950 924 pid_out = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
925 pid_in = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
10a1069a 926 }
b9a010a2 927
c7620c79 928 tfc->target_pid = pid_in;
929 if(!filter || !filter->head ||
930 lttv_filter_tree_parse(filter->head,e,tfc->tf,
931 tfc->t_context->t,tfc,NULL,NULL)) {
932 /* Find process pid_in in the list... */
933 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
934 //process_in = tfs->process;
935 guint cpu = tfs->cpu;
936 guint trace_num = ts->parent.index;
937 process_in = ts->running_process[cpu];
938 /* It should exist, because we are after the state update. */
96947fcf 939#ifdef EXTRA_CHECK
c7620c79 940 g_assert(process_in != NULL);
96947fcf 941#endif //EXTRA_CHECK
c7620c79 942 birth = process_in->creation_time;
943
944 hashed_process_data_in = processlist_get_process_data(process_list,
945 pid_in,
946 process_in->cpu,
947 &birth,
948 trace_num);
949 if(hashed_process_data_in == NULL)
950 {
951 g_assert(pid_in == 0 || pid_in != process_in->ppid);
952 ProcessInfo *process_info;
953 Drawing_t *drawing = control_flow_data->drawing;
954 /* Process not present */
955 processlist_add(process_list,
956 drawing,
10a1069a 957 pid_in,
c7620c79 958 process_in->tgid,
348c6ba8 959 process_in->cpu,
c7620c79 960 process_in->ppid,
10a1069a 961 &birth,
c7620c79 962 trace_num,
963 process_in->name,
964 process_in->brand,
965 &pl_height,
966 &process_info,
967 &hashed_process_data_in);
968 gtk_widget_set_size_request(drawing->drawing_area,
969 -1,
970 pl_height);
971 gtk_widget_queue_draw(drawing->drawing_area);
972 }
973 /* Set the current process */
974 process_list->current_hash_data[trace_num][process_in->cpu] =
975 hashed_process_data_in;
976
977 if(ltt_time_compare(hashed_process_data_in->next_good_time,
978 evtime) <= 0)
979 {
980 TimeWindow time_window =
981 lttvwindow_get_time_window(control_flow_data->tab);
982
fd22065b 983#ifdef EXTRA_CHECK
c7620c79 984 if(ltt_time_compare(evtime, time_window.start_time) == -1
985 || ltt_time_compare(evtime, time_window.end_time) == 1)
986 return FALSE;
fd22065b 987#endif //EXTRA_CHECK
c7620c79 988 Drawing_t *drawing = control_flow_data->drawing;
989 guint width = drawing->width;
990 guint new_x;
991
992 convert_time_to_pixels(
993 time_window,
994 evtime,
995 width,
996 &new_x);
997
998 if(hashed_process_data_in->x.middle != new_x) {
999 hashed_process_data_in->x.middle = new_x;
1000 hashed_process_data_in->x.middle_used = FALSE;
1001 hashed_process_data_in->x.middle_marked = FALSE;
1002 }
b2743953 1003 }
1004 }
c7620c79 1005
b9a010a2 1006 return 0;
4a24fa1f 1007}
b9a010a2 1008
1009
1010
e72908ed 1011
4a24fa1f 1012/* before_execmode_hook
1013 *
1014 * This function basically draw lines and icons. Two types of lines are drawn :
1015 * one small (3 pixels?) representing the state of the process and the second
1016 * type is thicker (10 pixels?) representing on which CPU a process is running
1017 * (and this only in running state).
1018 *
1019 * Extremums of the lines :
1020 * x_min : time of the last event context for this process kept in memory.
1021 * x_max : time of the current event.
1022 * y : middle of the process in the process list. The process is found in the
1023 * list, therefore is it's position in pixels.
1024 *
1025 * The choice of lines'color is defined by the context of the last event for this
1026 * process.
1027 */
1028
e72908ed 1029
4a24fa1f 1030int before_execmode_hook(void *hook_data, void *call_data)
1031{
dd455fb8 1032 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1033 EventsRequest *events_request = (EventsRequest*)th->hook_data;
b9a010a2 1034 ControlFlowData *control_flow_data = events_request->viewer_data;
1035
1036 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1037
1038 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
b9a010a2 1039
4a24fa1f 1040 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1041
50439712 1042 LttEvent *e;
4a24fa1f 1043 e = ltt_tracefile_get_event(tfc->tf);
50439712 1044
e38d9ea0 1045 LttvFilter *filter = control_flow_data->filter;
1046 if(filter != NULL && filter->head != NULL)
1047 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1048 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1049 return FALSE;
1050
9444deae 1051 LttTime evtime = ltt_event_time(e);
9444deae 1052
4a24fa1f 1053 /* we are in a execmode, before the state update. We must draw the
1054 * items corresponding to the state before it changes : now is the right
1055 * time to do it.
1056 */
1057 /* For the pid */
1058 //LttvProcessState *process = tfs->process;
ae3d0f50 1059 guint cpu = tfs->cpu;
0f090e21 1060 guint trace_num = ts->parent.index;
4a24fa1f 1061 LttvProcessState *process = ts->running_process[cpu];
1062 g_assert(process != NULL);
23093869 1063
10a1069a 1064 guint pid = process->pid;
23093869 1065
10a1069a 1066 /* Well, the process_out existed : we must get it in the process hash
1067 * or add it, and draw its items.
1068 */
1069 /* Add process to process list (if not present) */
1c736ed5 1070 guint pl_height = 0;
10a1069a 1071 HashedProcessData *hashed_process_data = NULL;
5c230fc4 1072 ProcessList *process_list = control_flow_data->process_list;
10a1069a 1073 LttTime birth = process->creation_time;
40debf7b 1074
0f090e21 1075 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1076 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
40debf7b 1077 } else {
ac4e21cf 1078 hashed_process_data = processlist_get_process_data(process_list,
40debf7b 1079 pid,
348c6ba8 1080 process->cpu,
40debf7b 1081 &birth,
0f090e21 1082 trace_num);
1d1df11d 1083 if(unlikely(hashed_process_data == NULL))
40debf7b 1084 {
1085 g_assert(pid == 0 || pid != process->ppid);
1086 ProcessInfo *process_info;
1087 /* Process not present */
1c736ed5 1088 Drawing_t *drawing = control_flow_data->drawing;
40debf7b 1089 processlist_add(process_list,
1c736ed5 1090 drawing,
40debf7b 1091 pid,
fcc08e1e 1092 process->tgid,
348c6ba8 1093 process->cpu,
40debf7b 1094 process->ppid,
1095 &birth,
0f090e21 1096 trace_num,
f4b88a7d 1097 process->name,
7b5f6cf1 1098 process->brand,
40debf7b 1099 &pl_height,
1100 &process_info,
1101 &hashed_process_data);
1c736ed5 1102 gtk_widget_set_size_request(drawing->drawing_area,
1103 -1,
1104 pl_height);
1105 gtk_widget_queue_draw(drawing->drawing_area);
40debf7b 1106 }
1107 /* Set the current process */
0f090e21 1108 process_list->current_hash_data[trace_num][process->cpu] =
40debf7b 1109 hashed_process_data;
10a1069a 1110 }
23093869 1111
10a1069a 1112 /* Now, the process is in the state hash and our own process hash.
1113 * We definitely can draw the items related to the ending state.
1114 */
b2743953 1115
1d1df11d 1116 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1117 evtime) > 0))
10a1069a 1118 {
1d1df11d 1119 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
fd22065b 1120 TimeWindow time_window =
1121 lttvwindow_get_time_window(control_flow_data->tab);
1122
1123#ifdef EXTRA_CHECK
1124 if(ltt_time_compare(evtime, time_window.start_time) == -1
1125 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1126 return FALSE;
fd22065b 1127#endif //EXTRA_CHECK
d6fef890 1128 Drawing_t *drawing = control_flow_data->drawing;
96947fcf 1129 guint width = drawing->width;
b2743953 1130 guint x;
1131 convert_time_to_pixels(
1132 time_window,
1133 evtime,
1134 width,
1135 &x);
1136
1137 /* Draw collision indicator */
1138 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1c736ed5 1139 gdk_draw_point(hashed_process_data->pixmap,
b2743953 1140 drawing->gc,
1141 x,
5bb606ce 1142 COLLISION_POSITION(hashed_process_data->height));
b2743953 1143 hashed_process_data->x.middle_marked = TRUE;
1144 }
1145 } else {
fd22065b 1146 TimeWindow time_window =
1147 lttvwindow_get_time_window(control_flow_data->tab);
1148
1149#ifdef EXTRA_CHECK
1150 if(ltt_time_compare(evtime, time_window.start_time) == -1
1151 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1152 return FALSE;
fd22065b 1153#endif //EXTRA_CHECK
d6fef890 1154 Drawing_t *drawing = control_flow_data->drawing;
96947fcf 1155 guint width = drawing->width;
10a1069a 1156 guint x;
dbd243b1 1157
10a1069a 1158 convert_time_to_pixels(
a18124ff 1159 time_window,
10a1069a 1160 evtime,
1161 width,
1162 &x);
dbd243b1 1163
23093869 1164
4b7dc462 1165 /* Jump over draw if we are at the same x position */
1d1df11d 1166 if(unlikely(x == hashed_process_data->x.middle &&
1167 hashed_process_data->x.middle_used))
10a1069a 1168 {
1d1df11d 1169 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
e72908ed 1170 /* Draw collision indicator */
1171 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1c736ed5 1172 gdk_draw_point(hashed_process_data->pixmap,
e72908ed 1173 drawing->gc,
1174 x,
5bb606ce 1175 COLLISION_POSITION(hashed_process_data->height));
de4ea1ad 1176 hashed_process_data->x.middle_marked = TRUE;
e72908ed 1177 }
4b7dc462 1178 /* jump */
1179 } else {
1180
1181 DrawContext draw_context;
1182 /* Now create the drawing context that will be used to draw
1183 * items related to the last state. */
1c736ed5 1184 draw_context.drawable = hashed_process_data->pixmap;
4b7dc462 1185 draw_context.gc = drawing->gc;
1186 draw_context.pango_layout = drawing->pango_layout;
9a1ec01b 1187 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
4b7dc462 1188 draw_context.drawinfo.end.x = x;
1189
1c736ed5 1190 draw_context.drawinfo.y.over = 1;
1191 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1192 draw_context.drawinfo.y.under = hashed_process_data->height;
4b7dc462 1193
1194 draw_context.drawinfo.start.offset.over = 0;
1195 draw_context.drawinfo.start.offset.middle = 0;
1196 draw_context.drawinfo.start.offset.under = 0;
1197 draw_context.drawinfo.end.offset.over = 0;
1198 draw_context.drawinfo.end.offset.middle = 0;
1199 draw_context.drawinfo.end.offset.under = 0;
1200
1201 {
1202 /* Draw the line */
9a1ec01b 1203 PropertiesLine prop_line = prepare_s_e_line(process);
4b7dc462 1204 draw_line((void*)&prop_line, (void*)&draw_context);
23093869 1205
4b7dc462 1206 }
1207 /* become the last x position */
9a1ec01b 1208 hashed_process_data->x.middle = x;
e72908ed 1209 hashed_process_data->x.middle_used = TRUE;
1210 hashed_process_data->x.middle_marked = FALSE;
b2743953 1211
1212 /* Calculate the next good time */
1213 convert_pixels_to_time(width, x+1, time_window,
1214 &hashed_process_data->next_good_time);
23093869 1215 }
1216 }
1217
1218 return 0;
1219}
1220
4a24fa1f 1221/* before_process_exit_hook
23093869 1222 *
4a24fa1f 1223 * Draw lines for process event.
1224 *
23093869 1225 * @param hook_data ControlFlowData structure of the viewer.
1226 * @param call_data Event context.
1227 *
1228 * This function adds items to be drawn in a queue for each process.
1229 *
1230 */
8869ac08 1231
1232
4a24fa1f 1233int before_process_exit_hook(void *hook_data, void *call_data)
1234{
dd455fb8 1235 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1236 EventsRequest *events_request = (EventsRequest*)th->hook_data;
4a24fa1f 1237
23093869 1238 ControlFlowData *control_flow_data = events_request->viewer_data;
1239
1240 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1241
1242 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
23093869 1243
4a24fa1f 1244 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1245
23093869 1246 LttEvent *e;
2c82c4dc 1247 e = ltt_tracefile_get_event(tfc->tf);
23093869 1248
e38d9ea0 1249 LttvFilter *filter = control_flow_data->filter;
1250 if(filter != NULL && filter->head != NULL)
1251 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1252 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1253 return FALSE;
1254
23093869 1255 LttTime evtime = ltt_event_time(e);
23093869 1256
10a1069a 1257 /* Add process to process list (if not present) */
4a24fa1f 1258 //LttvProcessState *process = tfs->process;
ae3d0f50 1259 guint cpu = tfs->cpu;
0f090e21 1260 guint trace_num = ts->parent.index;
4a24fa1f 1261 LttvProcessState *process = ts->running_process[cpu];
1262 guint pid = process->pid;
10a1069a 1263 LttTime birth;
1c736ed5 1264 guint pl_height = 0;
10a1069a 1265 HashedProcessData *hashed_process_data = NULL;
23093869 1266
5c230fc4 1267 ProcessList *process_list = control_flow_data->process_list;
4a24fa1f 1268
10a1069a 1269 g_assert(process != NULL);
23093869 1270
10a1069a 1271 birth = process->creation_time;
23093869 1272
0f090e21 1273 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1274 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
40debf7b 1275 } else {
ac4e21cf 1276 hashed_process_data = processlist_get_process_data(process_list,
4a24fa1f 1277 pid,
1278 process->cpu,
1279 &birth,
0f090e21 1280 trace_num);
1d1df11d 1281 if(unlikely(hashed_process_data == NULL))
40debf7b 1282 {
1283 g_assert(pid == 0 || pid != process->ppid);
1284 /* Process not present */
1c736ed5 1285 Drawing_t *drawing = control_flow_data->drawing;
40debf7b 1286 ProcessInfo *process_info;
1287 processlist_add(process_list,
1c736ed5 1288 drawing,
40debf7b 1289 pid,
fcc08e1e 1290 process->tgid,
4a24fa1f 1291 process->cpu,
40debf7b 1292 process->ppid,
1293 &birth,
0f090e21 1294 trace_num,
4a24fa1f 1295 process->name,
7b5f6cf1 1296 process->brand,
40debf7b 1297 &pl_height,
1298 &process_info,
1299 &hashed_process_data);
4a24fa1f 1300 gtk_widget_set_size_request(drawing->drawing_area,
1301 -1,
1302 pl_height);
1303 gtk_widget_queue_draw(drawing->drawing_area);
40debf7b 1304 }
23093869 1305 }
40debf7b 1306
4a24fa1f 1307 /* Now, the process is in the state hash and our own process hash.
1308 * We definitely can draw the items related to the ending state.
1309 */
1310
1311 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1312 evtime) > 0))
b2743953 1313 {
4a24fa1f 1314 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1315 TimeWindow time_window =
1316 lttvwindow_get_time_window(control_flow_data->tab);
1317
1318#ifdef EXTRA_CHECK
1319 if(ltt_time_compare(evtime, time_window.start_time) == -1
1320 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1321 return FALSE;
4a24fa1f 1322#endif //EXTRA_CHECK
1323 Drawing_t *drawing = control_flow_data->drawing;
1324 guint width = drawing->width;
1325 guint x;
1326 convert_time_to_pixels(
1327 time_window,
1328 evtime,
1329 width,
1330 &x);
1331
1332 /* Draw collision indicator */
1333 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1334 gdk_draw_point(hashed_process_data->pixmap,
1335 drawing->gc,
1336 x,
5bb606ce 1337 COLLISION_POSITION(hashed_process_data->height));
4a24fa1f 1338 hashed_process_data->x.middle_marked = TRUE;
1339 }
1340 } else {
fd22065b 1341 TimeWindow time_window =
1342 lttvwindow_get_time_window(control_flow_data->tab);
1343
1344#ifdef EXTRA_CHECK
1345 if(ltt_time_compare(evtime, time_window.start_time) == -1
1346 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1347 return FALSE;
fd22065b 1348#endif //EXTRA_CHECK
d6fef890 1349 Drawing_t *drawing = control_flow_data->drawing;
1350 guint width = drawing->width;
4a24fa1f 1351 guint x;
1352
2c82c4dc 1353 convert_time_to_pixels(
1354 time_window,
1355 evtime,
1356 width,
1357 &x);
1358
b2743953 1359
2c82c4dc 1360 /* Jump over draw if we are at the same x position */
1361 if(unlikely(x == hashed_process_data->x.middle &&
1362 hashed_process_data->x.middle_used))
1363 {
1364 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
b2743953 1365 /* Draw collision indicator */
1366 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1c736ed5 1367 gdk_draw_point(hashed_process_data->pixmap,
b2743953 1368 drawing->gc,
1369 x,
5bb606ce 1370 COLLISION_POSITION(hashed_process_data->height));
b2743953 1371 hashed_process_data->x.middle_marked = TRUE;
1372 }
2c82c4dc 1373 /* jump */
b2743953 1374 } else {
2c82c4dc 1375 DrawContext draw_context;
fd22065b 1376
2c82c4dc 1377 /* Now create the drawing context that will be used to draw
1378 * items related to the last state. */
1379 draw_context.drawable = hashed_process_data->pixmap;
1380 draw_context.gc = drawing->gc;
1381 draw_context.pango_layout = drawing->pango_layout;
1382 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1383 draw_context.drawinfo.end.x = x;
dbd243b1 1384
2c82c4dc 1385 draw_context.drawinfo.y.over = 1;
1386 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1387 draw_context.drawinfo.y.under = hashed_process_data->height;
dbd243b1 1388
2c82c4dc 1389 draw_context.drawinfo.start.offset.over = 0;
1390 draw_context.drawinfo.start.offset.middle = 0;
1391 draw_context.drawinfo.start.offset.under = 0;
1392 draw_context.drawinfo.end.offset.over = 0;
1393 draw_context.drawinfo.end.offset.middle = 0;
1394 draw_context.drawinfo.end.offset.under = 0;
dbd243b1 1395
2c82c4dc 1396 {
1397 /* Draw the line */
1398 PropertiesLine prop_line = prepare_s_e_line(process);
1399 draw_line((void*)&prop_line, (void*)&draw_context);
dbd243b1 1400
2c82c4dc 1401 }
1402 /* become the last x position */
1403 hashed_process_data->x.middle = x;
1404 hashed_process_data->x.middle_used = TRUE;
1405 hashed_process_data->x.middle_marked = FALSE;
dbd243b1 1406
2c82c4dc 1407 /* Calculate the next good time */
1408 convert_pixels_to_time(width, x+1, time_window,
1409 &hashed_process_data->next_good_time);
1410 }
1411 }
1412
1413 return 0;
1414
1415}
1416
1417
1418
1419/* before_process_release_hook
1420 *
1421 * Draw lines for process event.
1422 *
1423 * @param hook_data ControlFlowData structure of the viewer.
1424 * @param call_data Event context.
1425 *
1426 * This function adds items to be drawn in a queue for each process.
1427 *
1428 */
1429
1430
1431int before_process_release_hook(void *hook_data, void *call_data)
1432{
dd455fb8 1433 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1434 EventsRequest *events_request = (EventsRequest*)th->hook_data;
2c82c4dc 1435
1436 ControlFlowData *control_flow_data = events_request->viewer_data;
1437
1438 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1439
348c6ba8 1440 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1441
2c82c4dc 1442 LttEvent *e;
1443 e = ltt_tracefile_get_event(tfc->tf);
1444
e38d9ea0 1445 LttvFilter *filter = control_flow_data->filter;
1446 if(filter != NULL && filter->head != NULL)
1447 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1448 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1449 return FALSE;
1450
2c82c4dc 1451 LttTime evtime = ltt_event_time(e);
1452
0f090e21 1453 guint trace_num = ts->parent.index;
2c82c4dc 1454
1455 guint pid;
1456 {
04348950 1457 pid = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
2c82c4dc 1458 }
1459
1460 /* Add process to process list (if not present) */
1461 /* Don't care about the process if it's not in the state hash already :
1462 * that means a process that has never done anything in the trace and
1463 * unknown suddently gets destroyed : no state meaningful to show. */
348c6ba8 1464 LttvProcessState *process = lttv_state_find_process(ts, ANY_CPU, pid);
2c82c4dc 1465
1466 if(process != NULL) {
1467 LttTime birth;
2c82c4dc 1468 HashedProcessData *hashed_process_data = NULL;
1469
1470 ProcessList *process_list = control_flow_data->process_list;
1471
1472 birth = process->creation_time;
1473
1474 /* Cannot use current process : this event happens on another process,
1475 * action done by the parent. */
1476 hashed_process_data = processlist_get_process_data(process_list,
1477 pid,
348c6ba8 1478 process->cpu,
2c82c4dc 1479 &birth,
0f090e21 1480 trace_num);
2c82c4dc 1481 if(unlikely(hashed_process_data == NULL))
3311444c 1482 /*
1483 * Process already been scheduled out EXIT_DEAD, not in the process list
1484 * anymore. Just return.
1485 */
1486 return FALSE;
2c82c4dc 1487
1488 /* Now, the process is in the state hash and our own process hash.
1489 * We definitely can draw the items related to the ending state.
1490 */
1491
1492 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
1493 evtime) > 0))
1494 {
1495 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
1496 TimeWindow time_window =
1497 lttvwindow_get_time_window(control_flow_data->tab);
1498
1499#ifdef EXTRA_CHECK
1500 if(ltt_time_compare(evtime, time_window.start_time) == -1
1501 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1502 return FALSE;
2c82c4dc 1503#endif //EXTRA_CHECK
1504 Drawing_t *drawing = control_flow_data->drawing;
1505 guint width = drawing->width;
1506 guint x;
1507 convert_time_to_pixels(
1508 time_window,
1509 evtime,
1510 width,
1511 &x);
1512
1513 /* Draw collision indicator */
1514 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1515 gdk_draw_point(hashed_process_data->pixmap,
1516 drawing->gc,
1517 x,
5bb606ce 1518 COLLISION_POSITION(hashed_process_data->height));
2c82c4dc 1519 hashed_process_data->x.middle_marked = TRUE;
1520 }
1521 } else {
1522 TimeWindow time_window =
1523 lttvwindow_get_time_window(control_flow_data->tab);
1524
1525#ifdef EXTRA_CHECK
1526 if(ltt_time_compare(evtime, time_window.start_time) == -1
4a24fa1f 1527 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1528 return FALSE;
2da61677 1529#endif //EXTRA_CHECK
4a24fa1f 1530 Drawing_t *drawing = control_flow_data->drawing;
1531 guint width = drawing->width;
1532 guint x;
1533
1534 convert_time_to_pixels(
1535 time_window,
1536 evtime,
1537 width,
1538 &x);
1539
2da61677 1540
4a24fa1f 1541 /* Jump over draw if we are at the same x position */
1542 if(unlikely(x == hashed_process_data->x.middle &&
1543 hashed_process_data->x.middle_used))
1544 {
1545 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
2da61677 1546 /* Draw collision indicator */
1547 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1548 gdk_draw_point(hashed_process_data->pixmap,
1549 drawing->gc,
1550 x,
5bb606ce 1551 COLLISION_POSITION(hashed_process_data->height));
2da61677 1552 hashed_process_data->x.middle_marked = TRUE;
1553 }
4a24fa1f 1554 /* jump */
2da61677 1555 } else {
4a24fa1f 1556 DrawContext draw_context;
2da61677 1557
4a24fa1f 1558 /* Now create the drawing context that will be used to draw
1559 * items related to the last state. */
1560 draw_context.drawable = hashed_process_data->pixmap;
1561 draw_context.gc = drawing->gc;
1562 draw_context.pango_layout = drawing->pango_layout;
1563 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
1564 draw_context.drawinfo.end.x = x;
2da61677 1565
4a24fa1f 1566 draw_context.drawinfo.y.over = 1;
1567 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
1568 draw_context.drawinfo.y.under = hashed_process_data->height;
2da61677 1569
4a24fa1f 1570 draw_context.drawinfo.start.offset.over = 0;
1571 draw_context.drawinfo.start.offset.middle = 0;
1572 draw_context.drawinfo.start.offset.under = 0;
1573 draw_context.drawinfo.end.offset.over = 0;
1574 draw_context.drawinfo.end.offset.middle = 0;
1575 draw_context.drawinfo.end.offset.under = 0;
2da61677 1576
4a24fa1f 1577 {
1578 /* Draw the line */
1579 PropertiesLine prop_line = prepare_s_e_line(process);
1580 draw_line((void*)&prop_line, (void*)&draw_context);
2da61677 1581
2da61677 1582 }
4a24fa1f 1583 /* become the last x position */
1584 hashed_process_data->x.middle = x;
1585 hashed_process_data->x.middle_used = TRUE;
1586 hashed_process_data->x.middle_marked = FALSE;
1587
1588 /* Calculate the next good time */
1589 convert_pixels_to_time(width, x+1, time_window,
1590 &hashed_process_data->next_good_time);
2da61677 1591 }
1592 }
dbd243b1 1593 }
dbd243b1 1594
4a24fa1f 1595 return 0;
dbd243b1 1596}
1597
4a24fa1f 1598
2c82c4dc 1599
1600
1601
1602/* after_process_fork_hook
1603 *
1604 * Create the processlist entry for the child process. Put the last
1605 * position in x at the current time value.
1606 *
1607 * @param hook_data ControlFlowData structure of the viewer.
1608 * @param call_data Event context.
1609 *
1610 * This function adds items to be drawn in a queue for each process.
1611 *
1612 */
1613int after_process_fork_hook(void *hook_data, void *call_data)
1614{
dd455fb8 1615 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1616 EventsRequest *events_request = (EventsRequest*)th->hook_data;
2c82c4dc 1617 ControlFlowData *control_flow_data = events_request->viewer_data;
1618
1619 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1620
348c6ba8 1621 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1622
2c82c4dc 1623 LttEvent *e;
1624 e = ltt_tracefile_get_event(tfc->tf);
1625
e38d9ea0 1626 LttvFilter *filter = control_flow_data->filter;
1627 if(filter != NULL && filter->head != NULL)
1628 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1629 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1630 return FALSE;
1631
2c82c4dc 1632 LttTime evtime = ltt_event_time(e);
1633
1634 guint child_pid;
1635 {
04348950 1636 child_pid = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 1));
2c82c4dc 1637 }
1638
1639 /* Add process to process list (if not present) */
1640 LttvProcessState *process_child;
1641 LttTime birth;
1642 guint pl_height = 0;
1643 HashedProcessData *hashed_process_data_child = NULL;
1644
1645 ProcessList *process_list = control_flow_data->process_list;
1646
1647 /* Find child in the list... */
348c6ba8 1648 process_child = lttv_state_find_process(ts, ANY_CPU, child_pid);
2c82c4dc 1649 /* It should exist, because we are after the state update. */
1650 g_assert(process_child != NULL);
1651
1652 birth = process_child->creation_time;
0f090e21 1653 guint trace_num = ts->parent.index;
2c82c4dc 1654
1655 /* Cannot use current process, because this action is done by the parent
1656 * on its child. */
1657 hashed_process_data_child = processlist_get_process_data(process_list,
1658 child_pid,
348c6ba8 1659 process_child->cpu,
2c82c4dc 1660 &birth,
0f090e21 1661 trace_num);
2c82c4dc 1662 if(likely(hashed_process_data_child == NULL))
1663 {
1664 g_assert(child_pid == 0 || child_pid != process_child->ppid);
1665 /* Process not present */
1666 Drawing_t *drawing = control_flow_data->drawing;
2c82c4dc 1667 ProcessInfo *process_info;
1668 processlist_add(process_list,
1669 drawing,
1670 child_pid,
fcc08e1e 1671 process_child->tgid,
348c6ba8 1672 process_child->cpu,
2c82c4dc 1673 process_child->ppid,
1674 &birth,
0f090e21 1675 trace_num,
f4b88a7d 1676 process_child->name,
7b5f6cf1 1677 process_child->brand,
2c82c4dc 1678 &pl_height,
1679 &process_info,
1680 &hashed_process_data_child);
1681 gtk_widget_set_size_request(drawing->drawing_area,
1682 -1,
1683 pl_height);
1684 gtk_widget_queue_draw(drawing->drawing_area);
fcc08e1e 1685 } else {
1686 processlist_set_ppid(process_list, process_child->ppid,
1687 hashed_process_data_child);
1688 processlist_set_tgid(process_list, process_child->tgid,
1689 hashed_process_data_child);
2c82c4dc 1690 }
1691
1692
1693 if(likely(ltt_time_compare(hashed_process_data_child->next_good_time,
1694 evtime) <= 0))
1695 {
1696 TimeWindow time_window =
1697 lttvwindow_get_time_window(control_flow_data->tab);
1698
1699#ifdef EXTRA_CHECK
1700 if(ltt_time_compare(evtime, time_window.start_time) == -1
1701 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1702 return FALSE;
2c82c4dc 1703#endif //EXTRA_CHECK
1704 Drawing_t *drawing = control_flow_data->drawing;
1705 guint width = drawing->width;
1706 guint new_x;
1707 convert_time_to_pixels(
1708 time_window,
1709 evtime,
1710 width,
1711 &new_x);
1712
1713 if(likely(hashed_process_data_child->x.over != new_x)) {
1714 hashed_process_data_child->x.over = new_x;
1715 hashed_process_data_child->x.over_used = FALSE;
1716 hashed_process_data_child->x.over_marked = FALSE;
1717 }
1718 if(likely(hashed_process_data_child->x.middle != new_x)) {
1719 hashed_process_data_child->x.middle = new_x;
1720 hashed_process_data_child->x.middle_used = FALSE;
1721 hashed_process_data_child->x.middle_marked = FALSE;
1722 }
1723 if(likely(hashed_process_data_child->x.under != new_x)) {
1724 hashed_process_data_child->x.under = new_x;
1725 hashed_process_data_child->x.under_used = FALSE;
1726 hashed_process_data_child->x.under_marked = FALSE;
1727 }
1728 }
3311444c 1729 return FALSE;
2c82c4dc 1730}
1731
1732
1733
1734/* after_process_exit_hook
1735 *
1736 * Create the processlist entry for the child process. Put the last
1737 * position in x at the current time value.
1738 *
1739 * @param hook_data ControlFlowData structure of the viewer.
1740 * @param call_data Event context.
1741 *
1742 * This function adds items to be drawn in a queue for each process.
1743 *
1744 */
1745int after_process_exit_hook(void *hook_data, void *call_data)
1746{
dd455fb8 1747 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1748 EventsRequest *events_request = (EventsRequest*)th->hook_data;
2c82c4dc 1749 ControlFlowData *control_flow_data = events_request->viewer_data;
1750
1751 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1752
1753 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1754
348c6ba8 1755 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1756
2c82c4dc 1757 LttEvent *e;
1758 e = ltt_tracefile_get_event(tfc->tf);
1759
e38d9ea0 1760 LttvFilter *filter = control_flow_data->filter;
1761 if(filter != NULL && filter->head != NULL)
1762 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1763 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1764 return FALSE;
1765
2c82c4dc 1766 LttTime evtime = ltt_event_time(e);
1767
1768 /* Add process to process list (if not present) */
348c6ba8 1769 //LttvProcessState *process = tfs->process;
ae3d0f50 1770 guint cpu = tfs->cpu;
0f090e21 1771 guint trace_num = ts->parent.index;
348c6ba8 1772 LttvProcessState *process = ts->running_process[cpu];
1773
1774 /* It should exist, because we are after the state update. */
1775 g_assert(process != NULL);
1776
2c82c4dc 1777 guint pid = process->pid;
1778 LttTime birth;
1779 guint pl_height = 0;
1780 HashedProcessData *hashed_process_data = NULL;
1781
1782 ProcessList *process_list = control_flow_data->process_list;
1783
2c82c4dc 1784 birth = process->creation_time;
1785
0f090e21 1786 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL) ){
1787 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
2c82c4dc 1788 } else {
1789 hashed_process_data = processlist_get_process_data(process_list,
1790 pid,
348c6ba8 1791 process->cpu,
2c82c4dc 1792 &birth,
0f090e21 1793 trace_num);
2c82c4dc 1794 if(unlikely(hashed_process_data == NULL))
1795 {
1796 g_assert(pid == 0 || pid != process->ppid);
1797 /* Process not present */
1798 Drawing_t *drawing = control_flow_data->drawing;
2c82c4dc 1799 ProcessInfo *process_info;
1800 processlist_add(process_list,
1801 drawing,
1802 pid,
fcc08e1e 1803 process->tgid,
348c6ba8 1804 process->cpu,
2c82c4dc 1805 process->ppid,
1806 &birth,
0f090e21 1807 trace_num,
f4b88a7d 1808 process->name,
7b5f6cf1 1809 process->brand,
2c82c4dc 1810 &pl_height,
1811 &process_info,
1812 &hashed_process_data);
1813 gtk_widget_set_size_request(drawing->drawing_area,
1814 -1,
1815 pl_height);
1816 gtk_widget_queue_draw(drawing->drawing_area);
1817 }
1818
1819 /* Set the current process */
0f090e21 1820 process_list->current_hash_data[trace_num][process->cpu] =
2c82c4dc 1821 hashed_process_data;
1822 }
1823
1824 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
1825 evtime) <= 0))
1826 {
1827 TimeWindow time_window =
1828 lttvwindow_get_time_window(control_flow_data->tab);
dbd243b1 1829
2c82c4dc 1830#ifdef EXTRA_CHECK
1831 if(ltt_time_compare(evtime, time_window.start_time) == -1
1832 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1833 return FALSE;
2c82c4dc 1834#endif //EXTRA_CHECK
1835 Drawing_t *drawing = control_flow_data->drawing;
1836 guint width = drawing->width;
1837 guint new_x;
1838 convert_time_to_pixels(
1839 time_window,
1840 evtime,
1841 width,
1842 &new_x);
1843 if(unlikely(hashed_process_data->x.middle != new_x)) {
1844 hashed_process_data->x.middle = new_x;
1845 hashed_process_data->x.middle_used = FALSE;
1846 hashed_process_data->x.middle_marked = FALSE;
1847 }
1848 }
dbd243b1 1849
3311444c 1850 return FALSE;
2c82c4dc 1851}
dbd243b1 1852
1853
f4b88a7d 1854/* Get the filename of the process to print */
1855int after_fs_exec_hook(void *hook_data, void *call_data)
1856{
dd455fb8 1857 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1858 EventsRequest *events_request = (EventsRequest*)th->hook_data;
f4b88a7d 1859 ControlFlowData *control_flow_data = events_request->viewer_data;
1860
1861 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1862
1863 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1864
1865 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1866
e38d9ea0 1867 LttEvent *e;
1868 e = ltt_tracefile_get_event(tfc->tf);
1869
1870 LttvFilter *filter = control_flow_data->filter;
1871 if(filter != NULL && filter->head != NULL)
1872 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1873 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1874 return FALSE;
1875
ae3d0f50 1876 guint cpu = tfs->cpu;
0f090e21 1877 guint trace_num = ts->parent.index;
f4b88a7d 1878 LttvProcessState *process = ts->running_process[cpu];
1879 g_assert(process != NULL);
1880
1881 guint pid = process->pid;
1882
1883 /* Well, the process_out existed : we must get it in the process hash
1884 * or add it, and draw its items.
1885 */
1886 /* Add process to process list (if not present) */
1887 guint pl_height = 0;
1888 HashedProcessData *hashed_process_data = NULL;
1889 ProcessList *process_list = control_flow_data->process_list;
1890 LttTime birth = process->creation_time;
1891
0f090e21 1892 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1893 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
f4b88a7d 1894 } else {
1895 hashed_process_data = processlist_get_process_data(process_list,
1896 pid,
1897 process->cpu,
1898 &birth,
0f090e21 1899 trace_num);
f4b88a7d 1900 if(unlikely(hashed_process_data == NULL))
1901 {
1902 g_assert(pid == 0 || pid != process->ppid);
1903 ProcessInfo *process_info;
1904 /* Process not present */
1905 Drawing_t *drawing = control_flow_data->drawing;
1906 processlist_add(process_list,
1907 drawing,
1908 pid,
fcc08e1e 1909 process->tgid,
f4b88a7d 1910 process->cpu,
1911 process->ppid,
1912 &birth,
0f090e21 1913 trace_num,
f4b88a7d 1914 process->name,
7b5f6cf1 1915 process->brand,
f4b88a7d 1916 &pl_height,
1917 &process_info,
1918 &hashed_process_data);
1919 gtk_widget_set_size_request(drawing->drawing_area,
1920 -1,
1921 pl_height);
1922 gtk_widget_queue_draw(drawing->drawing_area);
1923 }
1924 /* Set the current process */
0f090e21 1925 process_list->current_hash_data[trace_num][process->cpu] =
f4b88a7d 1926 hashed_process_data;
1927 }
1928
1929 processlist_set_name(process_list, process->name, hashed_process_data);
1930
1931 return 0;
1932
1933}
1934
7b5f6cf1 1935/* Get the filename of the process to print */
1936int after_user_generic_thread_brand_hook(void *hook_data, void *call_data)
1937{
dd455fb8 1938 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1939 EventsRequest *events_request = (EventsRequest*)th->hook_data;
7b5f6cf1 1940 ControlFlowData *control_flow_data = events_request->viewer_data;
1941
1942 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1943
1944 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1945
1946 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1947
e38d9ea0 1948 LttEvent *e;
1949 e = ltt_tracefile_get_event(tfc->tf);
1950
1951 LttvFilter *filter = control_flow_data->filter;
1952 if(filter != NULL && filter->head != NULL)
1953 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1954 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1955 return FALSE;
1956
7b5f6cf1 1957 guint cpu = tfs->cpu;
0f090e21 1958 guint trace_num = ts->parent.index;
7b5f6cf1 1959 LttvProcessState *process = ts->running_process[cpu];
1960 g_assert(process != NULL);
1961
1962 guint pid = process->pid;
1963
1964 /* Well, the process_out existed : we must get it in the process hash
1965 * or add it, and draw its items.
1966 */
1967 /* Add process to process list (if not present) */
1968 guint pl_height = 0;
1969 HashedProcessData *hashed_process_data = NULL;
1970 ProcessList *process_list = control_flow_data->process_list;
1971 LttTime birth = process->creation_time;
1972
0f090e21 1973 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1974 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
7b5f6cf1 1975 } else {
1976 hashed_process_data = processlist_get_process_data(process_list,
1977 pid,
1978 process->cpu,
1979 &birth,
0f090e21 1980 trace_num);
7b5f6cf1 1981 if(unlikely(hashed_process_data == NULL))
1982 {
1983 g_assert(pid == 0 || pid != process->ppid);
1984 ProcessInfo *process_info;
1985 /* Process not present */
1986 Drawing_t *drawing = control_flow_data->drawing;
1987 processlist_add(process_list,
1988 drawing,
1989 pid,
fcc08e1e 1990 process->tgid,
7b5f6cf1 1991 process->cpu,
1992 process->ppid,
1993 &birth,
0f090e21 1994 trace_num,
7b5f6cf1 1995 process->name,
1996 process->brand,
1997 &pl_height,
1998 &process_info,
1999 &hashed_process_data);
2000 gtk_widget_set_size_request(drawing->drawing_area,
2001 -1,
2002 pl_height);
2003 gtk_widget_queue_draw(drawing->drawing_area);
2004 }
2005 /* Set the current process */
0f090e21 2006 process_list->current_hash_data[trace_num][process->cpu] =
7b5f6cf1 2007 hashed_process_data;
2008 }
2009
2010 processlist_set_brand(process_list, process->brand, hashed_process_data);
2011
2012 return 0;
2013
2014}
2015
2016
b3fd4c02 2017/* after_event_enum_process_hook
2018 *
b3fd4c02 2019 * Create the processlist entry for the child process. Put the last
2020 * position in x at the current time value.
2021 *
2022 * @param hook_data ControlFlowData structure of the viewer.
2023 * @param call_data Event context.
2024 *
2025 * This function adds items to be drawn in a queue for each process.
2026 *
2027 */
2028int after_event_enum_process_hook(void *hook_data, void *call_data)
2029{
dd455fb8 2030 LttvTraceHook *th = (LttvTraceHook*)hook_data;
2031 EventsRequest *events_request = (EventsRequest*)th->hook_data;
b3fd4c02 2032 ControlFlowData *control_flow_data = events_request->viewer_data;
2033
2034 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2035
b3fd4c02 2036 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
2037
c4a72569 2038 guint first_cpu, nb_cpus, cpu;
2039
b3fd4c02 2040 LttEvent *e;
2041 e = ltt_tracefile_get_event(tfc->tf);
2042
e38d9ea0 2043 LttvFilter *filter = control_flow_data->filter;
2044 if(filter != NULL && filter->head != NULL)
2045 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 2046 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 2047 return FALSE;
2048
b3fd4c02 2049 /* Add process to process list (if not present) */
2050 LttvProcessState *process_in;
2051 LttTime birth;
2052 guint pl_height = 0;
2053 HashedProcessData *hashed_process_data_in = NULL;
2054
2055 ProcessList *process_list = control_flow_data->process_list;
0f090e21 2056 guint trace_num = ts->parent.index;
b3fd4c02 2057
2058 guint pid_in;
2059 {
04348950 2060 pid_in = ltt_event_get_long_unsigned(e, lttv_trace_get_hook_field(th, 0));
b3fd4c02 2061 }
c4a72569 2062
2063 if(pid_in == 0) {
2064 first_cpu = 0;
2065 nb_cpus = ltt_trace_get_num_cpu(ts->parent.t);
2066 } else {
2067 first_cpu = ANY_CPU;
2068 nb_cpus = ANY_CPU+1;
2069 }
b3fd4c02 2070
c4a72569 2071 for(cpu = first_cpu; cpu < nb_cpus; cpu++) {
2072 /* Find process pid_in in the list... */
2073 process_in = lttv_state_find_process(ts, cpu, pid_in);
2074 //process_in = tfs->process;
2075 //guint cpu = tfs->cpu;
2076 //guint trace_num = ts->parent.index;
2077 //process_in = ts->running_process[cpu];
2078 /* It should exist, because we are after the state update. */
2079 #ifdef EXTRA_CHECK
2080 //g_assert(process_in != NULL);
2081 #endif //EXTRA_CHECK
2082 birth = process_in->creation_time;
2083
2084 hashed_process_data_in = processlist_get_process_data(process_list,
2085 pid_in,
2086 process_in->cpu,
2087 &birth,
2088 trace_num);
2089 if(hashed_process_data_in == NULL)
2090 {
2091 if(pid_in != 0 && pid_in == process_in->ppid)
2092 g_critical("TEST %u , %u", pid_in, process_in->ppid);
2093 g_assert(pid_in == 0 || pid_in != process_in->ppid);
2094 ProcessInfo *process_info;
2095 Drawing_t *drawing = control_flow_data->drawing;
2096 /* Process not present */
2097 processlist_add(process_list,
2098 drawing,
b3fd4c02 2099 pid_in,
c4a72569 2100 process_in->tgid,
b3fd4c02 2101 process_in->cpu,
c4a72569 2102 process_in->ppid,
b3fd4c02 2103 &birth,
c4a72569 2104 trace_num,
2105 process_in->name,
2106 process_in->brand,
2107 &pl_height,
2108 &process_info,
2109 &hashed_process_data_in);
2110 gtk_widget_set_size_request(drawing->drawing_area,
2111 -1,
2112 pl_height);
2113 gtk_widget_queue_draw(drawing->drawing_area);
2114 } else {
2115 processlist_set_name(process_list, process_in->name,
2116 hashed_process_data_in);
2117 processlist_set_ppid(process_list, process_in->ppid,
2118 hashed_process_data_in);
2119 processlist_set_tgid(process_list, process_in->tgid,
2120 hashed_process_data_in);
2121 }
2122 }
b3fd4c02 2123 return 0;
2124}
f4b88a7d 2125
2126
1b238973 2127gint update_time_window_hook(void *hook_data, void *call_data)
f7afe191 2128{
a56a1ba4 2129 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
a43d67ba 2130 Drawing_t *drawing = control_flow_data->drawing;
1c736ed5 2131 ProcessList *process_list = control_flow_data->process_list;
a43d67ba 2132
224446ce 2133 const TimeWindowNotifyData *time_window_nofify_data =
2134 ((const TimeWindowNotifyData *)call_data);
2135
14963be0 2136 TimeWindow *old_time_window =
224446ce 2137 time_window_nofify_data->old_time_window;
2138 TimeWindow *new_time_window =
2139 time_window_nofify_data->new_time_window;
a56a1ba4 2140
3cb8b205 2141 /* Update the ruler */
2142 drawing_update_ruler(control_flow_data->drawing,
2143 new_time_window);
2144
2145
a56a1ba4 2146 /* Two cases : zoom in/out or scrolling */
2147
2148 /* In order to make sure we can reuse the old drawing, the scale must
2149 * be the same and the new time interval being partly located in the
2150 * currently shown time interval. (reuse is only for scrolling)
2151 */
2152
2eef04b5 2153 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
14963be0 2154 old_time_window->start_time.tv_sec,
2155 old_time_window->start_time.tv_nsec,
2156 old_time_window->time_width.tv_sec,
2157 old_time_window->time_width.tv_nsec);
a56a1ba4 2158
2eef04b5 2159 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
14963be0 2160 new_time_window->start_time.tv_sec,
2161 new_time_window->start_time.tv_nsec,
2162 new_time_window->time_width.tv_sec,
2163 new_time_window->time_width.tv_nsec);
a56a1ba4 2164
14963be0 2165 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
2166 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
a56a1ba4 2167 {
2168 /* Same scale (scrolling) */
2169 g_info("scrolling");
14963be0 2170 LttTime *ns = &new_time_window->start_time;
2171 LttTime *os = &old_time_window->start_time;
6f26fc38 2172 LttTime old_end = old_time_window->end_time;
2173 LttTime new_end = new_time_window->end_time;
a56a1ba4 2174 //if(ns<os+w<ns+w)
2175 //if(ns<os+w && os+w<ns+w)
2176 //if(ns<old_end && os<ns)
2177 if(ltt_time_compare(*ns, old_end) == -1
2178 && ltt_time_compare(*os, *ns) == -1)
2179 {
2180 g_info("scrolling near right");
2181 /* Scroll right, keep right part of the screen */
2182 guint x = 0;
51705146 2183 guint width = control_flow_data->drawing->width;
a56a1ba4 2184 convert_time_to_pixels(
a18124ff 2185 *old_time_window,
a56a1ba4 2186 *ns,
2187 width,
2188 &x);
2189
2190 /* Copy old data to new location */
1c736ed5 2191 copy_pixmap_region(process_list,
2192 NULL,
2193 control_flow_data->drawing->drawing_area->style->black_gc,
2194 NULL,
2195 x, 0,
2196 0, 0,
2197 control_flow_data->drawing->width-x+SAFETY, -1);
2198
6395d57c 2199 if(drawing->damage_begin == drawing->damage_end)
2200 drawing->damage_begin = control_flow_data->drawing->width-x;
2201 else
2202 drawing->damage_begin = 0;
2203
2204 drawing->damage_end = control_flow_data->drawing->width;
2205
a56a1ba4 2206 /* Clear the data request background, but not SAFETY */
1c736ed5 2207 rectangle_pixmap(process_list,
cfe526b1 2208 control_flow_data->drawing->drawing_area->style->black_gc,
a56a1ba4 2209 TRUE,
6395d57c 2210 drawing->damage_begin+SAFETY, 0,
2211 drawing->damage_end - drawing->damage_begin, // do not overlap
1c736ed5 2212 -1);
7abb23ad 2213 gtk_widget_queue_draw(drawing->drawing_area);
2214 //gtk_widget_queue_draw_area (drawing->drawing_area,
2215 // 0,0,
2216 // control_flow_data->drawing->width,
2217 // control_flow_data->drawing->height);
a43d67ba 2218
a56a1ba4 2219 /* Get new data for the rest. */
501d5405 2220 drawing_data_request(control_flow_data->drawing,
6395d57c 2221 drawing->damage_begin, 0,
2222 drawing->damage_end - drawing->damage_begin,
501d5405 2223 control_flow_data->drawing->height);
a56a1ba4 2224 } else {
2225 //if(ns<os<ns+w)
2226 //if(ns<os && os<ns+w)
2227 //if(ns<os && os<new_end)
2228 if(ltt_time_compare(*ns,*os) == -1
2229 && ltt_time_compare(*os,new_end) == -1)
2230 {
2231 g_info("scrolling near left");
2232 /* Scroll left, keep left part of the screen */
2233 guint x = 0;
51705146 2234 guint width = control_flow_data->drawing->width;
a56a1ba4 2235 convert_time_to_pixels(
a18124ff 2236 *new_time_window,
a56a1ba4 2237 *os,
2238 width,
2239 &x);
6395d57c 2240
a56a1ba4 2241 /* Copy old data to new location */
1c736ed5 2242 copy_pixmap_region (process_list,
2243 NULL,
cfe526b1 2244 control_flow_data->drawing->drawing_area->style->black_gc,
1c736ed5 2245 NULL,
a56a1ba4 2246 0, 0,
2247 x, 0,
2248 -1, -1);
2249
6395d57c 2250 if(drawing->damage_begin == drawing->damage_end)
2251 drawing->damage_end = x;
2252 else
2253 drawing->damage_end =
51705146 2254 control_flow_data->drawing->width;
6395d57c 2255
2256 drawing->damage_begin = 0;
2257
1c736ed5 2258 rectangle_pixmap (process_list,
cfe526b1 2259 control_flow_data->drawing->drawing_area->style->black_gc,
a56a1ba4 2260 TRUE,
6395d57c 2261 drawing->damage_begin, 0,
2262 drawing->damage_end - drawing->damage_begin, // do not overlap
1c736ed5 2263 -1);
a43d67ba 2264
7abb23ad 2265 gtk_widget_queue_draw(drawing->drawing_area);
2266 //gtk_widget_queue_draw_area (drawing->drawing_area,
2267 // 0,0,
2268 // control_flow_data->drawing->width,
2269 // control_flow_data->drawing->height);
a43d67ba 2270
6395d57c 2271
a56a1ba4 2272 /* Get new data for the rest. */
501d5405 2273 drawing_data_request(control_flow_data->drawing,
6395d57c 2274 drawing->damage_begin, 0,
2275 drawing->damage_end - drawing->damage_begin,
501d5405 2276 control_flow_data->drawing->height);
a56a1ba4 2277
a56a1ba4 2278 } else {
a43d67ba 2279 if(ltt_time_compare(*ns,*os) == 0)
2280 {
2281 g_info("not scrolling");
2282 } else {
2283 g_info("scrolling far");
2284 /* Cannot reuse any part of the screen : far jump */
2285
2286
1c736ed5 2287 rectangle_pixmap (process_list,
a43d67ba 2288 control_flow_data->drawing->drawing_area->style->black_gc,
2289 TRUE,
a56a1ba4 2290 0, 0,
a43d67ba 2291 control_flow_data->drawing->width+SAFETY, // do not overlap
1c736ed5 2292 -1);
a43d67ba 2293
7abb23ad 2294 //gtk_widget_queue_draw_area (drawing->drawing_area,
2295 // 0,0,
2296 // control_flow_data->drawing->width,
2297 // control_flow_data->drawing->height);
2298 gtk_widget_queue_draw(drawing->drawing_area);
a43d67ba 2299
6395d57c 2300 drawing->damage_begin = 0;
2301 drawing->damage_end = control_flow_data->drawing->width;
2302
a43d67ba 2303 drawing_data_request(control_flow_data->drawing,
a43d67ba 2304 0, 0,
2305 control_flow_data->drawing->width,
2306 control_flow_data->drawing->height);
2307
2308 }
a56a1ba4 2309 }
2310 }
2311 } else {
2312 /* Different scale (zoom) */
2313 g_info("zoom");
2314
1c736ed5 2315 rectangle_pixmap (process_list,
cfe526b1 2316 control_flow_data->drawing->drawing_area->style->black_gc,
a56a1ba4 2317 TRUE,
2318 0, 0,
501d5405 2319 control_flow_data->drawing->width+SAFETY, // do not overlap
1c736ed5 2320 -1);
a56a1ba4 2321
7abb23ad 2322 //gtk_widget_queue_draw_area (drawing->drawing_area,
2323 // 0,0,
2324 // control_flow_data->drawing->width,
2325 // control_flow_data->drawing->height);
2326 gtk_widget_queue_draw(drawing->drawing_area);
a56a1ba4 2327
6395d57c 2328 drawing->damage_begin = 0;
2329 drawing->damage_end = control_flow_data->drawing->width;
2330
501d5405 2331 drawing_data_request(control_flow_data->drawing,
a56a1ba4 2332 0, 0,
501d5405 2333 control_flow_data->drawing->width,
2334 control_flow_data->drawing->height);
a56a1ba4 2335 }
2336
15f77e3b 2337 /* Update directly when scrolling */
2338 gdk_window_process_updates(control_flow_data->drawing->drawing_area->window,
2339 TRUE);
3cb8b205 2340
a56a1ba4 2341 return 0;
f7afe191 2342}
2343
6395d57c 2344gint traceset_notify(void *hook_data, void *call_data)
2345{
2346 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2347 Drawing_t *drawing = control_flow_data->drawing;
6395d57c 2348
6cec4cd2 2349 if(unlikely(drawing->gc == NULL)) {
2350 return FALSE;
2351 }
2352 if(drawing->dotted_gc == NULL) {
2353 return FALSE;
2354 }
6395d57c 2355
b9a010a2 2356 drawing_clear(control_flow_data->drawing);
2357 processlist_clear(control_flow_data->process_list);
07390ec1 2358 gtk_widget_set_size_request(
2359 control_flow_data->drawing->drawing_area,
2360 -1, processlist_get_height(control_flow_data->process_list));
d9267eec 2361 redraw_notify(control_flow_data, NULL);
6395d57c 2362
d9267eec 2363 request_background_data(control_flow_data);
6395d57c 2364
2365 return FALSE;
2366}
2367
ca0f8a8e 2368gint redraw_notify(void *hook_data, void *call_data)
2369{
2370 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
2371 Drawing_t *drawing = control_flow_data->drawing;
2372 GtkWidget *widget = drawing->drawing_area;
2373
2374 drawing->damage_begin = 0;
51705146 2375 drawing->damage_end = drawing->width;
ca0f8a8e 2376
49217bd4 2377 /* fun feature, to be separated someday... */
2378 drawing_clear(control_flow_data->drawing);
2379 processlist_clear(control_flow_data->process_list);
07390ec1 2380 gtk_widget_set_size_request(
2381 control_flow_data->drawing->drawing_area,
2382 -1, processlist_get_height(control_flow_data->process_list));
1c736ed5 2383 // Clear the images
2384 rectangle_pixmap (control_flow_data->process_list,
ca0f8a8e 2385 widget->style->black_gc,
2386 TRUE,
2387 0, 0,
f3b7430d 2388 drawing->alloc_width,
1c736ed5 2389 -1);
ca0f8a8e 2390
f3b7430d 2391 gtk_widget_queue_draw(drawing->drawing_area);
4a24fa1f 2392
ca0f8a8e 2393 if(drawing->damage_begin < drawing->damage_end)
2394 {
2395 drawing_data_request(drawing,
ca0f8a8e 2396 drawing->damage_begin,
2397 0,
2398 drawing->damage_end-drawing->damage_begin,
51705146 2399 drawing->height);
ca0f8a8e 2400 }
2401
7abb23ad 2402 //gtk_widget_queue_draw_area(drawing->drawing_area,
2403 // 0,0,
2404 // drawing->width,
2405 // drawing->height);
ca0f8a8e 2406 return FALSE;
2407
2408}
2409
2410
2411gint continue_notify(void *hook_data, void *call_data)
a43d67ba 2412{
2413 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
ca0f8a8e 2414 Drawing_t *drawing = control_flow_data->drawing;
a43d67ba 2415
6395d57c 2416 //g_assert(widget->allocation.width == drawing->damage_end);
ca0f8a8e 2417
2418 if(drawing->damage_begin < drawing->damage_end)
2419 {
2420 drawing_data_request(drawing,
ca0f8a8e 2421 drawing->damage_begin,
2422 0,
2423 drawing->damage_end-drawing->damage_begin,
51705146 2424 drawing->height);
ca0f8a8e 2425 }
2426
2427 return FALSE;
2428}
2429
2430
1b238973 2431gint update_current_time_hook(void *hook_data, void *call_data)
f7afe191 2432{
14963be0 2433 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
a56a1ba4 2434
224446ce 2435 LttTime current_time = *((LttTime*)call_data);
a56a1ba4 2436
ca0f8a8e 2437 TimeWindow time_window =
2438 lttvwindow_get_time_window(control_flow_data->tab);
a56a1ba4 2439
ca0f8a8e 2440 LttTime time_begin = time_window.start_time;
2441 LttTime width = time_window.time_width;
90ef7e4a 2442 LttTime half_width;
2443 {
2444 guint64 time_ll = ltt_time_to_uint64(width);
2445 time_ll = time_ll >> 1; /* divide by two */
2446 half_width = ltt_time_from_uint64(time_ll);
2447 }
a56a1ba4 2448 LttTime time_end = ltt_time_add(time_begin, width);
2449
2450 LttvTracesetContext * tsc =
ca0f8a8e 2451 lttvwindow_get_traceset_context(control_flow_data->tab);
a56a1ba4 2452
ca0f8a8e 2453 LttTime trace_start = tsc->time_span.start_time;
2454 LttTime trace_end = tsc->time_span.end_time;
a56a1ba4 2455
2eef04b5 2456 g_info("New current time HOOK : %lu, %lu", current_time.tv_sec,
224446ce 2457 current_time.tv_nsec);
a56a1ba4 2458
2459
2460
2461 /* If current time is inside time interval, just move the highlight
2462 * bar */
2463
2464 /* Else, we have to change the time interval. We have to tell it
2465 * to the main window. */
2466 /* The time interval change will take care of placing the current
2467 * time at the center of the visible area, or nearest possible if we are
2468 * at one end of the trace. */
2469
2470
dbc0ef8a 2471 if(ltt_time_compare(current_time, time_begin) < 0)
a56a1ba4 2472 {
224446ce 2473 TimeWindow new_time_window;
2474
2475 if(ltt_time_compare(current_time,
dbc0ef8a 2476 ltt_time_add(trace_start,half_width)) < 0)
a56a1ba4 2477 time_begin = trace_start;
2478 else
224446ce 2479 time_begin = ltt_time_sub(current_time,half_width);
a56a1ba4 2480
224446ce 2481 new_time_window.start_time = time_begin;
2482 new_time_window.time_width = width;
a18124ff 2483 new_time_window.time_width_double = ltt_time_to_double(width);
6f26fc38 2484 new_time_window.end_time = ltt_time_add(time_begin, width);
a56a1ba4 2485
e800cf84 2486 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
a56a1ba4 2487 }
dbc0ef8a 2488 else if(ltt_time_compare(current_time, time_end) > 0)
a56a1ba4 2489 {
224446ce 2490 TimeWindow new_time_window;
2491
dbc0ef8a 2492 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) > 0)
a56a1ba4 2493 time_begin = ltt_time_sub(trace_end,width);
2494 else
224446ce 2495 time_begin = ltt_time_sub(current_time,half_width);
a56a1ba4 2496
224446ce 2497 new_time_window.start_time = time_begin;
2498 new_time_window.time_width = width;
a18124ff 2499 new_time_window.time_width_double = ltt_time_to_double(width);
6f26fc38 2500 new_time_window.end_time = ltt_time_add(time_begin, width);
a56a1ba4 2501
e800cf84 2502 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
a56a1ba4 2503
2504 }
7abb23ad 2505 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
a56a1ba4 2506
15f77e3b 2507 /* Update directly when scrolling */
2508 gdk_window_process_updates(control_flow_data->drawing->drawing_area->window,
2509 TRUE);
2510
a56a1ba4 2511 return 0;
f7afe191 2512}
2513
8b90e648 2514typedef struct _ClosureData {
ca0f8a8e 2515 EventsRequest *events_request;
d0cd7f09 2516 LttvTracesetState *tss;
b9a010a2 2517 LttTime end_time;
bc8d270b 2518 guint x_end;
8b90e648 2519} ClosureData;
a56a1ba4 2520
8b90e648 2521
e800cf84 2522void draw_closure(gpointer key, gpointer value, gpointer user_data)
2523{
a56a1ba4 2524 ProcessInfo *process_info = (ProcessInfo*)key;
2525 HashedProcessData *hashed_process_data = (HashedProcessData*)value;
2526 ClosureData *closure_data = (ClosureData*)user_data;
2527
e800cf84 2528 EventsRequest *events_request = closure_data->events_request;
2529 ControlFlowData *control_flow_data = events_request->viewer_data;
a56a1ba4 2530
e800cf84 2531 LttvTracesetState *tss = closure_data->tss;
d6fef890 2532 LttvTracesetContext *tsc = (LttvTracesetContext*)tss;
a56a1ba4 2533
e800cf84 2534 LttTime evtime = closure_data->end_time;
d0cd7f09 2535
e3162168 2536 gboolean dodraw = TRUE;
2537
e800cf84 2538 {
2539 /* For the process */
2540 /* First, check if the current process is in the state computation
2541 * process list. If it is there, that means we must add it right now and
2542 * draw items from the beginning of the read for it. If it is not
2543 * present, it's a new process and it was not present : it will
2544 * be added after the state update. */
31b6868d 2545#ifdef EXTRA_CHECK
e800cf84 2546 g_assert(lttv_traceset_number(tsc->ts) > 0);
31b6868d 2547#endif //EXTRA_CHECK
2c82c4dc 2548 LttvTraceContext *tc = tsc->traces[process_info->trace_num];
348c6ba8 2549 LttvTraceState *ts = (LttvTraceState*)tc;
2c82c4dc 2550
348c6ba8 2551#if 0
2c82c4dc 2552 //FIXME : optimize data structures.
2553 LttvTracefileState *tfs;
2554 LttvTracefileContext *tfc;
2555 guint i;
2556 for(i=0;i<tc->tracefiles->len;i++) {
2557 tfc = g_array_index(tc->tracefiles, LttvTracefileContext*, i);
2558 if(ltt_tracefile_name(tfc->tf) == LTT_NAME_CPU
ae3d0f50 2559 && tfs->cpu == process_info->cpu)
2c82c4dc 2560 break;
2561
2562 }
2563 g_assert(i<tc->tracefiles->len);
2564 tfs = LTTV_TRACEFILE_STATE(tfc);
348c6ba8 2565#endif //0
2c82c4dc 2566 // LttvTracefileState *tfs =
2567 // (LttvTracefileState*)tsc->traces[process_info->trace_num]->
2568 // tracefiles[process_info->cpu];
2da61677 2569
e800cf84 2570 LttvProcessState *process;
348c6ba8 2571 process = lttv_state_find_process(ts, process_info->cpu,
e025a729 2572 process_info->pid);
a56a1ba4 2573
1d1df11d 2574 if(unlikely(process != NULL)) {
e800cf84 2575
b6ef18af 2576 LttvFilter *filter = control_flow_data->filter;
2577 if(filter != NULL && filter->head != NULL)
2578 if(!lttv_filter_tree_parse(filter->head,NULL,NULL,
2579 tc->t,NULL,process,tc))
e3162168 2580 dodraw = FALSE;
b6ef18af 2581
e800cf84 2582 /* Only draw for processes that are currently in the trace states */
ad2e83ba 2583
1d1df11d 2584#ifdef EXTRA_CHECK
e800cf84 2585 /* Should be alike when background info is ready */
2586 if(control_flow_data->background_info_waiting==0)
2587 g_assert(ltt_time_compare(process->creation_time,
2588 process_info->birth) == 0);
1d1df11d 2589#endif //EXTRA_CHECK
e800cf84 2590
2591 /* Now, the process is in the state hash and our own process hash.
2592 * We definitely can draw the items related to the ending state.
2593 */
2594
1d1df11d 2595 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
2596 evtime) <= 0))
e800cf84 2597 {
fd22065b 2598 TimeWindow time_window =
2599 lttvwindow_get_time_window(control_flow_data->tab);
2600
2601#ifdef EXTRA_CHECK
2602 if(ltt_time_compare(evtime, time_window.start_time) == -1
2603 || ltt_time_compare(evtime, time_window.end_time) == 1)
2604 return;
2605#endif //EXTRA_CHECK
d6fef890 2606 Drawing_t *drawing = control_flow_data->drawing;
96947fcf 2607 guint width = drawing->width;
a56a1ba4 2608
bc8d270b 2609 guint x = closure_data->x_end;
8b90e648 2610
4b7dc462 2611 DrawContext draw_context;
2612
e800cf84 2613 /* Now create the drawing context that will be used to draw
2614 * items related to the last state. */
1c736ed5 2615 draw_context.drawable = hashed_process_data->pixmap;
e800cf84 2616 draw_context.gc = drawing->gc;
2617 draw_context.pango_layout = drawing->pango_layout;
e800cf84 2618 draw_context.drawinfo.end.x = x;
2619
1c736ed5 2620 draw_context.drawinfo.y.over = 1;
2621 draw_context.drawinfo.y.middle = (hashed_process_data->height/2);
2622 draw_context.drawinfo.y.under = hashed_process_data->height;
e800cf84 2623
2624 draw_context.drawinfo.start.offset.over = 0;
2625 draw_context.drawinfo.start.offset.middle = 0;
2626 draw_context.drawinfo.start.offset.under = 0;
2627 draw_context.drawinfo.end.offset.over = 0;
2628 draw_context.drawinfo.end.offset.middle = 0;
2629 draw_context.drawinfo.end.offset.under = 0;
9a1ec01b 2630#if 0
4b7dc462 2631 /* Jump over draw if we are at the same x position */
2632 if(x == hashed_process_data->x.over)
e800cf84 2633 {
4b7dc462 2634 /* jump */
2635 } else {
23093869 2636 draw_context.drawinfo.start.x = hashed_process_data->x.over;
2637 /* Draw the line */
2638 PropertiesLine prop_line = prepare_execmode_line(process);
2639 draw_line((void*)&prop_line, (void*)&draw_context);
2640
4b7dc462 2641 hashed_process_data->x.over = x;
23093869 2642 }
9a1ec01b 2643#endif //0
4b7dc462 2644
1d1df11d 2645 if(unlikely(x == hashed_process_data->x.middle &&
2646 hashed_process_data->x.middle_used)) {
b2743953 2647#if 0 /* do not mark closure : not missing information */
e72908ed 2648 if(hashed_process_data->x.middle_marked == FALSE) {
2649 /* Draw collision indicator */
2650 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
2651 gdk_draw_point(drawing->pixmap,
2652 drawing->gc,
2653 x,
2c6618bc 2654 y+(height/2)-3);
de4ea1ad 2655 hashed_process_data->x.middle_marked = TRUE;
e72908ed 2656 }
b2743953 2657#endif //0
4b7dc462 2658 /* Jump */
2659 } else {
23093869 2660 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
e800cf84 2661 /* Draw the line */
c4a72569 2662 if(dodraw) {
2663 PropertiesLine prop_line = prepare_s_e_line(process);
2664 draw_line((void*)&prop_line, (void*)&draw_context);
2665 }
e800cf84 2666
4b7dc462 2667 /* become the last x position */
1d1df11d 2668 if(likely(x != hashed_process_data->x.middle)) {
e72908ed 2669 hashed_process_data->x.middle = x;
2670 /* but don't use the pixel */
2671 hashed_process_data->x.middle_used = FALSE;
b2743953 2672
2673 /* Calculate the next good time */
2674 convert_pixels_to_time(width, x+1, time_window,
2675 &hashed_process_data->next_good_time);
e72908ed 2676 }
e800cf84 2677 }
e800cf84 2678 }
2679 }
2680 }
2681 return;
8b90e648 2682}
2683
b9a010a2 2684int before_chunk(void *hook_data, void *call_data)
2685{
2686 EventsRequest *events_request = (EventsRequest*)hook_data;
16b9cadb 2687 LttvTracesetState *tss = (LttvTracesetState*)call_data;
cd3892fe 2688#if 0
7c0125e0 2689 /* Desactivate sort */
2690 gtk_tree_sortable_set_sort_column_id(
2691 GTK_TREE_SORTABLE(cfd->process_list->list_store),
2692 TRACE_COLUMN,
2693 GTK_SORT_ASCENDING);
cd3892fe 2694#endif //0
b9a010a2 2695 drawing_chunk_begin(events_request, tss);
2696
2697 return 0;
2698}
2699
2700int before_request(void *hook_data, void *call_data)
ca0f8a8e 2701{
2702 EventsRequest *events_request = (EventsRequest*)hook_data;
16b9cadb 2703 LttvTracesetState *tss = (LttvTracesetState*)call_data;
7c0125e0 2704
ca0f8a8e 2705 drawing_data_request_begin(events_request, tss);
2706
2707 return 0;
2708}
2709
2710
8b90e648 2711/*
b9a010a2 2712 * after request is necessary in addition of after chunk in order to draw
2713 * lines until the end of the screen. after chunk just draws lines until
2714 * the last event.
2715 *
8b90e648 2716 * for each process
a56a1ba4 2717 * draw closing line
b9a010a2 2718 * expose
8b90e648 2719 */
b9a010a2 2720int after_request(void *hook_data, void *call_data)
8b90e648 2721{
ca0f8a8e 2722 EventsRequest *events_request = (EventsRequest*)hook_data;
2723 ControlFlowData *control_flow_data = events_request->viewer_data;
16b9cadb 2724 LttvTracesetState *tss = (LttvTracesetState*)call_data;
a56a1ba4 2725
5c230fc4 2726 ProcessList *process_list = control_flow_data->process_list;
b9a010a2 2727 LttTime end_time = events_request->end_time;
2728
2729 ClosureData closure_data;
2730 closure_data.events_request = (EventsRequest*)hook_data;
2731 closure_data.tss = tss;
2732 closure_data.end_time = end_time;
2733
bc8d270b 2734 TimeWindow time_window =
2735 lttvwindow_get_time_window(control_flow_data->tab);
2736 guint width = control_flow_data->drawing->width;
2737 convert_time_to_pixels(
2738 time_window,
2739 end_time,
2740 width,
2741 &closure_data.x_end);
2742
2743
b9a010a2 2744 /* Draw last items */
2745 g_hash_table_foreach(process_list->process_hash, draw_closure,
2746 (void*)&closure_data);
7c0125e0 2747
b9a010a2 2748
2749 /* Request expose */
2750 drawing_request_expose(events_request, tss, end_time);
2751 return 0;
2752}
2753
2754/*
2755 * for each process
2756 * draw closing line
e800cf84 2757 * expose
b9a010a2 2758 */
2759int after_chunk(void *hook_data, void *call_data)
2760{
2761 EventsRequest *events_request = (EventsRequest*)hook_data;
2762 ControlFlowData *control_flow_data = events_request->viewer_data;
16b9cadb 2763 LttvTracesetState *tss = (LttvTracesetState*)call_data;
2764 LttvTracesetContext *tsc = (LttvTracesetContext*)call_data;
b9a010a2 2765 LttvTracefileContext *tfc = lttv_traceset_context_get_current_tfc(tsc);
2766 LttTime end_time;
2767
5c230fc4 2768 ProcessList *process_list = control_flow_data->process_list;
0f090e21 2769 guint i;
2770 LttvTraceset *traceset = tsc->ts;
2771 guint nb_trace = lttv_traceset_number(traceset);
b9a010a2 2772
0f090e21 2773 /* Only execute when called for the first trace's events request */
43ed82b5 2774 if(!process_list->current_hash_data)
2775 return 0;
0f090e21 2776
2777 for(i = 0 ; i < nb_trace ; i++) {
2778 g_free(process_list->current_hash_data[i]);
2779 }
40debf7b 2780 g_free(process_list->current_hash_data);
2781 process_list->current_hash_data = NULL;
0f090e21 2782
e800cf84 2783 if(tfc != NULL)
2784 end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time);
0c5dbe3b 2785 else /* end of traceset, or position now out of request : end */
2786 end_time = events_request->end_time;
2787
a56a1ba4 2788 ClosureData closure_data;
ca0f8a8e 2789 closure_data.events_request = (EventsRequest*)hook_data;
2790 closure_data.tss = tss;
b9a010a2 2791 closure_data.end_time = end_time;
a56a1ba4 2792
bc8d270b 2793 TimeWindow time_window =
2794 lttvwindow_get_time_window(control_flow_data->tab);
2795 guint width = control_flow_data->drawing->width;
2796 convert_time_to_pixels(
2797 time_window,
2798 end_time,
2799 width,
2800 &closure_data.x_end);
2801
b9a010a2 2802 /* Draw last items */
14963be0 2803 g_hash_table_foreach(process_list->process_hash, draw_closure,
a56a1ba4 2804 (void*)&closure_data);
cd3892fe 2805#if 0
7c0125e0 2806 /* Reactivate sort */
2807 gtk_tree_sortable_set_sort_column_id(
2808 GTK_TREE_SORTABLE(control_flow_data->process_list->list_store),
2809 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2810 GTK_SORT_ASCENDING);
2811
2812 update_index_to_pixmap(control_flow_data->process_list);
cd3892fe 2813 /* Request a full expose : drawing scrambled */
2814 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
2815#endif //0
2816 /* Request expose (updates damages zone also) */
b9a010a2 2817 drawing_request_expose(events_request, tss, end_time);
ca0f8a8e 2818
2819 return 0;
8b90e648 2820}
2821
b70ceef8 2822/* after_statedump_end
2823 *
2824 * @param hook_data ControlFlowData structure of the viewer.
2825 * @param call_data Event context.
2826 *
2827 * This function adds items to be drawn in a queue for each process.
2828 *
2829 */
2830int before_statedump_end(void *hook_data, void *call_data)
2831{
dd455fb8 2832 LttvTraceHook *th = (LttvTraceHook*)hook_data;
2833 EventsRequest *events_request = (EventsRequest*)th->hook_data;
b70ceef8 2834 ControlFlowData *control_flow_data = events_request->viewer_data;
2835
2836 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
2837
b70ceef8 2838 LttvTracesetState *tss = (LttvTracesetState*)tfc->t_context->ts_context;
2839 ProcessList *process_list = control_flow_data->process_list;
2840
2841 LttEvent *e;
2842 e = ltt_tracefile_get_event(tfc->tf);
2843
2844 LttvFilter *filter = control_flow_data->filter;
2845 if(filter != NULL && filter->head != NULL)
2846 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 2847 tfc->t_context->t,tfc,NULL,NULL))
b70ceef8 2848 return FALSE;
2849
2850 LttTime evtime = ltt_event_time(e);
2851
2852 ClosureData closure_data;
2853 closure_data.events_request = events_request;
2854 closure_data.tss = tss;
2855 closure_data.end_time = evtime;
2856
2857 TimeWindow time_window =
2858 lttvwindow_get_time_window(control_flow_data->tab);
2859 guint width = control_flow_data->drawing->width;
2860 convert_time_to_pixels(
2861 time_window,
2862 evtime,
2863 width,
2864 &closure_data.x_end);
2865
2866 /* Draw last items */
2867 g_hash_table_foreach(process_list->process_hash, draw_closure,
2868 (void*)&closure_data);
2869#if 0
2870 /* Reactivate sort */
2871 gtk_tree_sortable_set_sort_column_id(
2872 GTK_TREE_SORTABLE(control_flow_data->process_list->list_store),
2873 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2874 GTK_SORT_ASCENDING);
2875
2876 update_index_to_pixmap(control_flow_data->process_list);
2877 /* Request a full expose : drawing scrambled */
2878 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
2879#endif //0
2880 /* Request expose (updates damages zone also) */
2881 drawing_request_expose(events_request, tss, evtime);
2882
2883 return 0;
2884}
This page took 0.238753 seconds and 4 git commands to generate.