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