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