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