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