Remove reference to thread brand
[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
2a2fa4f0 62#include <lttv/lttv.h>
558aa013 63#include <lttv/hook.h>
80a52ff8 64#include <lttv/state.h>
2d262115 65#include <lttvwindow/lttvwindow.h>
6395d57c 66#include <lttvwindow/lttvwindowtraces.h>
0de51231 67#include <lttvwindow/support.h>
80a52ff8 68
f0d936c0 69
a117e3f7 70#include "eventhooks.h"
71#include "cfv.h"
72#include "processlist.h"
73#include "drawing.h"
5f16133f 74
80a52ff8 75
1a31868c 76#define MAX_PATH_LEN 256
98dfb302 77#define STATE_LINE_WIDTH 8
5bb606ce 78#define COLLISION_POSITION(height) (((height - STATE_LINE_WIDTH)/2) -3)
1a31868c 79
0de51231 80extern GSList *g_legend_list;
81
b9a010a2 82
6395d57c 83/* Action to do when background computation completed.
84 *
e800cf84 85 * Wait for all the awaited computations to be over.
6395d57c 86 */
87
703b25fa 88static gint background_ready(void *hook_data, void *call_data)
6395d57c 89{
90 ControlFlowData *control_flow_data = (ControlFlowData *)hook_data;
6395d57c 91
e800cf84 92 control_flow_data->background_info_waiting--;
93
94 if(control_flow_data->background_info_waiting == 0) {
4a24fa1f 95 g_message("control flow viewer : background computation data ready.");
6395d57c 96
e800cf84 97 drawing_clear(control_flow_data->drawing);
98 processlist_clear(control_flow_data->process_list);
07390ec1 99 gtk_widget_set_size_request(
100 control_flow_data->drawing->drawing_area,
101 -1, processlist_get_height(control_flow_data->process_list));
e800cf84 102 redraw_notify(control_flow_data, NULL);
b9a010a2 103 }
6395d57c 104
105 return 0;
106}
107
108
109/* Request background computation. Verify if it is in progress or ready first.
e800cf84 110 * Only for each trace in the tab's traceset.
6395d57c 111 */
88bf15f0 112
3f7f592e 113static void request_background_data(ControlFlowData *control_flow_data)
6395d57c 114{
88bf15f0
FD
115
116 LttvTraceset *ts = lttvwindow_get_traceset(control_flow_data->tab);
117 gint num_traces = lttv_traceset_number(ts);
6395d57c 118 gint i;
119 LttvTrace *trace;
7df20ca4 120 LttvTraceState *tstate;
6395d57c 121
88bf15f0 122 LttvHooks *background_ready_hook = lttv_hooks_new();
6395d57c 123 lttv_hooks_add(background_ready_hook, background_ready, control_flow_data,
124 LTTV_PRIO_DEFAULT);
e800cf84 125 control_flow_data->background_info_waiting = 0;
6395d57c 126
127 for(i=0;i<num_traces;i++) {
88bf15f0 128 trace = lttv_traceset_get(ts, i);
dd47d0d8 129
7df20ca4 130 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE
88bf15f0 131 && !ts->has_precomputed_states) {
6395d57c 132
133 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
134 trace) == FALSE) {
135 /* We first remove requests that could have been done for the same
136 * information. Happens when two viewers ask for it before servicing
137 * starts.
138 */
93ac601b 139 if(!lttvwindowtraces_background_request_find(trace, "state"))
b5e17af5 140 lttvwindowtraces_background_request_queue(
141 main_window_get_widget(control_flow_data->tab), trace, "state");
6395d57c 142 lttvwindowtraces_background_notify_queue(control_flow_data,
143 trace,
144 ltt_time_infinite,
145 NULL,
146 background_ready_hook);
e800cf84 147 control_flow_data->background_info_waiting++;
6395d57c 148 } else { /* in progress */
149
150 lttvwindowtraces_background_notify_current(control_flow_data,
151 trace,
152 ltt_time_infinite,
153 NULL,
154 background_ready_hook);
e800cf84 155 control_flow_data->background_info_waiting++;
6395d57c 156 }
4368b993 157 } else {
7df20ca4 158 /* Data ready. By its nature, this viewer doesn't need to have
618fbcc1 159 * its data ready hook called there, because a background
4368b993 160 * request is always linked with a redraw.
161 */
6395d57c 162 }
4368b993 163
6395d57c 164 }
165
166 lttv_hooks_destroy(background_ready_hook);
167}
168
169
170
171
f0d936c0 172/**
173 * Event Viewer's constructor hook
174 *
175 * This constructor is given as a parameter to the menuitem and toolbar button
176 * registration. It creates the list.
ca0f8a8e 177 * @param tab A pointer to the parent tab.
f0d936c0 178 * @return The widget created.
179 */
180GtkWidget *
e433e6d6 181h_guicontrolflow(LttvPlugin *plugin)
f0d936c0 182{
e433e6d6 183 LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
184 Tab *tab = ptab->tab;
d47b33d2 185 g_info("h_guicontrolflow, %p", tab);
e433e6d6 186 ControlFlowData *control_flow_data = guicontrolflow(ptab);
a56a1ba4 187
ca0f8a8e 188 control_flow_data->tab = tab;
a56a1ba4 189
a56a1ba4 190 // Unreg done in the GuiControlFlow_Destructor
6395d57c 191 lttvwindow_register_traceset_notify(tab,
192 traceset_notify,
193 control_flow_data);
194
ca0f8a8e 195 lttvwindow_register_time_window_notify(tab,
224446ce 196 update_time_window_hook,
197 control_flow_data);
ca0f8a8e 198 lttvwindow_register_current_time_notify(tab,
224446ce 199 update_current_time_hook,
200 control_flow_data);
ca0f8a8e 201 lttvwindow_register_redraw_notify(tab,
202 redraw_notify,
203 control_flow_data);
204 lttvwindow_register_continue_notify(tab,
205 continue_notify,
206 control_flow_data);
667ca2a0 207 request_background_data(control_flow_data);
6395d57c 208
ca0f8a8e 209
68997a22 210 return guicontrolflow_get_widget(control_flow_data) ;
a56a1ba4 211
f0d936c0 212}
213
3cff8cc1 214int event_selected_hook(void *hook_data, void *call_data)
f0d936c0 215{
14963be0 216 guint *event_number = (guint*) call_data;
f0d936c0 217
2a2fa4f0 218 g_debug("DEBUG : event selected by main window : %u", *event_number);
a56a1ba4 219
2eef04b5 220 return 0;
f0d936c0 221}
222
9a1ec01b 223/* Function that selects the color of status&exemode line */
6550d711 224static inline PropertiesLine prepare_s_e_line(LttvProcessState *process)
9a1ec01b 225{
226 PropertiesLine prop_line;
5bb606ce 227 prop_line.line_width = STATE_LINE_WIDTH;
9a1ec01b 228 prop_line.style = GDK_LINE_SOLID;
229 prop_line.y = MIDDLE;
230 //GdkColormap *colormap = gdk_colormap_get_system();
231
9a1ec01b 232 if(process->state->s == LTTV_STATE_RUN) {
233 if(process->state->t == LTTV_STATE_USER_MODE)
234 prop_line.color = drawing_colors[COL_RUN_USER_MODE];
235 else if(process->state->t == LTTV_STATE_SYSCALL)
236 prop_line.color = drawing_colors[COL_RUN_SYSCALL];
237 else if(process->state->t == LTTV_STATE_TRAP)
238 prop_line.color = drawing_colors[COL_RUN_TRAP];
239 else if(process->state->t == LTTV_STATE_IRQ)
240 prop_line.color = drawing_colors[COL_RUN_IRQ];
faf074a3 241 else if(process->state->t == LTTV_STATE_SOFT_IRQ)
242 prop_line.color = drawing_colors[COL_RUN_SOFT_IRQ];
f044974e
MD
243 else if(process->state->t == LTTV_STATE_MAYBE_SYSCALL)
244 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
245 else if(process->state->t == LTTV_STATE_MAYBE_USER_MODE)
246 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
247 else if(process->state->t == LTTV_STATE_MAYBE_TRAP)
248 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
9a1ec01b 249 else if(process->state->t == LTTV_STATE_MODE_UNKNOWN)
250 prop_line.color = drawing_colors[COL_MODE_UNKNOWN];
251 else
252 g_assert(FALSE); /* RUNNING MODE UNKNOWN */
253 } else if(process->state->s == LTTV_STATE_WAIT) {
254 /* We don't show if we wait while in user mode, trap, irq or syscall */
255 prop_line.color = drawing_colors[COL_WAIT];
256 } else if(process->state->s == LTTV_STATE_WAIT_CPU) {
257 /* We don't show if we wait for CPU while in user mode, trap, irq
258 * or syscall */
259 prop_line.color = drawing_colors[COL_WAIT_CPU];
260 } else if(process->state->s == LTTV_STATE_ZOMBIE) {
261 prop_line.color = drawing_colors[COL_ZOMBIE];
262 } else if(process->state->s == LTTV_STATE_WAIT_FORK) {
263 prop_line.color = drawing_colors[COL_WAIT_FORK];
264 } else if(process->state->s == LTTV_STATE_EXIT) {
265 prop_line.color = drawing_colors[COL_EXIT];
266 } else if(process->state->s == LTTV_STATE_UNNAMED) {
267 prop_line.color = drawing_colors[COL_UNNAMED];
c7620c79 268 } else if(process->state->s == LTTV_STATE_DEAD) {
269 prop_line.color = drawing_colors[COL_DEAD];
b3fd4c02 270 } else {
271 g_critical("unknown state : %s", g_quark_to_string(process->state->s));
9a1ec01b 272 g_assert(FALSE); /* UNKNOWN STATE */
b3fd4c02 273 }
9a1ec01b 274
275 return prop_line;
276
277}
278
98dfb302
YB
279HashedProcessData *get_hashed_process_data(ControlFlowData *control_flow_data,
280 LttvProcessState *process,
281 guint pid,
282 guint trace_num)
283{
284 HashedProcessData *hashed_process_data = NULL;
285 ProcessList *process_list = control_flow_data->process_list;
286 LttTime birth = process->creation_time;
287 guint pl_height = 0;
288
289 hashed_process_data = processlist_get_process_data(process_list,
290 pid,
291 process->cpu,
292 &birth,
293 trace_num);
294 if(hashed_process_data == NULL)
295 {
296 g_assert(pid == 0 || pid != process->ppid);
297 ProcessInfo *process_info;
298 Drawing_t *drawing = control_flow_data->drawing;
299 /* Process not present */
300 processlist_add(process_list,
301 drawing,
302 pid,
303 process->tgid,
304 process->cpu,
305 process->ppid,
306 &birth,
307 trace_num,
308 process->name,
98dfb302
YB
309 &pl_height,
310 &process_info,
311 &hashed_process_data);
312 gtk_widget_set_size_request(drawing->drawing_area,
313 -1,
314 pl_height);
315 gtk_widget_queue_draw(drawing->drawing_area);
316 }
317 return hashed_process_data;
318}
319
320void init_drawing_context(DrawContext *draw_context,
321 HashedProcessData *hashed_process_data,
322 Drawing_t *drawing,
323 guint x
324 )
325{
326 draw_context->drawable = hashed_process_data->pixmap;
327 draw_context->gc = drawing->gc;
328 draw_context->pango_layout = drawing->pango_layout;
329 draw_context->drawinfo.start.x = hashed_process_data->x.middle;
330 draw_context->drawinfo.end.x = x;
331
332 draw_context->drawinfo.y.over = 1;
333 draw_context->drawinfo.y.middle = (hashed_process_data->height/2);
334 draw_context->drawinfo.y.under = hashed_process_data->height;
335
336 draw_context->drawinfo.start.offset.over = 0;
337 draw_context->drawinfo.start.offset.middle = 0;
338 draw_context->drawinfo.start.offset.under = 0;
339 draw_context->drawinfo.end.offset.over = 0;
340 draw_context->drawinfo.end.offset.middle = 0;
341 draw_context->drawinfo.end.offset.under = 0;
342
343}
344
345void draw_state_line(HashedProcessData *hashed_process_data,
346 LttvProcessState *process,
347 Drawing_t *drawing,
348 guint x,
349 TimeWindow time_window)
350{
351 DrawContext draw_context;
352 guint width = drawing->width;
353
354 init_drawing_context(&draw_context,
355 hashed_process_data,
356 drawing,
357 x);
358
359
360 /* Draw the line */
361 PropertiesLine prop_line = prepare_s_e_line(process);
362 draw_line((void*)&prop_line, (void*)&draw_context);
363
364 /* become the last x position */
365 hashed_process_data->x.middle = x;
366 hashed_process_data->x.middle_used = TRUE;
367 hashed_process_data->x.middle_marked = FALSE;
368
369 /* Calculate the next good time */
370 convert_pixels_to_time(width, x+1, time_window,
371 &hashed_process_data->next_good_time);
372}
373
374
375void draw_state_items(ControlFlowData *control_flow_data,
376 HashedProcessData *hashed_process_data,
377 LttvProcessState *process,
378 LttTime evtime )
379{
380
381
382 if(likely(ltt_time_compare(hashed_process_data->next_good_time,
383 evtime) > 0))
384 {
385 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
386 TimeWindow time_window =
387 lttvwindow_get_time_window(control_flow_data->tab);
388
389#ifdef EXTRA_CHECK
390 if(ltt_time_compare(evtime, time_window.start_time) == -1
391 || ltt_time_compare(evtime, time_window.end_time) == 1)
392 return FALSE;
393#endif //EXTRA_CHECK
394 Drawing_t *drawing = control_flow_data->drawing;
395 guint width = drawing->width;
396 guint x;
397 convert_time_to_pixels(
398 time_window,
399 evtime,
400 width,
401 &x);
402
403 /* Draw collision indicator */
404 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
405 gdk_draw_point(hashed_process_data->pixmap,
406 drawing->gc,
407 x,
408 COLLISION_POSITION(hashed_process_data->height));
409 hashed_process_data->x.middle_marked = TRUE;
410 }
411 } else {
412 TimeWindow time_window =
413 lttvwindow_get_time_window(control_flow_data->tab);
414
415#ifdef EXTRA_CHECK
416 if(ltt_time_compare(evtime, time_window.start_time) == -1
417 || ltt_time_compare(evtime, time_window.end_time) == 1)
418 return FALSE;
419#endif //EXTRA_CHECK
420 Drawing_t *drawing = control_flow_data->drawing;
421 guint width = drawing->width;
422 guint x;
423
424 convert_time_to_pixels(
425 time_window,
426 evtime,
427 width,
428 &x);
429
430
431 /* Jump over draw if we are at the same x position */
432 if(unlikely(x == hashed_process_data->x.middle &&
433 hashed_process_data->x.middle_used))
434 {
435 if(unlikely(hashed_process_data->x.middle_marked == FALSE)) {
436 /* Draw collision indicator */
437 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
438 gdk_draw_point(hashed_process_data->pixmap,
439 drawing->gc,
440 x,
441 COLLISION_POSITION(hashed_process_data->height));
442 hashed_process_data->x.middle_marked = TRUE;
443 }
444 /* jump */
445 } else {
446
447 draw_state_line(hashed_process_data,
448 process,
449 drawing,
450 x,
451 time_window);
452 }
453 }
454}
455
456
068572ab
CS
457/* Before try-wake-up hook. A process is being woken; we need to draw its line up to this point in time
458 in that colour. This is basically like exec-state, but the change applies to a process other than that
459 which is currently running. */
460
461int before_trywakeup_hook(void *hook_data, void *call_data)
462{
88bf15f0 463
7b20eed1 464 LttvEvent *event;
068572ab 465
7b20eed1
YB
466 event = (LttvEvent *) call_data;
467 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_wakeup") != 0)
468 return FALSE;
068572ab 469
7b20eed1 470 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
068572ab 471
7b20eed1 472 LttvTraceState *ts = event->state;;
068572ab 473
7b20eed1
YB
474
475 LttTime evtime = lttv_event_get_timestamp(event);
476#ifdef BABEL_CLEANUP
068572ab 477 LttvFilter *filter = control_flow_data->filter;
7b20eed1 478#endif
068572ab
CS
479
480 guint woken_pid;
481 gint woken_cpu;
482
7b20eed1
YB
483 woken_pid = lttv_event_get_long(event, "tid");
484 woken_cpu = lttv_event_get_long(event, "target_cpu");
485
486#ifdef BABEL_CLEANUP
068572ab
CS
487 if(!filter || !filter->head ||
488 lttv_filter_tree_parse(filter->head,e,tfc->tf,
489 tfc->t_context->t,tfc,NULL,NULL)) {
7b20eed1
YB
490#else
491 {
492#endif
068572ab
CS
493 /* First, check if the woken process is in the state computation
494 * process list. If it is there, that means we must add it right now and
495 * draw items from the beginning of the read for it. If it is not
496 * present, it's a new process and it was not present : it will
497 * be added after the state update. TOCHECK: What does that last para mean? */
8284135e 498 guint trace_num = lttv_traceset_get_trace_index_from_event(event);
7b20eed1 499 LttvProcessState *process = lttv_state_find_process(ts, woken_cpu, woken_pid);
068572ab
CS
500
501 if(process != NULL) {
502 /* Well, the woken process existed : we must get it in the process hash
503 * or add it, and draw its items.
504 */
505 /* Add process to process list (if not present) */
068572ab 506
98dfb302 507 HashedProcessData *hashed_process_data = get_hashed_process_data(control_flow_data, process, woken_pid, trace_num);
068572ab
CS
508
509 /* Now, the process is in the state hash and our own process hash.
510 * We definitely can draw the items related to the ending state.
511 */
068572ab 512
98dfb302
YB
513 draw_state_items(control_flow_data,
514 hashed_process_data,
515 process,
516 evtime );
068572ab 517
068572ab
CS
518 }
519 }
520
068572ab 521
7b20eed1
YB
522
523
10599fb9 524 return 0;
068572ab
CS
525
526}
c8bba5fa 527
e92eabaf 528/* before_schedchange_hook
b9a010a2 529 *
f0d936c0 530 * This function basically draw lines and icons. Two types of lines are drawn :
531 * one small (3 pixels?) representing the state of the process and the second
532 * type is thicker (10 pixels?) representing on which CPU a process is running
533 * (and this only in running state).
534 *
535 * Extremums of the lines :
536 * x_min : time of the last event context for this process kept in memory.
537 * x_max : time of the current event.
538 * y : middle of the process in the process list. The process is found in the
539 * list, therefore is it's position in pixels.
540 *
541 * The choice of lines'color is defined by the context of the last event for this
542 * process.
543 */
b9a010a2 544
545
e92eabaf 546int before_schedchange_hook(void *hook_data, void *call_data)
f0d936c0 547{
88bf15f0
FD
548 LttvEvent *event;
549 guint cpu;
550 LttvTraceState *ts;
551 LttvProcessState *process;
552
553 //LttvProcessState *old_process = ts->running_process[cpu];
554
555 guint pid_in, pid_out;
556 gint64 state_out;
98dfb302 557 LttTime evtime;
88bf15f0 558 event = (LttvEvent *) call_data;
8924e3e4
FD
559 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_switch") != 0)
560 return FALSE;
561
88bf15f0 562 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
b9a010a2 563
fd22065b 564
10a1069a 565 /* we are in a schedchange, before the state update. We must draw the
566 * items corresponding to the state before it changes : now is the right
567 * time to do it.
568 */
88bf15f0
FD
569 cpu = lttv_traceset_get_cpuid_from_event(event);
570 ts = event->state;
8924e3e4 571
88bf15f0
FD
572 pid_out = lttv_event_get_long(event, "prev_tid");
573 pid_in = lttv_event_get_long(event, "next_tid");
574 state_out = lttv_event_get_long(event, "prev_state");
8284135e 575 guint trace_number = lttv_traceset_get_trace_index_from_event(event);
88bf15f0 576
8924e3e4 577 process = lttv_state_find_process(ts,cpu,pid_out);
98dfb302 578 evtime = lttv_event_get_timestamp(event);
10a1069a 579 /* For the pid_out */
580 /* First, check if the current process is in the state computation
581 * process list. If it is there, that means we must add it right now and
582 * draw items from the beginning of the read for it. If it is not
583 * present, it's a new process and it was not present : it will
584 * be added after the state update. */
b9a010a2 585
88bf15f0
FD
586 /* unknown state, bad current pid */
587
10a1069a 588 if(process != NULL) {
589 /* Well, the process_out existed : we must get it in the process hash
590 * or add it, and draw its items.
591 */
592 /* Add process to process list (if not present) */
1c736ed5 593
98dfb302
YB
594 HashedProcessData *hashed_process_data = get_hashed_process_data(control_flow_data, process, pid_out, trace_number);
595
10a1069a 596 /* Now, the process is in the state hash and our own process hash.
597 * We definitely can draw the items related to the ending state.
598 */
e800cf84 599
98dfb302
YB
600 draw_state_items(control_flow_data,
601 hashed_process_data,
602 process,
603 evtime );
e800cf84 604 }
605
10a1069a 606 /* For the pid_in */
607 /* First, check if the current process is in the state computation
608 * process list. If it is there, that means we must add it right now and
609 * draw items from the beginning of the read for it. If it is not
610 * present, it's a new process and it was not present : it will
611 * be added after the state update. */
8924e3e4 612 process = lttv_state_find_process(ts,cpu,pid_in);
10a1069a 613
614 if(process != NULL) {
800aa029 615 /* Well, the process existed : we must get it in the process hash
10a1069a 616 * or add it, and draw its items.
617 */
618 /* Add process to process list (if not present) */
1c736ed5 619
98dfb302
YB
620 HashedProcessData *hashed_process_data = get_hashed_process_data(control_flow_data, process, pid_in, trace_number);
621
40debf7b 622 //We could set the current process and hash here, but will be done
623 //by after schedchange hook
10a1069a 624
625 /* Now, the process is in the state hash and our own process hash.
626 * We definitely can draw the items related to the ending state.
627 */
98dfb302
YB
628 draw_state_items(control_flow_data,
629 hashed_process_data,
630 process,
631 evtime );
10a1069a 632
8e680509 633 } else
433e7ba0 634 g_warning("Cannot find pid_in in schedchange %u at %u.%u", pid_in, evtime.tv_sec, evtime.tv_nsec);
88bf15f0 635#ifdef BABEL_CLEANUP
e38d9ea0 636 tfc->target_pid = target_pid_saved;
88bf15f0 637#endif //babel_cleanup
b9a010a2 638 return 0;
639
640
b9a010a2 641
a56a1ba4 642
51705146 643 /* Text dump */
80a52ff8 644#ifdef DONTSHOW
a56a1ba4 645 GString *string = g_string_new("");;
646 gboolean field_names = TRUE, state = TRUE;
80a52ff8 647
e9a9c513 648 lttv_event_to_string(e, tfc->tf, string, TRUE, field_names, tfs);
649 g_string_append_printf(string,"\n");
650
651 if(state) {
652 g_string_append_printf(string, " %s",
653 g_quark_to_string(tfs->process->state->s));
654 }
655
656 g_info("%s",string->str);
657
a56a1ba4 658 g_string_free(string, TRUE);
659
660 /* End of text dump */
80a52ff8 661#endif //DONTSHOW
50439712 662
f0d936c0 663}
664
e92eabaf 665/* after_schedchange_hook
b9a010a2 666 *
667 * The draw after hook is called by the reading API to have a
668 * particular event drawn on the screen.
669 * @param hook_data ControlFlowData structure of the viewer.
670 * @param call_data Event context.
671 *
672 * This function adds items to be drawn in a queue for each process.
673 *
674 */
e92eabaf 675int after_schedchange_hook(void *hook_data, void *call_data)
f0d936c0 676{
7b20eed1 677 LttvEvent *event;
50439712 678
7b20eed1
YB
679 event = (LttvEvent *) call_data;
680
681 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_switch") != 0)
682 return FALSE;
50439712 683
7b20eed1 684 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
50439712 685
348c6ba8 686
7b20eed1 687 LttvTraceState *ts = event->state;
b9a010a2 688
7b20eed1 689#ifdef BABEL_CLEANUP
e38d9ea0 690 LttvFilter *filter = control_flow_data->filter;
7b20eed1
YB
691#endif
692 LttTime evtime = lttv_event_get_timestamp(event);
b9a010a2 693
10a1069a 694 /* Add process to process list (if not present) */
2eef04b5 695 LttvProcessState *process_in;
10a1069a 696 HashedProcessData *hashed_process_data_in = NULL;
b9a010a2 697
5c230fc4 698 ProcessList *process_list = control_flow_data->process_list;
10a1069a 699
700 guint pid_in;
701 {
7b20eed1 702 pid_in = lttv_event_get_long(event, "next_tid");
10a1069a 703 }
b9a010a2 704
7b20eed1 705#ifdef BABEL_CLEANUP
c7620c79 706 if(!filter || !filter->head ||
707 lttv_filter_tree_parse(filter->head,e,tfc->tf,
708 tfc->t_context->t,tfc,NULL,NULL)) {
7b20eed1
YB
709#else
710 {
711#endif
c7620c79 712 /* Find process pid_in in the list... */
713 //process_in = lttv_state_find_process(ts, ANY_CPU, pid_in);
714 //process_in = tfs->process;
7b20eed1 715 guint cpu = lttv_traceset_get_cpuid_from_event(event);
8284135e 716 guint trace_num = lttv_traceset_get_trace_index_from_event(event);
c7620c79 717 process_in = ts->running_process[cpu];
718 /* It should exist, because we are after the state update. */
96947fcf 719#ifdef EXTRA_CHECK
c7620c79 720 g_assert(process_in != NULL);
96947fcf 721#endif //EXTRA_CHECK
98dfb302
YB
722 hashed_process_data_in = get_hashed_process_data(control_flow_data, process_in, pid_in, trace_num);
723
c7620c79 724 /* Set the current process */
725 process_list->current_hash_data[trace_num][process_in->cpu] =
726 hashed_process_data_in;
727
728 if(ltt_time_compare(hashed_process_data_in->next_good_time,
729 evtime) <= 0)
730 {
731 TimeWindow time_window =
732 lttvwindow_get_time_window(control_flow_data->tab);
733
fd22065b 734#ifdef EXTRA_CHECK
c7620c79 735 if(ltt_time_compare(evtime, time_window.start_time) == -1
736 || ltt_time_compare(evtime, time_window.end_time) == 1)
737 return FALSE;
fd22065b 738#endif //EXTRA_CHECK
c7620c79 739 Drawing_t *drawing = control_flow_data->drawing;
740 guint width = drawing->width;
741 guint new_x;
742
743 convert_time_to_pixels(
744 time_window,
745 evtime,
746 width,
747 &new_x);
748
749 if(hashed_process_data_in->x.middle != new_x) {
750 hashed_process_data_in->x.middle = new_x;
751 hashed_process_data_in->x.middle_used = FALSE;
752 hashed_process_data_in->x.middle_marked = FALSE;
753 }
b2743953 754 }
755 }
c7620c79 756
10599fb9 757 return 0;
4a24fa1f 758}
b9a010a2 759
760
761
e72908ed 762
4a24fa1f 763/* before_execmode_hook
764 *
765 * This function basically draw lines and icons. Two types of lines are drawn :
766 * one small (3 pixels?) representing the state of the process and the second
767 * type is thicker (10 pixels?) representing on which CPU a process is running
768 * (and this only in running state).
769 *
770 * Extremums of the lines :
771 * x_min : time of the last event context for this process kept in memory.
772 * x_max : time of the current event.
773 * y : middle of the process in the process list. The process is found in the
774 * list, therefore is it's position in pixels.
775 *
776 * The choice of lines'color is defined by the context of the last event for this
777 * process.
778 */
779
e72908ed 780
4a24fa1f 781int before_execmode_hook(void *hook_data, void *call_data)
782{
88bf15f0
FD
783 LttvEvent *event;
784 guint cpu;
10599fb9 785 guint pid = 0;
88bf15f0
FD
786 LttvTraceState *ts;
787 LttvProcessState *process;
788
4a24fa1f 789 /* we are in a execmode, before the state update. We must draw the
790 * items corresponding to the state before it changes : now is the right
791 * time to do it.
792 */
88bf15f0
FD
793
794 event = (LttvEvent *) call_data;
8924e3e4
FD
795 if ((strncmp(lttv_traceset_get_name_from_event(event),"sys_", sizeof("sys_") - 1) == 0)
796 ||(strcmp(lttv_traceset_get_name_from_event(event),"exit_syscall") == 0)
d940a891
YB
797 ||(strncmp(lttv_traceset_get_name_from_event(event),"irq_handler_",sizeof("irq_handler_") -1) == 0)
798 ||(strncmp(lttv_traceset_get_name_from_event(event),"softirq_", sizeof("softirq_") - 1) == 0)) {
8924e3e4 799
88bf15f0
FD
800 LttTime evtime = lttv_event_get_timestamp(event);
801 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
4a24fa1f 802 /* For the pid */
88bf15f0
FD
803 LttvTraceset *traceSet = lttvwindow_get_traceset(control_flow_data->tab);
804
805 cpu = lttv_traceset_get_cpuid_from_event(event);
806 ts = event->state;
807
8284135e 808 guint trace_number = lttv_traceset_get_trace_index_from_event(event);
d940a891
YB
809
810 //TODO ybrosseau 2013-04-09 validate that using the running process is the right choice
811 //process = lttv_state_find_process(ts ,cpu ,pid);
812 process = ts->running_process[cpu];
813
4a24fa1f 814 g_assert(process != NULL);
23093869 815
10a1069a 816 guint pid = process->pid;
23093869 817
10a1069a 818 /* Well, the process_out existed : we must get it in the process hash
819 * or add it, and draw its items.
820 */
821 /* Add process to process list (if not present) */
10a1069a 822 HashedProcessData *hashed_process_data = NULL;
5c230fc4 823 ProcessList *process_list = control_flow_data->process_list;
88bf15f0
FD
824 if(process_list->current_hash_data == NULL){//TODO fdeslauriers 2012-07-17 : should not be necessary
825 return 0;
826 }
827
88bf15f0
FD
828 if(likely(process_list->current_hash_data[trace_number][cpu] != NULL)) {
829 hashed_process_data = process_list->current_hash_data[trace_number][cpu];
40debf7b 830 } else {
98dfb302
YB
831 hashed_process_data = get_hashed_process_data(control_flow_data,
832 process, pid, trace_number);
833
40debf7b 834 /* Set the current process */
88bf15f0 835 process_list->current_hash_data[trace_number][process->cpu] =
40debf7b 836 hashed_process_data;
10a1069a 837 }
23093869 838
10a1069a 839 /* Now, the process is in the state hash and our own process hash.
840 * We definitely can draw the items related to the ending state.
841 */
98dfb302
YB
842
843 draw_state_items(control_flow_data,
844 hashed_process_data,
845 process,
846 evtime );
8924e3e4 847 }
98dfb302 848
23093869 849 return 0;
98dfb302 850
23093869 851}
852
4a24fa1f 853/* before_process_exit_hook
23093869 854 *
4a24fa1f 855 * Draw lines for process event.
856 *
23093869 857 * @param hook_data ControlFlowData structure of the viewer.
858 * @param call_data Event context.
859 *
860 * This function adds items to be drawn in a queue for each process.
861 *
862 */
8869ac08 863
864
4a24fa1f 865int before_process_exit_hook(void *hook_data, void *call_data)
866{
23093869 867
7b20eed1 868 LttvEvent *event;
23093869 869
7b20eed1
YB
870 event = (LttvEvent *) call_data;
871 if (strcmp(lttv_traceset_get_name_from_event(event),
872 "sched_process_exit") != 0)
873 return FALSE;
4a24fa1f 874
7b20eed1
YB
875
876 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
877 LttvTraceState *ts = event->state;
23093869 878
7b20eed1 879#ifdef BABEL_CLEANUP
e38d9ea0 880 LttvFilter *filter = control_flow_data->filter;
881 if(filter != NULL && filter->head != NULL)
98dfb302
YB
882 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
883 tfc->t_context->t,tfc,NULL,NULL))
884 return FALSE;
885#endif
dbd243b1 886
98dfb302 887 LttTime evtime = lttv_event_get_timestamp(event);
dbd243b1 888
98dfb302
YB
889 /* Add process to process list (if not present) */
890 //LttvProcessState *process = tfs->process;
891 guint cpu = lttv_traceset_get_cpuid_from_event(event);
8284135e 892 guint trace_num = lttv_traceset_get_trace_index_from_event(event);
dbd243b1 893
98dfb302
YB
894 LttvProcessState *process = ts->running_process[cpu];
895 guint pid = process->pid;
896 HashedProcessData *hashed_process_data = NULL;
897
898 ProcessList *process_list = control_flow_data->process_list;
899
900 g_assert(process != NULL);
901
902 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
903 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
904 } else {
905 hashed_process_data = get_hashed_process_data(control_flow_data,
906 process, pid, trace_num);
2c82c4dc 907 }
7b20eed1 908
98dfb302
YB
909 /* Now, the process is in the state hash and our own process hash.
910 * We definitely can draw the items related to the ending state.
911 */
912
913 draw_state_items(control_flow_data,
914 hashed_process_data,
915 process,
916 evtime);
917
10599fb9 918 return 0;
2c82c4dc 919
920}
921
922
923
924/* before_process_release_hook
925 *
926 * Draw lines for process event.
927 *
928 * @param hook_data ControlFlowData structure of the viewer.
929 * @param call_data Event context.
930 *
931 * This function adds items to be drawn in a queue for each process.
932 *
933 */
934
935
936int before_process_release_hook(void *hook_data, void *call_data)
937{
2c82c4dc 938
7b20eed1 939 LttvEvent *event;
2c82c4dc 940
7b20eed1
YB
941 event = (LttvEvent *) call_data;
942
943 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_process_free") != 0)
944 return FALSE;
2c82c4dc 945
7b20eed1 946 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
348c6ba8 947
2c82c4dc 948
7b20eed1
YB
949 LttvTraceState *ts = event->state;
950
951#ifdef BABEL_CLEANUP
e38d9ea0 952 LttvFilter *filter = control_flow_data->filter;
953 if(filter != NULL && filter->head != NULL)
954 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 955 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 956 return FALSE;
7b20eed1
YB
957#endif
958 LttTime evtime = lttv_event_get_timestamp(event);
e38d9ea0 959
2c82c4dc 960
8284135e 961 guint trace_num = lttv_traceset_get_trace_index_from_event(event);
2c82c4dc 962
963 guint pid;
964 {
7b20eed1 965 pid = lttv_event_get_long(event, "tid");
2c82c4dc 966 }
967
968 /* Add process to process list (if not present) */
969 /* Don't care about the process if it's not in the state hash already :
970 * that means a process that has never done anything in the trace and
971 * unknown suddently gets destroyed : no state meaningful to show. */
348c6ba8 972 LttvProcessState *process = lttv_state_find_process(ts, ANY_CPU, pid);
2c82c4dc 973
974 if(process != NULL) {
975 LttTime birth;
2c82c4dc 976 HashedProcessData *hashed_process_data = NULL;
977
978 ProcessList *process_list = control_flow_data->process_list;
979
980 birth = process->creation_time;
981
982 /* Cannot use current process : this event happens on another process,
983 * action done by the parent. */
984 hashed_process_data = processlist_get_process_data(process_list,
985 pid,
348c6ba8 986 process->cpu,
2c82c4dc 987 &birth,
0f090e21 988 trace_num);
2c82c4dc 989 if(unlikely(hashed_process_data == NULL))
3311444c 990 /*
991 * Process already been scheduled out EXIT_DEAD, not in the process list
992 * anymore. Just return.
993 */
994 return FALSE;
2c82c4dc 995
996 /* Now, the process is in the state hash and our own process hash.
997 * We definitely can draw the items related to the ending state.
998 */
999
98dfb302
YB
1000 draw_state_items(control_flow_data,
1001 hashed_process_data,
1002 process,
1003 evtime);
dbd243b1 1004 }
10599fb9 1005 return 0;
dbd243b1 1006}
1007
4a24fa1f 1008
2c82c4dc 1009
1010
1011
1012/* after_process_fork_hook
1013 *
1014 * Create the processlist entry for the child process. Put the last
1015 * position in x at the current time value.
1016 *
1017 * @param hook_data ControlFlowData structure of the viewer.
1018 * @param call_data Event context.
1019 *
1020 * This function adds items to be drawn in a queue for each process.
1021 *
1022 */
1023int after_process_fork_hook(void *hook_data, void *call_data)
1024{
7b20eed1 1025 LttvEvent *event;
2c82c4dc 1026
7b20eed1
YB
1027 event = (LttvEvent *) call_data;
1028
1029 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_process_fork") != 0)
1030 return FALSE;
2c82c4dc 1031
7b20eed1 1032 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
348c6ba8 1033
2c82c4dc 1034
7b20eed1
YB
1035 LttvTraceState *ts = event->state;
1036
1037#ifdef BABEL_CLEANUP
e38d9ea0 1038 LttvFilter *filter = control_flow_data->filter;
1039 if(filter != NULL && filter->head != NULL)
1040 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1041 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1042 return FALSE;
7b20eed1 1043#endif
e38d9ea0 1044
7b20eed1 1045 LttTime evtime = lttv_event_get_timestamp(event);
2c82c4dc 1046
1047 guint child_pid;
1048 {
7b20eed1 1049 child_pid = lttv_event_get_long(event, "child_tid");
2c82c4dc 1050 }
1051
1052 /* Add process to process list (if not present) */
1053 LttvProcessState *process_child;
2c82c4dc 1054 HashedProcessData *hashed_process_data_child = NULL;
1055
1056 ProcessList *process_list = control_flow_data->process_list;
1057
1058 /* Find child in the list... */
348c6ba8 1059 process_child = lttv_state_find_process(ts, ANY_CPU, child_pid);
2c82c4dc 1060 /* It should exist, because we are after the state update. */
1061 g_assert(process_child != NULL);
1062
8284135e 1063 guint trace_num = lttv_traceset_get_trace_index_from_event(event);
2c82c4dc 1064
1065 /* Cannot use current process, because this action is done by the parent
1066 * on its child. */
98dfb302
YB
1067 hashed_process_data_child = get_hashed_process_data(control_flow_data,
1068 process_child, child_pid, trace_num);
1069
1070
fcc08e1e 1071 processlist_set_ppid(process_list, process_child->ppid,
1072 hashed_process_data_child);
1073 processlist_set_tgid(process_list, process_child->tgid,
1074 hashed_process_data_child);
98dfb302 1075
2c82c4dc 1076
1077
1078 if(likely(ltt_time_compare(hashed_process_data_child->next_good_time,
1079 evtime) <= 0))
1080 {
1081 TimeWindow time_window =
1082 lttvwindow_get_time_window(control_flow_data->tab);
1083
1084#ifdef EXTRA_CHECK
1085 if(ltt_time_compare(evtime, time_window.start_time) == -1
1086 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1087 return FALSE;
2c82c4dc 1088#endif //EXTRA_CHECK
1089 Drawing_t *drawing = control_flow_data->drawing;
1090 guint width = drawing->width;
1091 guint new_x;
1092 convert_time_to_pixels(
1093 time_window,
1094 evtime,
1095 width,
1096 &new_x);
1097
1098 if(likely(hashed_process_data_child->x.over != new_x)) {
1099 hashed_process_data_child->x.over = new_x;
1100 hashed_process_data_child->x.over_used = FALSE;
1101 hashed_process_data_child->x.over_marked = FALSE;
1102 }
1103 if(likely(hashed_process_data_child->x.middle != new_x)) {
1104 hashed_process_data_child->x.middle = new_x;
1105 hashed_process_data_child->x.middle_used = FALSE;
1106 hashed_process_data_child->x.middle_marked = FALSE;
1107 }
1108 if(likely(hashed_process_data_child->x.under != new_x)) {
1109 hashed_process_data_child->x.under = new_x;
1110 hashed_process_data_child->x.under_used = FALSE;
1111 hashed_process_data_child->x.under_marked = FALSE;
1112 }
1113 }
10599fb9 1114 return FALSE;
2c82c4dc 1115}
1116
1117
1118
1119/* after_process_exit_hook
1120 *
1121 * Create the processlist entry for the child process. Put the last
1122 * position in x at the current time value.
1123 *
1124 * @param hook_data ControlFlowData structure of the viewer.
1125 * @param call_data Event context.
1126 *
1127 * This function adds items to be drawn in a queue for each process.
1128 *
1129 */
1130int after_process_exit_hook(void *hook_data, void *call_data)
1131{
31799520 1132
7b20eed1 1133 LttvEvent *event;
2c82c4dc 1134
7b20eed1
YB
1135 event = (LttvEvent *) call_data;
1136
1137 if (strcmp(lttv_traceset_get_name_from_event(event),"sched_process_exit") != 0)
1138 return FALSE;
2c82c4dc 1139
7b20eed1 1140 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
348c6ba8 1141
7b20eed1 1142 LttvTraceState *ts = event->state;
2c82c4dc 1143
7b20eed1 1144#ifdef BABEL_CLEANUP
e38d9ea0 1145 LttvFilter *filter = control_flow_data->filter;
1146 if(filter != NULL && filter->head != NULL)
1147 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1148 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1149 return FALSE;
7b20eed1 1150#endif
e38d9ea0 1151
7b20eed1 1152 LttTime evtime = lttv_event_get_timestamp(event);
2c82c4dc 1153
1154 /* Add process to process list (if not present) */
348c6ba8 1155 //LttvProcessState *process = tfs->process;
7b20eed1 1156 guint cpu = lttv_traceset_get_cpuid_from_event(event);
8284135e 1157 guint trace_num = lttv_traceset_get_trace_index_from_event(event);
348c6ba8 1158 LttvProcessState *process = ts->running_process[cpu];
1159
1160 /* It should exist, because we are after the state update. */
1161 g_assert(process != NULL);
1162
2c82c4dc 1163 guint pid = process->pid;
31799520
YB
1164 //LttTime birth;
1165 //guint pl_height = 0;
2c82c4dc 1166 HashedProcessData *hashed_process_data = NULL;
1167
1168 ProcessList *process_list = control_flow_data->process_list;
1169
31799520 1170 //birth = process->creation_time;
2c82c4dc 1171
0f090e21 1172 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL) ){
1173 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
2c82c4dc 1174 } else {
98dfb302 1175 hashed_process_data = get_hashed_process_data(control_flow_data,
31799520 1176 process, pid, trace_num);
98dfb302 1177
2c82c4dc 1178
1179 /* Set the current process */
0f090e21 1180 process_list->current_hash_data[trace_num][process->cpu] =
2c82c4dc 1181 hashed_process_data;
1182 }
1183
1184 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
1185 evtime) <= 0))
1186 {
1187 TimeWindow time_window =
1188 lttvwindow_get_time_window(control_flow_data->tab);
dbd243b1 1189
2c82c4dc 1190#ifdef EXTRA_CHECK
1191 if(ltt_time_compare(evtime, time_window.start_time) == -1
1192 || ltt_time_compare(evtime, time_window.end_time) == 1)
3311444c 1193 return FALSE;
2c82c4dc 1194#endif //EXTRA_CHECK
1195 Drawing_t *drawing = control_flow_data->drawing;
1196 guint width = drawing->width;
1197 guint new_x;
1198 convert_time_to_pixels(
1199 time_window,
1200 evtime,
1201 width,
1202 &new_x);
1203 if(unlikely(hashed_process_data->x.middle != new_x)) {
1204 hashed_process_data->x.middle = new_x;
1205 hashed_process_data->x.middle_used = FALSE;
1206 hashed_process_data->x.middle_marked = FALSE;
1207 }
1208 }
31799520 1209
10599fb9 1210 return FALSE;
2c82c4dc 1211}
dbd243b1 1212
1213
f4b88a7d 1214/* Get the filename of the process to print */
1215int after_fs_exec_hook(void *hook_data, void *call_data)
1216{
88bf15f0 1217#ifdef BABEL_CLEANUP
dd455fb8 1218 LttvTraceHook *th = (LttvTraceHook*)hook_data;
1219 EventsRequest *events_request = (EventsRequest*)th->hook_data;
f4b88a7d 1220 ControlFlowData *control_flow_data = events_request->viewer_data;
1221
1222 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
1223
1224 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
1225
1226 LttvTraceState *ts = (LttvTraceState *)tfc->t_context;
1227
e38d9ea0 1228 LttEvent *e;
1229 e = ltt_tracefile_get_event(tfc->tf);
1230
1231 LttvFilter *filter = control_flow_data->filter;
1232 if(filter != NULL && filter->head != NULL)
1233 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1234 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1235 return FALSE;
1236
ae3d0f50 1237 guint cpu = tfs->cpu;
0f090e21 1238 guint trace_num = ts->parent.index;
f4b88a7d 1239 LttvProcessState *process = ts->running_process[cpu];
1240 g_assert(process != NULL);
1241
1242 guint pid = process->pid;
1243
1244 /* Well, the process_out existed : we must get it in the process hash
1245 * or add it, and draw its items.
1246 */
1247 /* Add process to process list (if not present) */
1248 guint pl_height = 0;
1249 HashedProcessData *hashed_process_data = NULL;
1250 ProcessList *process_list = control_flow_data->process_list;
1251 LttTime birth = process->creation_time;
1252
0f090e21 1253 if(likely(process_list->current_hash_data[trace_num][cpu] != NULL)) {
1254 hashed_process_data = process_list->current_hash_data[trace_num][cpu];
f4b88a7d 1255 } else {
98dfb302
YB
1256 hashed_process_data = get_hashed_process_data(control_flow_data,
1257 process, pid, trace_num);
f4b88a7d 1258 /* Set the current process */
0f090e21 1259 process_list->current_hash_data[trace_num][process->cpu] =
f4b88a7d 1260 hashed_process_data;
1261 }
1262
1263 processlist_set_name(process_list, process->name, hashed_process_data);
1264
88bf15f0 1265#endif //babel_cleanup
10599fb9 1266 return 0;
f4b88a7d 1267
1268}
1269
b3fd4c02 1270/* after_event_enum_process_hook
1271 *
b3fd4c02 1272 * Create the processlist entry for the child process. Put the last
1273 * position in x at the current time value.
1274 *
1275 * @param hook_data ControlFlowData structure of the viewer.
1276 * @param call_data Event context.
1277 *
1278 * This function adds items to be drawn in a queue for each process.
1279 *
1280 */
1281int after_event_enum_process_hook(void *hook_data, void *call_data)
1282{
7b20eed1 1283 LttvEvent *event;
b3fd4c02 1284
7b20eed1
YB
1285 event = (LttvEvent *) call_data;
1286
1287 if (strcmp(lttv_traceset_get_name_from_event(event),"lttng_statedump_process_state") != 0)
1288 return FALSE;
b3fd4c02 1289
7b20eed1 1290 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
b3fd4c02 1291
c4a72569 1292
7b20eed1 1293 LttvTraceState *ts = event->state;
b3fd4c02 1294
7b20eed1
YB
1295 guint first_cpu, nb_cpus, cpu;
1296
1297#ifdef BABEL_CLEANUP
e38d9ea0 1298 LttvFilter *filter = control_flow_data->filter;
1299 if(filter != NULL && filter->head != NULL)
1300 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 1301 tfc->t_context->t,tfc,NULL,NULL))
e38d9ea0 1302 return FALSE;
7b20eed1 1303#endif
b3fd4c02 1304 /* Add process to process list (if not present) */
1305 LttvProcessState *process_in;
b3fd4c02 1306 HashedProcessData *hashed_process_data_in = NULL;
1307
1308 ProcessList *process_list = control_flow_data->process_list;
8284135e 1309 guint trace_num = lttv_traceset_get_trace_index_from_event(event);
b3fd4c02 1310
1311 guint pid_in;
1312 {
7b20eed1 1313 pid_in = lttv_event_get_long(event, "tid");
b3fd4c02 1314 }
c4a72569 1315
1316 if(pid_in == 0) {
1317 first_cpu = 0;
7b20eed1 1318 nb_cpus = lttv_trace_get_num_cpu(ts->trace);
c4a72569 1319 } else {
1320 first_cpu = ANY_CPU;
1321 nb_cpus = ANY_CPU+1;
1322 }
b3fd4c02 1323
c4a72569 1324 for(cpu = first_cpu; cpu < nb_cpus; cpu++) {
1325 /* Find process pid_in in the list... */
1326 process_in = lttv_state_find_process(ts, cpu, pid_in);
1327 //process_in = tfs->process;
1328 //guint cpu = tfs->cpu;
1329 //guint trace_num = ts->parent.index;
1330 //process_in = ts->running_process[cpu];
1331 /* It should exist, because we are after the state update. */
1332 #ifdef EXTRA_CHECK
1333 //g_assert(process_in != NULL);
1334 #endif //EXTRA_CHECK
c4a72569 1335
98dfb302
YB
1336 hashed_process_data_in = get_hashed_process_data(control_flow_data,
1337 process_in, pid_in, trace_num);
1338
c4a72569 1339 processlist_set_name(process_list, process_in->name,
1340 hashed_process_data_in);
1341 processlist_set_ppid(process_list, process_in->ppid,
1342 hashed_process_data_in);
1343 processlist_set_tgid(process_list, process_in->tgid,
1344 hashed_process_data_in);
98dfb302 1345
c4a72569 1346 }
10599fb9 1347 return 0;
b3fd4c02 1348}
f4b88a7d 1349
1350
1b238973 1351gint update_time_window_hook(void *hook_data, void *call_data)
f7afe191 1352{
a56a1ba4 1353 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
98dfb302 1354
a43d67ba 1355 Drawing_t *drawing = control_flow_data->drawing;
1c736ed5 1356 ProcessList *process_list = control_flow_data->process_list;
a43d67ba 1357
224446ce 1358 const TimeWindowNotifyData *time_window_nofify_data =
1359 ((const TimeWindowNotifyData *)call_data);
1360
14963be0 1361 TimeWindow *old_time_window =
224446ce 1362 time_window_nofify_data->old_time_window;
1363 TimeWindow *new_time_window =
1364 time_window_nofify_data->new_time_window;
a56a1ba4 1365
3cb8b205 1366 /* Update the ruler */
1367 drawing_update_ruler(control_flow_data->drawing,
1368 new_time_window);
1369
1370
a56a1ba4 1371 /* Two cases : zoom in/out or scrolling */
1372
1373 /* In order to make sure we can reuse the old drawing, the scale must
1374 * be the same and the new time interval being partly located in the
1375 * currently shown time interval. (reuse is only for scrolling)
1376 */
1377
2eef04b5 1378 g_info("Old time window HOOK : %lu, %lu to %lu, %lu",
14963be0 1379 old_time_window->start_time.tv_sec,
1380 old_time_window->start_time.tv_nsec,
1381 old_time_window->time_width.tv_sec,
1382 old_time_window->time_width.tv_nsec);
a56a1ba4 1383
2eef04b5 1384 g_info("New time window HOOK : %lu, %lu to %lu, %lu",
14963be0 1385 new_time_window->start_time.tv_sec,
1386 new_time_window->start_time.tv_nsec,
1387 new_time_window->time_width.tv_sec,
1388 new_time_window->time_width.tv_nsec);
a56a1ba4 1389
14963be0 1390 if( new_time_window->time_width.tv_sec == old_time_window->time_width.tv_sec
1391 && new_time_window->time_width.tv_nsec == old_time_window->time_width.tv_nsec)
a56a1ba4 1392 {
1393 /* Same scale (scrolling) */
1394 g_info("scrolling");
14963be0 1395 LttTime *ns = &new_time_window->start_time;
1396 LttTime *os = &old_time_window->start_time;
6f26fc38 1397 LttTime old_end = old_time_window->end_time;
1398 LttTime new_end = new_time_window->end_time;
a56a1ba4 1399 //if(ns<os+w<ns+w)
1400 //if(ns<os+w && os+w<ns+w)
1401 //if(ns<old_end && os<ns)
1402 if(ltt_time_compare(*ns, old_end) == -1
1403 && ltt_time_compare(*os, *ns) == -1)
1404 {
1405 g_info("scrolling near right");
1406 /* Scroll right, keep right part of the screen */
1407 guint x = 0;
51705146 1408 guint width = control_flow_data->drawing->width;
a56a1ba4 1409 convert_time_to_pixels(
a18124ff 1410 *old_time_window,
a56a1ba4 1411 *ns,
1412 width,
1413 &x);
1414
1415 /* Copy old data to new location */
1c736ed5 1416 copy_pixmap_region(process_list,
1417 NULL,
1418 control_flow_data->drawing->drawing_area->style->black_gc,
1419 NULL,
1420 x, 0,
1421 0, 0,
1422 control_flow_data->drawing->width-x+SAFETY, -1);
1423
6395d57c 1424 if(drawing->damage_begin == drawing->damage_end)
1425 drawing->damage_begin = control_flow_data->drawing->width-x;
1426 else
1427 drawing->damage_begin = 0;
1428
1429 drawing->damage_end = control_flow_data->drawing->width;
1430
a56a1ba4 1431 /* Clear the data request background, but not SAFETY */
1c736ed5 1432 rectangle_pixmap(process_list,
cfe526b1 1433 control_flow_data->drawing->drawing_area->style->black_gc,
a56a1ba4 1434 TRUE,
6395d57c 1435 drawing->damage_begin+SAFETY, 0,
1436 drawing->damage_end - drawing->damage_begin, // do not overlap
1c736ed5 1437 -1);
7abb23ad 1438 gtk_widget_queue_draw(drawing->drawing_area);
1439 //gtk_widget_queue_draw_area (drawing->drawing_area,
1440 // 0,0,
1441 // control_flow_data->drawing->width,
1442 // control_flow_data->drawing->height);
a43d67ba 1443
a56a1ba4 1444 /* Get new data for the rest. */
501d5405 1445 drawing_data_request(control_flow_data->drawing,
6395d57c 1446 drawing->damage_begin, 0,
1447 drawing->damage_end - drawing->damage_begin,
501d5405 1448 control_flow_data->drawing->height);
a56a1ba4 1449 } else {
1450 //if(ns<os<ns+w)
1451 //if(ns<os && os<ns+w)
1452 //if(ns<os && os<new_end)
1453 if(ltt_time_compare(*ns,*os) == -1
1454 && ltt_time_compare(*os,new_end) == -1)
1455 {
1456 g_info("scrolling near left");
1457 /* Scroll left, keep left part of the screen */
1458 guint x = 0;
51705146 1459 guint width = control_flow_data->drawing->width;
a56a1ba4 1460 convert_time_to_pixels(
a18124ff 1461 *new_time_window,
a56a1ba4 1462 *os,
1463 width,
1464 &x);
6395d57c 1465
a56a1ba4 1466 /* Copy old data to new location */
1c736ed5 1467 copy_pixmap_region (process_list,
1468 NULL,
cfe526b1 1469 control_flow_data->drawing->drawing_area->style->black_gc,
1c736ed5 1470 NULL,
a56a1ba4 1471 0, 0,
1472 x, 0,
1473 -1, -1);
1474
6395d57c 1475 if(drawing->damage_begin == drawing->damage_end)
1476 drawing->damage_end = x;
1477 else
1478 drawing->damage_end =
51705146 1479 control_flow_data->drawing->width;
6395d57c 1480
1481 drawing->damage_begin = 0;
1482
1c736ed5 1483 rectangle_pixmap (process_list,
cfe526b1 1484 control_flow_data->drawing->drawing_area->style->black_gc,
a56a1ba4 1485 TRUE,
6395d57c 1486 drawing->damage_begin, 0,
1487 drawing->damage_end - drawing->damage_begin, // do not overlap
1c736ed5 1488 -1);
a43d67ba 1489
7abb23ad 1490 gtk_widget_queue_draw(drawing->drawing_area);
1491 //gtk_widget_queue_draw_area (drawing->drawing_area,
1492 // 0,0,
1493 // control_flow_data->drawing->width,
1494 // control_flow_data->drawing->height);
a43d67ba 1495
6395d57c 1496
a56a1ba4 1497 /* Get new data for the rest. */
501d5405 1498 drawing_data_request(control_flow_data->drawing,
6395d57c 1499 drawing->damage_begin, 0,
1500 drawing->damage_end - drawing->damage_begin,
501d5405 1501 control_flow_data->drawing->height);
a56a1ba4 1502
a56a1ba4 1503 } else {
a43d67ba 1504 if(ltt_time_compare(*ns,*os) == 0)
1505 {
1506 g_info("not scrolling");
1507 } else {
1508 g_info("scrolling far");
1509 /* Cannot reuse any part of the screen : far jump */
1510
1511
1c736ed5 1512 rectangle_pixmap (process_list,
a43d67ba 1513 control_flow_data->drawing->drawing_area->style->black_gc,
1514 TRUE,
a56a1ba4 1515 0, 0,
a43d67ba 1516 control_flow_data->drawing->width+SAFETY, // do not overlap
1c736ed5 1517 -1);
a43d67ba 1518
7abb23ad 1519 //gtk_widget_queue_draw_area (drawing->drawing_area,
1520 // 0,0,
1521 // control_flow_data->drawing->width,
1522 // control_flow_data->drawing->height);
1523 gtk_widget_queue_draw(drawing->drawing_area);
a43d67ba 1524
6395d57c 1525 drawing->damage_begin = 0;
1526 drawing->damage_end = control_flow_data->drawing->width;
1527
a43d67ba 1528 drawing_data_request(control_flow_data->drawing,
a43d67ba 1529 0, 0,
1530 control_flow_data->drawing->width,
1531 control_flow_data->drawing->height);
1532
1533 }
a56a1ba4 1534 }
1535 }
1536 } else {
1537 /* Different scale (zoom) */
1538 g_info("zoom");
1539
1c736ed5 1540 rectangle_pixmap (process_list,
cfe526b1 1541 control_flow_data->drawing->drawing_area->style->black_gc,
a56a1ba4 1542 TRUE,
1543 0, 0,
501d5405 1544 control_flow_data->drawing->width+SAFETY, // do not overlap
1c736ed5 1545 -1);
a56a1ba4 1546
7abb23ad 1547 //gtk_widget_queue_draw_area (drawing->drawing_area,
1548 // 0,0,
1549 // control_flow_data->drawing->width,
1550 // control_flow_data->drawing->height);
1551 gtk_widget_queue_draw(drawing->drawing_area);
a56a1ba4 1552
6395d57c 1553 drawing->damage_begin = 0;
1554 drawing->damage_end = control_flow_data->drawing->width;
1555
501d5405 1556 drawing_data_request(control_flow_data->drawing,
a56a1ba4 1557 0, 0,
501d5405 1558 control_flow_data->drawing->width,
1559 control_flow_data->drawing->height);
a56a1ba4 1560 }
1561
15f77e3b 1562 /* Update directly when scrolling */
1563 gdk_window_process_updates(control_flow_data->drawing->drawing_area->window,
1564 TRUE);
3cb8b205 1565
a56a1ba4 1566 return 0;
f7afe191 1567}
1568
6395d57c 1569gint traceset_notify(void *hook_data, void *call_data)
1570{
1571 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
1572 Drawing_t *drawing = control_flow_data->drawing;
6395d57c 1573
6cec4cd2 1574 if(unlikely(drawing->gc == NULL)) {
1575 return FALSE;
1576 }
1577 if(drawing->dotted_gc == NULL) {
1578 return FALSE;
1579 }
6395d57c 1580
b9a010a2 1581 drawing_clear(control_flow_data->drawing);
1582 processlist_clear(control_flow_data->process_list);
07390ec1 1583 gtk_widget_set_size_request(
1584 control_flow_data->drawing->drawing_area,
1585 -1, processlist_get_height(control_flow_data->process_list));
d9267eec 1586 redraw_notify(control_flow_data, NULL);
6395d57c 1587
d9267eec 1588 request_background_data(control_flow_data);
6395d57c 1589
1590 return FALSE;
1591}
1592
ca0f8a8e 1593gint redraw_notify(void *hook_data, void *call_data)
1594{
1595 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
1596 Drawing_t *drawing = control_flow_data->drawing;
1597 GtkWidget *widget = drawing->drawing_area;
1598
1599 drawing->damage_begin = 0;
51705146 1600 drawing->damage_end = drawing->width;
ca0f8a8e 1601
49217bd4 1602 /* fun feature, to be separated someday... */
1603 drawing_clear(control_flow_data->drawing);
1604 processlist_clear(control_flow_data->process_list);
07390ec1 1605 gtk_widget_set_size_request(
1606 control_flow_data->drawing->drawing_area,
1607 -1, processlist_get_height(control_flow_data->process_list));
1c736ed5 1608 // Clear the images
1609 rectangle_pixmap (control_flow_data->process_list,
ca0f8a8e 1610 widget->style->black_gc,
1611 TRUE,
1612 0, 0,
f3b7430d 1613 drawing->alloc_width,
1c736ed5 1614 -1);
ca0f8a8e 1615
f3b7430d 1616 gtk_widget_queue_draw(drawing->drawing_area);
4a24fa1f 1617
ca0f8a8e 1618 if(drawing->damage_begin < drawing->damage_end)
1619 {
1620 drawing_data_request(drawing,
ca0f8a8e 1621 drawing->damage_begin,
1622 0,
1623 drawing->damage_end-drawing->damage_begin,
51705146 1624 drawing->height);
ca0f8a8e 1625 }
1626
7abb23ad 1627 //gtk_widget_queue_draw_area(drawing->drawing_area,
1628 // 0,0,
1629 // drawing->width,
1630 // drawing->height);
ca0f8a8e 1631 return FALSE;
1632
1633}
1634
1635
1636gint continue_notify(void *hook_data, void *call_data)
a43d67ba 1637{
1638 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
ca0f8a8e 1639 Drawing_t *drawing = control_flow_data->drawing;
a43d67ba 1640
6395d57c 1641 //g_assert(widget->allocation.width == drawing->damage_end);
ca0f8a8e 1642
1643 if(drawing->damage_begin < drawing->damage_end)
1644 {
1645 drawing_data_request(drawing,
ca0f8a8e 1646 drawing->damage_begin,
1647 0,
1648 drawing->damage_end-drawing->damage_begin,
51705146 1649 drawing->height);
ca0f8a8e 1650 }
1651
1652 return FALSE;
1653}
1654
1655
1b238973 1656gint update_current_time_hook(void *hook_data, void *call_data)
f7afe191 1657{
88bf15f0 1658
14963be0 1659 ControlFlowData *control_flow_data = (ControlFlowData*)hook_data;
a56a1ba4 1660
224446ce 1661 LttTime current_time = *((LttTime*)call_data);
88bf15f0 1662
ca0f8a8e 1663 TimeWindow time_window =
1664 lttvwindow_get_time_window(control_flow_data->tab);
a56a1ba4 1665
ca0f8a8e 1666 LttTime time_begin = time_window.start_time;
1667 LttTime width = time_window.time_width;
90ef7e4a 1668 LttTime half_width;
1669 {
1670 guint64 time_ll = ltt_time_to_uint64(width);
1671 time_ll = time_ll >> 1; /* divide by two */
1672 half_width = ltt_time_from_uint64(time_ll);
1673 }
a56a1ba4 1674 LttTime time_end = ltt_time_add(time_begin, width);
1675
88bf15f0 1676 LttvTraceset * ts = lttvwindow_get_traceset(control_flow_data->tab);
a56a1ba4 1677
88bf15f0
FD
1678 TimeInterval time_span = lttv_traceset_get_time_span_real(ts);
1679 LttTime trace_start = time_span.start_time;
1680 LttTime trace_end = time_span.end_time;
a56a1ba4 1681
2eef04b5 1682 g_info("New current time HOOK : %lu, %lu", current_time.tv_sec,
224446ce 1683 current_time.tv_nsec);
a56a1ba4 1684
1685
1686
1687 /* If current time is inside time interval, just move the highlight
1688 * bar */
1689
1690 /* Else, we have to change the time interval. We have to tell it
1691 * to the main window. */
1692 /* The time interval change will take care of placing the current
1693 * time at the center of the visible area, or nearest possible if we are
1694 * at one end of the trace. */
1695
1696
dbc0ef8a 1697 if(ltt_time_compare(current_time, time_begin) < 0)
a56a1ba4 1698 {
224446ce 1699 TimeWindow new_time_window;
1700
1701 if(ltt_time_compare(current_time,
dbc0ef8a 1702 ltt_time_add(trace_start,half_width)) < 0)
a56a1ba4 1703 time_begin = trace_start;
1704 else
224446ce 1705 time_begin = ltt_time_sub(current_time,half_width);
a56a1ba4 1706
224446ce 1707 new_time_window.start_time = time_begin;
1708 new_time_window.time_width = width;
a18124ff 1709 new_time_window.time_width_double = ltt_time_to_double(width);
6f26fc38 1710 new_time_window.end_time = ltt_time_add(time_begin, width);
a56a1ba4 1711
e800cf84 1712 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
a56a1ba4 1713 }
dbc0ef8a 1714 else if(ltt_time_compare(current_time, time_end) > 0)
a56a1ba4 1715 {
224446ce 1716 TimeWindow new_time_window;
1717
dbc0ef8a 1718 if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) > 0)
a56a1ba4 1719 time_begin = ltt_time_sub(trace_end,width);
1720 else
224446ce 1721 time_begin = ltt_time_sub(current_time,half_width);
a56a1ba4 1722
224446ce 1723 new_time_window.start_time = time_begin;
1724 new_time_window.time_width = width;
a18124ff 1725 new_time_window.time_width_double = ltt_time_to_double(width);
6f26fc38 1726 new_time_window.end_time = ltt_time_add(time_begin, width);
a56a1ba4 1727
e800cf84 1728 lttvwindow_report_time_window(control_flow_data->tab, new_time_window);
a56a1ba4 1729
1730 }
7abb23ad 1731 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
a56a1ba4 1732
15f77e3b 1733 /* Update directly when scrolling */
1734 gdk_window_process_updates(control_flow_data->drawing->drawing_area->window,
1735 TRUE);
1736
a56a1ba4 1737 return 0;
88bf15f0 1738
f7afe191 1739}
1740
8b90e648 1741typedef struct _ClosureData {
ca0f8a8e 1742 EventsRequest *events_request;
b9a010a2 1743 LttTime end_time;
bc8d270b 1744 guint x_end;
8b90e648 1745} ClosureData;
a56a1ba4 1746
8b90e648 1747
e800cf84 1748void draw_closure(gpointer key, gpointer value, gpointer user_data)
1749{
88bf15f0 1750
a56a1ba4 1751 ProcessInfo *process_info = (ProcessInfo*)key;
1752 HashedProcessData *hashed_process_data = (HashedProcessData*)value;
1753 ClosureData *closure_data = (ClosureData*)user_data;
88bf15f0 1754
e800cf84 1755 EventsRequest *events_request = closure_data->events_request;
1756 ControlFlowData *control_flow_data = events_request->viewer_data;
88bf15f0 1757 LttvTraceset *ts = lttvwindow_get_traceset(control_flow_data->tab);
a56a1ba4 1758
a56a1ba4 1759
e800cf84 1760 LttTime evtime = closure_data->end_time;
d0cd7f09 1761
e3162168 1762 gboolean dodraw = TRUE;
1763
e800cf84 1764 {
1765 /* For the process */
1766 /* First, check if the current process is in the state computation
1767 * process list. If it is there, that means we must add it right now and
1768 * draw items from the beginning of the read for it. If it is not
1769 * present, it's a new process and it was not present : it will
1770 * be added after the state update. */
31b6868d 1771#ifdef EXTRA_CHECK
e800cf84 1772 g_assert(lttv_traceset_number(tsc->ts) > 0);
31b6868d 1773#endif //EXTRA_CHECK
8284135e
YB
1774
1775 LttvTrace *trace = lttv_traceset_get(ts, process_info->trace_num);
88bf15f0 1776 LttvTraceState *trace_state = trace->state;
2c82c4dc 1777
348c6ba8 1778#if 0
2c82c4dc 1779 //FIXME : optimize data structures.
1780 LttvTracefileState *tfs;
1781 LttvTracefileContext *tfc;
1782 guint i;
1783 for(i=0;i<tc->tracefiles->len;i++) {
1784 tfc = g_array_index(tc->tracefiles, LttvTracefileContext*, i);
1785 if(ltt_tracefile_name(tfc->tf) == LTT_NAME_CPU
ae3d0f50 1786 && tfs->cpu == process_info->cpu)
2c82c4dc 1787 break;
1788
1789 }
1790 g_assert(i<tc->tracefiles->len);
1791 tfs = LTTV_TRACEFILE_STATE(tfc);
348c6ba8 1792#endif //0
88bf15f0 1793 // LttvTracefileState *tfs =ts
2c82c4dc 1794 // (LttvTracefileState*)tsc->traces[process_info->trace_num]->
1795 // tracefiles[process_info->cpu];
2da61677 1796
e800cf84 1797 LttvProcessState *process;
88bf15f0 1798 process = lttv_state_find_process(trace_state, process_info->cpu,
e025a729 1799 process_info->pid);
a56a1ba4 1800
1d1df11d 1801 if(unlikely(process != NULL)) {
88bf15f0 1802#ifdef BABEL_CLEANUP
b6ef18af 1803 LttvFilter *filter = control_flow_data->filter;
1804 if(filter != NULL && filter->head != NULL)
1805 if(!lttv_filter_tree_parse(filter->head,NULL,NULL,
1806 tc->t,NULL,process,tc))
e3162168 1807 dodraw = FALSE;
88bf15f0 1808#endif //babel_cleanup
e800cf84 1809 /* Only draw for processes that are currently in the trace states */
ad2e83ba 1810
1d1df11d 1811#ifdef EXTRA_CHECK
e800cf84 1812 /* Should be alike when background info is ready */
1813 if(control_flow_data->background_info_waiting==0)
1814 g_assert(ltt_time_compare(process->creation_time,
1815 process_info->birth) == 0);
1d1df11d 1816#endif //EXTRA_CHECK
e800cf84 1817
1818 /* Now, the process is in the state hash and our own process hash.
1819 * We definitely can draw the items related to the ending state.
1820 */
1821
1d1df11d 1822 if(unlikely(ltt_time_compare(hashed_process_data->next_good_time,
1823 evtime) <= 0))
e800cf84 1824 {
fd22065b 1825 TimeWindow time_window =
1826 lttvwindow_get_time_window(control_flow_data->tab);
1827
1828#ifdef EXTRA_CHECK
1829 if(ltt_time_compare(evtime, time_window.start_time) == -1
1830 || ltt_time_compare(evtime, time_window.end_time) == 1)
1831 return;
1832#endif //EXTRA_CHECK
d6fef890 1833 Drawing_t *drawing = control_flow_data->drawing;
96947fcf 1834 guint width = drawing->width;
a56a1ba4 1835
bc8d270b 1836 guint x = closure_data->x_end;
8b90e648 1837
4b7dc462 1838 DrawContext draw_context;
1839
98dfb302
YB
1840 init_drawing_context(&draw_context,
1841 hashed_process_data,
1842 drawing,
1843 x);
1844
9a1ec01b 1845#if 0
4b7dc462 1846 /* Jump over draw if we are at the same x position */
1847 if(x == hashed_process_data->x.over)
e800cf84 1848 {
4b7dc462 1849 /* jump */
1850 } else {
23093869 1851 draw_context.drawinfo.start.x = hashed_process_data->x.over;
1852 /* Draw the line */
1853 PropertiesLine prop_line = prepare_execmode_line(process);
1854 draw_line((void*)&prop_line, (void*)&draw_context);
1855
4b7dc462 1856 hashed_process_data->x.over = x;
23093869 1857 }
9a1ec01b 1858#endif //0
4b7dc462 1859
1d1df11d 1860 if(unlikely(x == hashed_process_data->x.middle &&
1861 hashed_process_data->x.middle_used)) {
b2743953 1862#if 0 /* do not mark closure : not missing information */
e72908ed 1863 if(hashed_process_data->x.middle_marked == FALSE) {
1864 /* Draw collision indicator */
1865 gdk_gc_set_foreground(drawing->gc, &drawing_colors[COL_WHITE]);
1866 gdk_draw_point(drawing->pixmap,
1867 drawing->gc,
1868 x,
2c6618bc 1869 y+(height/2)-3);
de4ea1ad 1870 hashed_process_data->x.middle_marked = TRUE;
e72908ed 1871 }
b2743953 1872#endif //0
4b7dc462 1873 /* Jump */
1874 } else {
23093869 1875 draw_context.drawinfo.start.x = hashed_process_data->x.middle;
e800cf84 1876 /* Draw the line */
c4a72569 1877 if(dodraw) {
1878 PropertiesLine prop_line = prepare_s_e_line(process);
1879 draw_line((void*)&prop_line, (void*)&draw_context);
1880 }
e800cf84 1881
4b7dc462 1882 /* become the last x position */
1d1df11d 1883 if(likely(x != hashed_process_data->x.middle)) {
e72908ed 1884 hashed_process_data->x.middle = x;
1885 /* but don't use the pixel */
1886 hashed_process_data->x.middle_used = FALSE;
b2743953 1887
1888 /* Calculate the next good time */
1889 convert_pixels_to_time(width, x+1, time_window,
1890 &hashed_process_data->next_good_time);
e72908ed 1891 }
e800cf84 1892 }
e800cf84 1893 }
1894 }
1895 }
1896 return;
8b90e648 1897}
1898
b9a010a2 1899int before_chunk(void *hook_data, void *call_data)
1900{
88bf15f0 1901
b9a010a2 1902 EventsRequest *events_request = (EventsRequest*)hook_data;
88bf15f0 1903 LttvTraceset *ts = (LttvTraceset*)call_data;
cd3892fe 1904#if 0
7c0125e0 1905 /* Desactivate sort */
1906 gtk_tree_sortable_set_sort_column_id(
1907 GTK_TREE_SORTABLE(cfd->process_list->list_store),
1908 TRACE_COLUMN,
1909 GTK_SORT_ASCENDING);
cd3892fe 1910#endif //0
88bf15f0 1911 drawing_chunk_begin(events_request, ts);
b9a010a2 1912
1913 return 0;
1914}
1915
1916int before_request(void *hook_data, void *call_data)
ca0f8a8e 1917{
88bf15f0 1918
ca0f8a8e 1919 EventsRequest *events_request = (EventsRequest*)hook_data;
7c0125e0 1920
88bf15f0 1921 drawing_data_request_begin(events_request);
ca0f8a8e 1922
1923 return 0;
88bf15f0 1924
ca0f8a8e 1925}
1926
1927
98dfb302
YB
1928void draw_closing_lines(ControlFlowData *control_flow_data,
1929 EventsRequest* events_request)
8b90e648 1930{
98dfb302 1931 ProcessList *process_list = control_flow_data->process_list;
88bf15f0 1932
b9a010a2 1933
1934 ClosureData closure_data;
98dfb302
YB
1935 closure_data.events_request = events_request;
1936 closure_data.end_time = events_request->end_time;
b9a010a2 1937
bc8d270b 1938 TimeWindow time_window =
1939 lttvwindow_get_time_window(control_flow_data->tab);
1940 guint width = control_flow_data->drawing->width;
1941 convert_time_to_pixels(
1942 time_window,
98dfb302 1943 events_request->end_time,
bc8d270b 1944 width,
1945 &closure_data.x_end);
1946
1947
b9a010a2 1948 /* Draw last items */
1949 g_hash_table_foreach(process_list->process_hash, draw_closure,
1950 (void*)&closure_data);
7c0125e0 1951
b9a010a2 1952
1953 /* Request expose */
98dfb302
YB
1954 drawing_request_expose(events_request, events_request->end_time);
1955}
1956
1957/*
1958 * after request is necessary in addition of after chunk in order to draw
1959 * lines until the end of the screen. after chunk just draws lines until
1960 * the last event.
1961 *
1962 * for each process
1963 * draw closing line
1964 * expose
1965 */
1966int after_request(void *hook_data, void *call_data)
1967{
1968
1969 EventsRequest *events_request = (EventsRequest*)hook_data;
1970 ControlFlowData *control_flow_data = events_request->viewer_data;
1971
1972 draw_closing_lines(control_flow_data, events_request);
1973
b9a010a2 1974 return 0;
1975}
1976
1977/*
1978 * for each process
1979 * draw closing line
e800cf84 1980 * expose
b9a010a2 1981 */
1982int after_chunk(void *hook_data, void *call_data)
1983{
88bf15f0 1984
b9a010a2 1985 EventsRequest *events_request = (EventsRequest*)hook_data;
1986 ControlFlowData *control_flow_data = events_request->viewer_data;
88bf15f0
FD
1987 LttvTraceset *ts = (LttvTraceset*)call_data;
1988
b9a010a2 1989
5c230fc4 1990 ProcessList *process_list = control_flow_data->process_list;
0f090e21 1991 guint i;
88bf15f0 1992 guint nb_trace = lttv_traceset_number(ts);
b9a010a2 1993
0f090e21 1994 /* Only execute when called for the first trace's events request */
43ed82b5 1995 if(!process_list->current_hash_data)
1996 return 0;
0f090e21 1997
1998 for(i = 0 ; i < nb_trace ; i++) {
1999 g_free(process_list->current_hash_data[i]);
2000 }
40debf7b 2001 g_free(process_list->current_hash_data);
2002 process_list->current_hash_data = NULL;
0f090e21 2003
98dfb302 2004 draw_closing_lines(control_flow_data, events_request);
ca0f8a8e 2005
2006 return 0;
8b90e648 2007}
2008
b70ceef8 2009/* after_statedump_end
2010 *
2011 * @param hook_data ControlFlowData structure of the viewer.
2012 * @param call_data Event context.
2013 *
2014 * This function adds items to be drawn in a queue for each process.
2015 *
2016 */
2017int before_statedump_end(void *hook_data, void *call_data)
2018{
7b20eed1 2019 LttvEvent *event;
b70ceef8 2020
7b20eed1
YB
2021 event = (LttvEvent *) call_data;
2022
2023 if (strcmp(lttv_traceset_get_name_from_event(event),"lttng_statedump_end") != 0)
2024 return FALSE;
b70ceef8 2025
7b20eed1 2026 ControlFlowData *control_flow_data = (ControlFlowData*) hook_data;
b70ceef8 2027
b70ceef8 2028
7b20eed1
YB
2029 LttvTraceState *ts = event->state;
2030
2031
2032 ProcessList *process_list = control_flow_data->process_list;
2033
2034#ifdef BABEL_CLEANUP
b70ceef8 2035 LttvFilter *filter = control_flow_data->filter;
2036 if(filter != NULL && filter->head != NULL)
2037 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
b6ef18af 2038 tfc->t_context->t,tfc,NULL,NULL))
b70ceef8 2039 return FALSE;
7b20eed1 2040#endif
b70ceef8 2041
7b20eed1 2042 LttTime evtime = lttv_event_get_timestamp(event);
3dc97878 2043
b70ceef8 2044 ClosureData closure_data;
3dc97878
YB
2045 //TODO ybrosseau 2013-03-27: Fake and event_request.
2046 // We need to change the API of drawing_request_expose to ask
2047 // For and control flow data only.
2048 EventsRequest events_request;
2049 events_request.viewer_data = control_flow_data;
2050 closure_data.events_request = &events_request;
b70ceef8 2051 closure_data.end_time = evtime;
2052
2053 TimeWindow time_window =
2054 lttvwindow_get_time_window(control_flow_data->tab);
2055 guint width = control_flow_data->drawing->width;
2056 convert_time_to_pixels(
2057 time_window,
2058 evtime,
2059 width,
2060 &closure_data.x_end);
2061
2062 /* Draw last items */
2063 g_hash_table_foreach(process_list->process_hash, draw_closure,
2064 (void*)&closure_data);
7b20eed1 2065
b70ceef8 2066#if 0
2067 /* Reactivate sort */
2068 gtk_tree_sortable_set_sort_column_id(
2069 GTK_TREE_SORTABLE(control_flow_data->process_list->list_store),
2070 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
2071 GTK_SORT_ASCENDING);
2072
2073 update_index_to_pixmap(control_flow_data->process_list);
2074 /* Request a full expose : drawing scrambled */
2075 gtk_widget_queue_draw(control_flow_data->drawing->drawing_area);
2076#endif //0
2077 /* Request expose (updates damages zone also) */
3dc97878
YB
2078 drawing_request_expose(&events_request, evtime);
2079
10599fb9 2080 return 0;
b70ceef8 2081}
This page took 0.213231 seconds and 4 git commands to generate.