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