convert from svn repository: remove tags directory
[lttv.git] / trunk / lttng-xenomai / LinuxTraceToolkitViewer-0.8.61-xenoltt / lttv / lttv / xenoltt_sim.c.bkp
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
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 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <stdio.h>
24 #include <lttv/module.h>
25 #include <lttv/xenoltt_sim.h>
26 #include <lttv/stats.h>
27 #include <lttv/lttv.h>
28 #include <lttv/attribute.h>
29 #include <ltt/facility.h>
30 #include <ltt/trace.h>
31 #include <ltt/event.h>
32 #include <ltt/type.h>
33
34
35 /****************************************************************************************************************************/
36 gboolean save_event(void *hook_data, void *call_data);
37 /****************************************************************************************************************************/
38
39 gboolean sim_every_event(void *hook_data, void *call_data)
40 {
41 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
42
43 LttEvent *e = ltt_tracefile_get_event(tfcs->parent.parent.tf);
44
45 LttvAttributeValue v;
46
47 /* The current branch corresponds to the tracefile/process/interrupt state.
48 Statistics are added within it, to count the number of events of this
49 type occuring in this context. A quark has been pre-allocated for each
50 event type and is used as name. */
51
52 lttv_attribute_find(tfcs->current_event_types_tree,
53 ltt_eventtype_name(ltt_event_eventtype(e)),
54 LTTV_UINT, &v);
55 (*(v.v_uint))++;
56 return FALSE;
57 }
58
59 // Hook wrapper. call_data is a traceset context.
60 gboolean lttv_xenoltt_sim_hook_add_event_hooks(void *hook_data, void *call_data)
61 {
62 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
63
64 thread_event_list = g_array_new(FALSE, FALSE, sizeof(ThreadEventData*));
65 running_thread = g_array_new(FALSE, FALSE, sizeof(RunningThread*));
66
67 lttv_xenoltt_sim_add_event_hooks(tss);
68
69 return 0;
70 }
71
72 void lttv_xenoltt_sim_add_event_hooks(LttvTracesetStats *self)
73 {
74 LttvTraceset *traceset = self->parent.parent.ts;
75
76 guint i, j, k, l, nb_trace, nb_tracefile;
77
78 LttvTraceStats *ts;
79
80 LttvTracefileStats *tfs;
81
82 GArray *hooks, *before_hooks;
83
84 LttvTraceHook *hook;
85
86 LttvTraceHookByFacility *thf;
87
88 LttvAttributeValue val;
89
90 gint ret;
91 gint hn;
92
93 nb_trace = lttv_traceset_number(traceset);
94 for(i = 0 ; i < nb_trace ; i++) {
95 ts = (LttvTraceStats *)self->parent.parent.traces[i];
96
97 /* Find the eventtype id for the following events and register the
98 associated by id hooks. */
99
100 hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 16);
101 g_array_set_size(hooks, 16);
102 hn=0;
103 /*
104 LTT_EVENT_XENOLTT_THREAD_INIT,
105 LTT_EVENT_XENOLTT_THREAD_SET_PERIOD,
106 LTT_EVENT_XENOLTT_THREAD_WAIT_PERIOD,
107 LTT_EVENT_XENOLTT_THREAD_MISSED_PERIOD,
108 LTT_EVENT_XENOLTT_THREAD_SUSPEND,
109 LTT_EVENT_XENOLTT_THREAD_START,
110 LTT_EVENT_XENOLTT_THREAD_RESUME,
111 LTT_EVENT_XENOLTT_THREAD_DELETE,
112 LTT_EVENT_XENOLTT_THREAD_UNBLOCK,
113 LTT_EVENT_XENOLTT_THREAD_RENICE,
114 LTT_EVENT_XENOLTT_TIMER_TICK,
115 LTT_EVENT_XENOLTT_SYNCH_SET_OWNER,
116 LTT_EVENT_XENOLTT_SYNCH_UNLOCK,
117 LTT_EVENT_XENOLTT_SYNCH_WAKEUP1,
118 LTT_EVENT_XENOLTT_SYNCH_WAKEUPX,
119 LTT_EVENT_XENOLTT_SYNCH_SLEEP_ON,
120 LTT_EVENT_XENOLTT_SYNCH_FLUSH,
121 LTT_EVENT_XENOLTT_SYNCH_FORGET,
122 LTT_EVENT_XENOLTT_THREAD_SWITCH;
123 */
124
125 ret = lttv_trace_find_hook(ts->parent.parent.t,
126 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_INIT,
127 LTT_FIELD_XENOLTT_ADDRESS, 0, 0,
128 save_event, NULL,
129 &g_array_index(hooks, LttvTraceHook, hn++));
130 if(ret) hn--;
131
132 ret = lttv_trace_find_hook(ts->parent.parent.t,
133 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_SET_PERIOD,
134 LTT_FIELD_XENOLTT_ADDRESS, 0, 0,
135 save_event, NULL,
136 &g_array_index(hooks, LttvTraceHook, hn++));
137 if(ret) hn--;
138
139 ret = lttv_trace_find_hook(ts->parent.parent.t,
140 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_WAIT_PERIOD,
141 LTT_FIELD_XENOLTT_ADDRESS, 0, 0,
142 save_event, NULL,
143 &g_array_index(hooks, LttvTraceHook, hn++));
144 if(ret) hn--;
145
146 ret = lttv_trace_find_hook(ts->parent.parent.t,
147 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_MISSED_PERIOD,
148 LTT_FIELD_XENOLTT_ADDRESS, 0, 0,
149 save_event, NULL,
150 &g_array_index(hooks, LttvTraceHook, hn++));
151 if(ret) hn--;
152
153 ret = lttv_trace_find_hook(ts->parent.parent.t,
154 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_SUSPEND,
155 LTT_FIELD_XENOLTT_ADDRESS, 0, 0,
156 save_event, NULL,
157 &g_array_index(hooks, LttvTraceHook, hn++));
158 if(ret) hn--;
159
160 ret = lttv_trace_find_hook(ts->parent.parent.t,
161 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_START,
162 LTT_FIELD_XENOLTT_ADDRESS, 0, 0,
163 save_event, NULL,
164 &g_array_index(hooks, LttvTraceHook, hn++));
165 if(ret) hn--;
166
167 ret = lttv_trace_find_hook(ts->parent.parent.t,
168 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_RESUME,
169 LTT_FIELD_XENOLTT_ADDRESS, 0, 0,
170 save_event, NULL,
171 &g_array_index(hooks, LttvTraceHook, hn++));
172 if(ret) hn--;
173
174 ret = lttv_trace_find_hook(ts->parent.parent.t,
175 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_DELETE,
176 LTT_FIELD_XENOLTT_ADDRESS, 0, 0,
177 save_event, NULL,
178 &g_array_index(hooks, LttvTraceHook, hn++));
179 if(ret) hn--;
180
181 ret = lttv_trace_find_hook(ts->parent.parent.t,
182 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_SWITCH,
183 LTT_FIELD_XENOLTT_ADDRESS, 0, 0,
184 save_event, NULL,
185 &g_array_index(hooks, LttvTraceHook, hn++));
186 if(ret) hn--;
187
188 ret = lttv_trace_find_hook(ts->parent.parent.t,
189 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_THREAD_SWITCH,
190 LTT_FIELD_XENOLTT_ADDRESS_OUT, 0, 0,
191 save_event, NULL,
192 &g_array_index(hooks, LttvTraceHook, hn++));
193 if(ret) hn--;
194
195 ret = lttv_trace_find_hook(ts->parent.parent.t,
196 LTT_FACILITY_XENOLTT, LTT_EVENT_XENOLTT_TIMER_TICK,
197 LTT_FIELD_XENOLTT_ADDRESS, 0, 0,
198 save_event, NULL,
199 &g_array_index(hooks, LttvTraceHook, hn++));
200 if(ret) hn--;
201
202 g_array_set_size(hooks, hn);
203
204 before_hooks = hooks;
205
206 /* Add these hooks to each event_by_id hooks list */
207
208 nb_tracefile = ts->parent.parent.tracefiles->len;
209
210 for(j = 0 ; j < nb_tracefile ; j++) {
211 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
212 LttvTracefileContext*, j));
213 lttv_hooks_add(tfs->parent.parent.event, sim_every_event, NULL,
214 LTTV_PRIO_DEFAULT);
215
216 for(k = 0 ; k < before_hooks->len ; k++) {
217 hook = &g_array_index(before_hooks, LttvTraceHook, k);
218 for(l = 0; l<hook->fac_list->len;l++) {
219 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
220 lttv_hooks_add(
221 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
222 thf->h,
223 thf,
224 LTTV_PRIO_DEFAULT);
225 }
226 }
227
228 }
229 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
230 LTTV_POINTER, &val);
231 *(val.v_pointer) = before_hooks;
232 }
233 }
234
235 // Hook wrapper. call_data is a traceset context.
236 gboolean lttv_xenoltt_sim_hook_remove_event_hooks(void *hook_data, void *call_data)
237 {
238 LttvTracesetStats *tss = (LttvTracesetStats*)call_data;
239
240 lttv_xenoltt_sim_remove_event_hooks(tss);
241
242 return 0;
243 }
244
245 void lttv_xenoltt_sim_remove_event_hooks(LttvTracesetStats *self)
246 {
247 LttvTraceset *traceset = self->parent.parent.ts;
248
249 guint i, j, k, l, nb_trace, nb_tracefile;
250
251 LttvTraceStats *ts;
252
253 LttvTracefileStats *tfs;
254
255 GArray *before_hooks;
256
257 LttvTraceHook *hook;
258
259 LttvTraceHookByFacility *thf;
260
261 LttvAttributeValue val;
262
263 nb_trace = lttv_traceset_number(traceset);
264 for(i = 0 ; i < nb_trace ; i++) {
265 ts = (LttvTraceStats*)self->parent.parent.traces[i];
266 lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
267 LTTV_POINTER, &val);
268 before_hooks = *(val.v_pointer);
269
270 /* Remove these hooks from each event_by_id hooks list */
271
272 nb_tracefile = ts->parent.parent.tracefiles->len;
273
274 for(j = 0 ; j < nb_tracefile ; j++) {
275 tfs = LTTV_TRACEFILE_STATS(g_array_index(ts->parent.parent.tracefiles,
276 LttvTracefileContext*, j));
277 lttv_hooks_remove_data(tfs->parent.parent.event, sim_every_event,
278 NULL);
279
280 for(k = 0 ; k < before_hooks->len ; k++) {
281 hook = &g_array_index(before_hooks, LttvTraceHook, k);
282 for(l = 0 ; l < hook->fac_list->len ; l++) {
283 thf = g_array_index(hook->fac_list, LttvTraceHookByFacility*, l);
284 lttv_hooks_remove_data(
285 lttv_hooks_by_id_find(tfs->parent.parent.event_by_id, thf->id),
286 thf->h,
287 thf);
288 }
289 }
290 }
291 g_debug("lttv_stats_remove_event_hooks()");
292 g_array_free(before_hooks, TRUE);
293 }
294 }
295
296
297
298 /****************************************************************************************************************************/
299
300
301
302 /*
303 This function will look into the thread list to find the corresponding thread and returns it
304 This way we will be able to add a new event to this thread events list.
305 */
306 ThreadEventData* lookup_or_create_thread(gulong address, guint prio, LttTime creation_time, GQuark name){
307 printf("lookup_or_create\n");
308 int i, index = 0;
309 ThreadEventData *temp_thread;
310 ThreadEventData *temp_thread_2 = g_new(ThreadEventData, 1);
311 temp_thread_2->address = address;
312 temp_thread_2->prio = prio;
313 temp_thread_2->creation_time = creation_time;
314 temp_thread_2->name = name;
315 temp_thread_2->event_list = g_array_new(FALSE, FALSE, sizeof(EventData*));
316
317
318 for(i=0;i<thread_event_list->len;i++){
319 temp_thread = g_array_index(thread_event_list, ThreadEventData*, i);
320 if (temp_thread->address == temp_thread_2->address &&
321 ltt_time_compare(temp_thread->creation_time,temp_thread_2->creation_time) == 0)
322 return temp_thread; // Thread is found we return it
323 /* Otherwise we check for the priority, this will help us to defined the
324 index where to insert the thread. This way we don't to sort the thread list */
325 else if(temp_thread_2->prio <= temp_thread->prio) index++;
326 }
327
328 g_array_insert_val(thread_event_list,index,temp_thread_2);
329
330 return temp_thread_2; // New inserted thread is returned
331 }
332
333 void calculate_event_time(guint index, ThreadEventData *temp_thread){
334 LttTime next_tick = ltt_time_zero, delay, preempt_begin, preempt_time,
335 last_write_event_time, last_read_event_time, original_event_time;
336 EventData *new_event, *event;
337 int i,j, overruns = 0;
338 gboolean wait_period_called = FALSE;
339 RunningThread *temp_running_thread;
340 GArray* new_event_list = g_array_new(FALSE, FALSE, sizeof(EventData*));
341 gboolean first_thread_switch, running = FALSE;
342 LttTime new_period = { 0, temp_thread->period };
343
344 // We will iterate on all event of this thread
345 for(i=0;i<temp_thread->event_list->len;i++){
346 // for the first event read
347 if (i == 0){
348 new_event = g_array_index(temp_thread->event_list, EventData*, i);
349 last_write_event_time = new_event->event_time;
350 last_read_event_time = new_event->event_time;
351 original_event_time = new_event->event_time;
352 }
353 else{
354 last_write_event_time = new_event->event_time;
355 last_read_event_time = original_event_time;
356 new_event = g_array_index(temp_thread->event_list, EventData*, i);
357 original_event_time = new_event->event_time;
358 }
359
360 // Calculate the delay between to following events
361 delay = ltt_time_sub(original_event_time,last_read_event_time);
362
363 // We need to save all events from the timer_tick until the wait_period event
364 // At the same time we can calculate the new time of the event
365 if (new_event->name == LTT_EVENT_XENOLTT_TIMER_TICK){
366 printf("NEW PERIOD\n");
367 // The first tick will be unchanged
368 if(ltt_time_compare(ltt_time_zero,next_tick) != 0){
369 new_event->event_time = next_tick;
370 }
371 next_tick = ltt_time_add(new_event->event_time,new_period);
372 wait_period_called = FALSE; // We prepare for next period that should begin now
373
374 g_array_append_val(new_event_list,new_event); // insert the new timer_tick
375 printf("\tTIMER_TICK - TIME: %lu.%lu - %lu.%lu\n", original_event_time.tv_sec,original_event_time.tv_nsec,
376 new_event->event_time.tv_sec,new_event->event_time.tv_nsec);
377
378 first_thread_switch = TRUE;
379 preempt_time = ltt_time_zero;
380 preempt_begin = ltt_time_zero;
381
382 /************************************************************************
383 * Beginning of a new period
384 * We must check for thread_switching (preemption)
385 * new timer tick to create
386 * overrun to create
387 * event missed_period to create
388 ************************************************************************/
389
390 while(new_event->name != LTT_EVENT_XENOLTT_THREAD_WAIT_PERIOD){ // Until the end of the period
391 i++;
392 last_write_event_time = new_event->event_time;
393 last_read_event_time = original_event_time;
394 new_event = g_array_index(temp_thread->event_list, EventData*, i);
395 original_event_time = new_event->event_time;
396
397 // Calculate the delay between to following events
398 delay = ltt_time_sub(original_event_time,last_read_event_time);
399 delay = ltt_time_sub(delay,preempt_time);
400
401 // Need to test if we have exceeded the new period
402 if(new_event->name != LTT_EVENT_XENOLTT_TIMER_TICK){
403 if (ltt_time_compare(ltt_time_add(last_write_event_time,delay),next_tick) > 0){
404 EventData *tick_event = g_new(EventData, 1);
405 tick_event->event_time = next_tick;
406 tick_event->name = LTT_EVENT_XENOLTT_TIMER_TICK;
407 g_array_append_val(new_event_list,tick_event);
408 next_tick = ltt_time_add(tick_event->event_time,new_period);
409 printf("\t%s - TIME: \t%lu.%lu\n", g_quark_to_string(tick_event->name),tick_event->event_time.tv_sec,tick_event->event_time.tv_nsec);
410 overruns++;
411 }
412 }
413
414 if(new_event->name == LTT_EVENT_XENOLTT_THREAD_INIT ||
415 new_event->name == LTT_EVENT_XENOLTT_THREAD_SET_PERIOD ||
416 new_event->name == LTT_EVENT_XENOLTT_THREAD_START ||
417 new_event->name == LTT_EVENT_XENOLTT_THREAD_RESUME ||
418 new_event->name == LTT_EVENT_XENOLTT_THREAD_RENICE ||
419 new_event->name == LTT_EVENT_XENOLTT_THREAD_SUSPEND){
420 new_event->event_time = ltt_time_add(last_write_event_time,delay); // New time of the event
421 // Insert event in the period list
422 g_array_append_val(new_event_list,new_event);
423 printf("\t%s - TIME: %lu.%lu - %lu.%lu\n", g_quark_to_string(new_event->name),original_event_time.tv_sec,original_event_time.tv_nsec,
424 new_event->event_time.tv_sec,new_event->event_time.tv_nsec);
425 }
426 // the first Thread_Switch indicate that the thread is now running
427 else if(new_event->name == LTT_EVENT_XENOLTT_THREAD_SWITCH){
428 if (first_thread_switch){
429 running = TRUE;
430 first_thread_switch = FALSE;
431 new_event->event_time = ltt_time_add(last_write_event_time,delay); // New time of the event
432 // Insert event in the period list
433 g_array_append_val(new_event_list,new_event);
434 printf("\t%s - TIME: %lu.%lu - %lu.%lu\n", g_quark_to_string(new_event->name),original_event_time.tv_sec,original_event_time.tv_nsec,
435 new_event->event_time.tv_sec,new_event->event_time.tv_nsec);
436 }
437 // Not the first thread switch, we will delete this event and the previous one that should be thread_suspend
438 else if(running){
439 running = FALSE; // Stop the thread
440 new_event = g_array_index(temp_thread->event_list, EventData*, (i-1));
441 preempt_begin = new_event->event_time;// Save the time of the preemption (time of the suspend event
442 }
443 // Thread is suspended and want to restart, delete the thread_switch and the following event that should be thread_resume
444 else{
445 running = TRUE; // restart thread
446 i++;
447 new_event = g_array_index(temp_thread->event_list, EventData*, i);
448 preempt_time = ltt_time_add(preempt_time,ltt_time_sub(new_event->event_time,preempt_begin));// ignore the time spent in ready state
449 }
450 }
451 // Thread going in overrun
452 else if(new_event->name == LTT_EVENT_XENOLTT_TIMER_TICK){
453 new_event->event_time = next_tick;
454 next_tick = ltt_time_add(new_event->event_time,new_period);
455 overruns++; // If wait_period has not been called, this means we are going in overrun
456 // Insert event in the period list
457 g_array_append_val(new_event_list,new_event);
458 printf("\t%s - TIME: %lu.%lu - %lu.%lu\n", g_quark_to_string(new_event->name),original_event_time.tv_sec,original_event_time.tv_nsec,
459 new_event->event_time.tv_sec,new_event->event_time.tv_nsec);
460 }
461
462 if(new_event->name == LTT_EVENT_XENOLTT_THREAD_WAIT_PERIOD){
463 new_event->event_time = ltt_time_add(last_write_event_time,delay); // New time of the event
464 g_array_append_val(new_event_list,new_event);
465 printf("\t%s - TIME: %lu.%lu - %lu.%lu\n", g_quark_to_string(new_event->name),original_event_time.tv_sec,original_event_time.tv_nsec,
466 new_event->event_time.tv_sec,new_event->event_time.tv_nsec);
467 printf("END PERIOD\n");
468 wait_period_called = TRUE;
469 if(overruns > 0){
470 EventData *missed_period_event = g_new(EventData, 1);
471 missed_period_event->event_time = new_event->event_time; // Same time ??
472 missed_period_event->name = LTT_EVENT_XENOLTT_THREAD_MISSED_PERIOD;
473 g_array_append_val(new_event_list,missed_period_event);
474 printf("\t%s - TIME: %lu.%lu\n", g_quark_to_string(missed_period_event->name),
475 missed_period_event->event_time.tv_sec,missed_period_event->event_time.tv_nsec);
476 }
477 overruns = 0;
478 // Period is finished
479 running = FALSE;
480 }
481
482 if(new_event->name == LTT_EVENT_XENOLTT_THREAD_DELETE){
483 // Insert event in the period list
484 new_event->event_time = ltt_time_add(last_write_event_time,delay); // New time of the event
485 g_array_append_val(new_event_list,new_event);
486 printf("\t%s - TIME: %lu.%lu - %lu.%lu\n", g_quark_to_string(new_event->name),original_event_time.tv_sec,original_event_time.tv_nsec,
487 new_event->event_time.tv_sec,new_event->event_time.tv_nsec);
488 break;
489 }
490 }
491 }
492 // For other events, simply save them with new time
493 else{
494 if (new_event->name != LTT_EVENT_XENOLTT_THREAD_MISSED_PERIOD){
495 new_event->event_time = ltt_time_add(last_write_event_time,delay); // New time of the event
496 g_array_append_val(new_event_list,new_event);
497 printf("NO_PERIOD %s - TIME: %lu.%lu - %lu.%lu\n", g_quark_to_string(new_event->name),original_event_time.tv_sec,original_event_time.tv_nsec,
498 new_event->event_time.tv_sec,new_event->event_time.tv_nsec);
499 }
500 }
501 }
502
503 // Now we have a full list of events representing the simulation of the current task
504 // Last step consist of checking if this thread will be preempted by others
505 // To see that, we will check in the running_thread list to find some free time space
506
507 // Iterate on the event_list and check for every thread_switch
508 // We will iterate on all event of this thread
509 gboolean not_running = TRUE;
510
511 for(i=0;i<new_event_list->len;i++){
512 event = g_array_index(new_event_list, EventData*, i);
513 if (event->name == LTT_EVENT_XENOLTT_THREAD_SWITCH){
514 if (not_running){
515 not_running = FALSE;
516 for(j=0;j<running_thread->len;j++){
517 temp_running_thread = g_array_index(running_thread, RunningThread*, j);
518 // First we need to get the thread running at the closest time before the current time
519 if (ltt_time_compare(temp_running_thread->begin_time,event->event_time) > 0){
520 // If thread finishes after current time, we must delay the task
521 // We will check the previous thread in the running list
522 temp_running_thread = g_array_index(running_thread, RunningThread*, (j-1));
523 if (ltt_time_compare(temp_running_thread->end_time,event->event_time) <= 0){
524 event->event_time = temp_running_thread->end_time;
525 }
526 else{ // Time is good
527 break;
528 }
529 }
530 }
531
532
533 // At this time we should have found a free starting position
534 RunningThread *new_running = g_new(RunningThread,1);
535 new_running->thread = temp_thread;
536 new_running->begin_time = event->event_time;
537
538 j--;
539
540 delay = ltt_time_zero;
541 // Next step is to chek before all event, if we must preempt the thread because a higher priority task is already running
542 // Preemption will cause the creation of 2 events thread_switch
543 for(i++;i<new_event_list->len;i++){
544 event = g_array_index(new_event_list, EventData*, i);
545 // Don't delay Timer_Tick
546 if (event->name == LTT_EVENT_XENOLTT_TIMER_TICK){
547 if (wait_period_called) wait_period_called = FALSE;
548 }
549 // If event is a thread_switch, this means we have finish the period
550 else if (event->name == LTT_EVENT_XENOLTT_THREAD_SWITCH){
551 event->event_time = ltt_time_add(event->event_time,delay);
552 new_running->end_time = event->event_time;
553 // Add the thread in the running thread list
554 // j is the index where we found a free time space
555 g_array_insert_val(running_thread,j,new_running);
556 not_running = TRUE;
557 break;
558 }
559 else{
560 event->event_time = ltt_time_add(event->event_time,delay);
561
562 // We must check the if the next running thread is beginning before the event_time
563 temp_running_thread = g_array_index(running_thread, RunningThread*, j);
564
565 if(ltt_time_compare(event->event_time,temp_running_thread->begin_time) >= 0){
566 // if so, we must preempt the task and delay all event of the period
567 delay = ltt_time_add(delay,ltt_time_sub(event->event_time,temp_running_thread->begin_time));
568
569 // Insert a thread switch out
570 new_event = g_new(EventData, 1);
571 new_event->event_time = temp_running_thread->begin_time;
572 new_event->name = LTT_EVENT_XENOLTT_THREAD_SWITCH;
573 g_array_insert_val(new_event_list,i,new_event);
574
575 // Insert a thread switch in that will be check at next iteration
576 new_event = g_new(EventData, 1);
577 new_event->event_time = temp_running_thread->end_time;
578 new_event->name = LTT_EVENT_XENOLTT_THREAD_SWITCH;
579 g_array_insert_val(new_event_list,(i+1),new_event);
580
581 // Insert the thread in the running thread
582 new_running->end_time = temp_running_thread->begin_time;
583 g_array_insert_val(running_thread,j,new_running);
584 not_running = TRUE;
585
586 break;
587 }
588 }
589 }
590 }
591 }
592 }
593
594 /*
595 //Print the new thread simulation
596 for(j=0;j<new_event_list->len;j++){
597 event = g_array_index(new_event_list, EventData*, j);
598 printf("%s - TIME: %lu.%lu\n", g_quark_to_string(event->name),event->event_time.tv_sec,event->event_time.tv_nsec);
599 }
600 */
601 }
602
603 void simulater_high_priority_thread(ThreadEventData* thread){
604 EventData *event;
605 gboolean running = FALSE;
606 RunningThread *run_thread = g_new(RunningThread, 1);
607 RunningThread *temp_thread;
608 int i,j;
609 LttTime begin_time = ltt_time_zero;
610 LttTime end_time = ltt_time_zero;
611 gboolean inserted;
612
613 for(i=0;i<thread->event_list->len;i++){
614 event = g_array_index(thread->event_list, EventData*, i);
615
616 if(event->name == LTT_EVENT_XENOLTT_THREAD_SWITCH){
617 if(running){
618 running = FALSE;
619 end_time = event->event_time;
620 run_thread = g_new(RunningThread, 1);
621 run_thread->thread = thread;
622 run_thread->begin_time = begin_time;
623 run_thread->end_time = end_time;
624
625 inserted = FALSE;
626 for(j=0;j<running_thread->len;j++){
627 temp_thread = g_array_index(running_thread, RunningThread*, j);
628 if (ltt_time_compare(temp_thread->begin_time,run_thread->begin_time) > 0){
629 g_array_insert_val(running_thread,j,run_thread);
630 inserted = TRUE;
631 break;
632 }
633 }
634 if (!inserted) g_array_append_val(running_thread,run_thread);
635 }
636 else{
637 running = TRUE;
638 begin_time = event->event_time;
639 }
640 }
641
642
643 }
644 }
645
646 gint sort_running_thread(gconstpointer a,gconstpointer b){
647 const RunningThread *pa = (const RunningThread*)a;
648 const RunningThread *pb = (const RunningThread*)b;
649
650 return ltt_time_compare(pa->begin_time,pb->begin_time);
651 }
652
653 void compute_simulation(guint index,guint period){
654
655 int i;
656 ThreadEventData *temp_thread;
657 RunningThread *run_thread;
658
659 printf("---\n");
660
661 printf("-> %u\n",thread_event_list->len);
662 // First, set the new period of the thread
663 temp_thread = g_array_index(thread_event_list, ThreadEventData*, index);
664 // We will double the simulation only if period has changed
665 if (period != temp_thread->period) temp_thread->period = period;
666 else{
667 printf("Period is the same, no need to simulate\n");
668 return;
669 }
670
671 /*
672 First, we need to ignore all task with higher priority
673 than the task we want to simulate that's why we begin the simulation
674 from the thread index which we will modify the period
675 */
676 printf("simulater_high_priority_thread\n");
677 for(i=0;i<index;i++){
678 temp_thread = g_array_index(thread_event_list, ThreadEventData*, i);
679 simulater_high_priority_thread(temp_thread);
680 }
681
682 for(i=index;i<thread_event_list->len;i++){
683 temp_thread = g_array_index(thread_event_list, ThreadEventData*, i);
684 printf("%s - %u\n",g_quark_to_string(temp_thread->name), temp_thread->prio);
685
686
687 // temp_thread->period = period;
688 temp_thread->period = 20000;
689
690
691 // We will simulate this thread considering all higher priority threads
692 printf("calculate_event_time\n");
693 calculate_event_time(index, temp_thread);
694 }
695
696
697 printf("print run_thread\n");
698 for(i=0;i<running_thread->len;i++){
699 run_thread = g_array_index(running_thread, RunningThread*, i);
700 printf("%s\tFROM:%lu.%lu\tTO:%lu.%lu\n",g_quark_to_string(run_thread->thread->name),run_thread->begin_time.tv_sec,run_thread->begin_time.tv_nsec,
701 run_thread->end_time.tv_sec,run_thread->end_time.tv_nsec);
702 }
703 }
704
705 gboolean save_event(void *hook_data, void *call_data){
706 LttvTraceHookByFacility *thf = (LttvTraceHookByFacility*)hook_data;
707 LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
708 LttvTraceState *ts = (LttvTraceState*)tfcs->parent.parent.t_context;
709 guint cpu = tfcs->parent.cpu;
710 LttvXenoThreadState *thread_info;
711
712 LttvTracefileContext *tfc = (LttvTracefileContext *)call_data;
713 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
714 GQuark event_name = ltt_eventtype_name(ltt_event_eventtype(e));
715 LttTime evtime = ltt_event_time(e);
716
717 if (event_name == LTT_EVENT_XENOLTT_TIMER_TICK){
718 gulong timer_address = ltt_event_get_long_unsigned(e, thf->f1);
719 thread_info = lttv_xeno_state_find_thread_from_timer(ts,cpu,timer_address);
720 }
721 else{
722 gulong address = ltt_event_get_long_unsigned(e, thf->f1);
723 // First we need to lookup for the current thread in the list
724 thread_info = lttv_xeno_state_find_thread(ts,cpu,address);
725 }
726
727 if (thread_info != NULL){
728 ThreadEventData *thread = lookup_or_create_thread(thread_info->address, thread_info->prio, thread_info->creation_time, thread_info->name);
729 // printf("%s - %lu.%lu\n",g_quark_to_string(event_name), evtime.tv_sec, evtime.tv_nsec);
730 if (event_name == LTT_EVENT_XENOLTT_THREAD_SET_PERIOD) thread->period = thread_info->period;
731 //Thread is found in the table, we can insert the new event in the list
732 EventData *new_event = g_new(EventData, 1);
733 new_event->event_time = evtime;
734 new_event->name = event_name;
735 new_event->event = e;
736 g_array_append_val(thread->event_list,new_event);
737 }
738
739 return FALSE;
740 }
741
742 /****************************************************************************************************************************/
743
744
745
746
747 static void module_init()
748 {
749 }
750
751 static void module_destroy()
752 {
753 }
754
755
756 LTTV_MODULE("xenoltt_sim", "Compute Xenomai Tasks simulation", \
757 "Simulate a task execution with a different period", \
758 module_init, module_destroy, "state");
This page took 0.046462 seconds and 4 git commands to generate.