Commit | Line | Data |
---|---|---|
e09e518e GM |
1 | #include <lttv/option.h> |
2 | #include <lttv/module.h> | |
3 | #include <lttv/hook.h> | |
4 | #include <lttv/attribute.h> | |
5 | #include <lttv/iattribute.h> | |
6 | #include <lttv/stats.h> | |
7 | #include <lttv/filter.h> | |
8 | #include <ltt/ltt.h> | |
9 | #include <ltt/event.h> | |
10 | #include <ltt/trace.h> | |
11 | #include <stdio.h> | |
12 | #include <math.h> | |
13 | #include "realtime.h" | |
14 | ||
15 | int application_pid; | |
16 | long period_sec, period_nsec, running_time_sec, running_time_nsec; | |
17 | long t2_sec, t2_nsec; | |
18 | GArray *fsm_list; | |
19 | struct timeval *tv1, *tv2; | |
20 | ||
21 | static gboolean schedule(void *hook_data, void *call_data){ | |
22 | LttvTracefileState *s = (LttvTracefileState *) call_data; | |
23 | LttEvent *e = ltt_tracefile_get_event(s->parent.tf); | |
24 | LttvTraceHook *th = (LttvTraceHook *)hook_data; | |
25 | ||
26 | struct marker_field *f = lttv_trace_get_hook_field(th,0); | |
27 | guint32 prev_pid = ltt_event_get_long_unsigned(e, f); | |
28 | ||
29 | f = lttv_trace_get_hook_field(th, 1); | |
30 | guint32 next_pid = ltt_event_get_long_unsigned(e, f); | |
31 | ||
32 | LttTime time = ltt_event_time(e); | |
33 | t2_sec=(long)time.tv_sec; | |
34 | t2_nsec=(long)time.tv_nsec; | |
35 | struct realtime *rtstruct; | |
36 | if(application_pid==-1){ | |
37 | //iterate over all fsms | |
38 | int i, found=0; | |
39 | ||
40 | for(i=0; i<fsm_list->len; i++) | |
41 | { | |
42 | rtstruct = g_array_index(fsm_list, struct realtime *, i); | |
43 | if(rtstruct->pid==next_pid){ | |
44 | found=1; | |
45 | realtimeContext_schedule_in(&rtstruct->_fsm, t2_sec, t2_nsec); | |
46 | break; | |
47 | } | |
48 | else if(rtstruct->pid==prev_pid){ | |
49 | found=1; | |
50 | realtimeContext_schedule_out(&rtstruct->_fsm, t2_sec, t2_nsec); | |
51 | break; | |
52 | } | |
53 | ||
54 | } | |
55 | if(!found){ | |
56 | rtstruct = realtime_Init(next_pid, DEFAULT_PERIOD_SEC, | |
57 | DEFAULT_PERIOD_NSEC, | |
58 | DEFAULT_RUNNING_TIME_SEC, | |
59 | DEFAULT_RUNNING_TIME_NSEC); | |
60 | g_array_append_val(fsm_list, rtstruct); | |
61 | //call transition | |
62 | realtimeContext_schedule_in(&rtstruct->_fsm, t2_sec, t2_nsec); | |
63 | ||
64 | } | |
65 | } | |
66 | ||
67 | else//we might have already created the fsm so check @ first | |
68 | { | |
69 | if(fsm_list->len==0){ | |
70 | rtstruct = realtime_Init(application_pid, period_sec, period_nsec, running_time_sec, running_time_nsec); | |
71 | g_array_append_val(fsm_list, rtstruct); | |
72 | ||
73 | } | |
74 | else | |
75 | rtstruct = g_array_index(fsm_list, struct realtime *, 0); | |
76 | ||
77 | ||
78 | if(rtstruct->pid==next_pid) | |
79 | realtimeContext_schedule_in(&rtstruct->_fsm, t2_sec, t2_nsec); | |
80 | else if(rtstruct->pid==prev_pid) | |
81 | realtimeContext_schedule_out(&rtstruct->_fsm, t2_sec, t2_nsec); | |
82 | } | |
83 | return FALSE; | |
84 | } | |
85 | void removefsm(struct realtime *rtstruct){ | |
86 | int i; | |
87 | for(i=0; i<fsm_list->len; i++){ | |
88 | struct realtime *tmp = g_array_index(fsm_list,struct realtime *, i); | |
89 | if(tmp==rtstruct){ | |
90 | g_array_remove_index(fsm_list,i); | |
91 | break; | |
92 | } | |
93 | } | |
94 | ||
95 | } | |
96 | static int add_events_by_id_hooks(void *hook_data, void *call_data){ | |
97 | LttvTraceContext *tc = (LttvTraceContext *) call_data; | |
98 | LttTrace *t = tc->t; | |
99 | ||
100 | //EVENT CHROOT | |
101 | GQuark LTT_FACILITY_KERNEL = g_quark_from_string("kernel"); | |
102 | GQuark LTT_EVENT_SCHED_SCHEDULE = g_quark_from_string("sched_schedule"); | |
103 | //EVENT FIELDS | |
104 | GQuark LTT_FIELD_PREV_PID = g_quark_from_string("prev_pid"); | |
105 | GQuark LTT_FIELD_NEXT_PID = g_quark_from_string("next_pid"); | |
106 | GQuark LTT_FIELD_PREV_STATE = g_quark_from_string("prev_state"); | |
107 | ||
108 | ||
109 | GArray *hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 1); | |
110 | ||
111 | lttv_trace_find_hook(t, LTT_FACILITY_KERNEL, LTT_EVENT_SCHED_SCHEDULE, | |
112 | FIELD_ARRAY(LTT_FIELD_PREV_PID, LTT_FIELD_NEXT_PID, LTT_FIELD_PREV_STATE), | |
113 | schedule, | |
114 | NULL, | |
115 | &hooks); | |
116 | ||
117 | int nb_tracefiles = tc->tracefiles->len; | |
118 | LttvTracefileContext **tfc; | |
119 | LttvHooks *needed_hooks; | |
120 | LttvTraceHook *th = (LttvTraceHook *)hook_data; | |
121 | int i, j; | |
122 | for(i=0; i<nb_tracefiles; i++){ | |
123 | tfc = &g_array_index(tc->tracefiles, LttvTracefileContext*, i); | |
124 | for(j=0; j<hooks->len; j++){ | |
125 | th=&g_array_index(hooks, LttvTraceHook, j); | |
126 | needed_hooks = lttv_hooks_by_id_find((*tfc)->event_by_id, th->id); | |
127 | lttv_hooks_add(needed_hooks, th->h, th, LTTV_PRIO_DEFAULT); | |
128 | } | |
129 | } | |
130 | } | |
131 | static void init(){ | |
132 | ||
133 | gboolean result; | |
134 | ||
135 | LttvAttributeValue value; | |
136 | ||
137 | LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes()); | |
138 | ||
139 | static LttvHooks *before_trace; | |
140 | ||
141 | result = lttv_iattribute_find_by_path(attributes, "hooks/trace/before", LTTV_POINTER, &value); | |
142 | g_assert(result); | |
143 | before_trace = *(value.v_pointer); | |
144 | g_assert(before_trace); | |
145 | ||
146 | //Register add_events_by_id_hook to be called before starting to read the trace | |
147 | //This function will be overwritten between checkers | |
148 | lttv_hooks_add(before_trace, add_events_by_id_hooks, NULL, LTTV_PRIO_DEFAULT); | |
149 | ||
150 | printf("Enter your real-time application ip (-1 for all)\n"); | |
151 | scanf("%d", &application_pid); | |
152 | if(application_pid!=-1) | |
153 | { | |
154 | printf("Enter period_sec, period_nsec, running_time_sec, running_time_nsec:\n"); | |
155 | //scanf("%ld%ld%ld%ld", &period_sec, &period_nsec, &running_time_sec, &running_time_nsec); | |
156 | period_sec=1; | |
157 | period_nsec=0; | |
158 | running_time_sec=0; | |
159 | running_time_nsec=500000; | |
160 | ||
161 | } | |
162 | tv1 = (struct timeval *)malloc(sizeof(struct timeval)); | |
163 | gettimeofday(tv1, NULL); | |
164 | ||
165 | fsm_list = g_array_new(FALSE, FALSE, sizeof(struct realtime *)); | |
166 | } | |
167 | static void destroy(){ | |
168 | tv2 = (struct timeval *)malloc(sizeof(struct timeval)); | |
169 | gettimeofday(tv2, NULL); | |
170 | int seconds = tv2->tv_sec - tv1->tv_sec; | |
171 | printf("analysis took: %d seconds \n", seconds); | |
172 | ||
173 | ||
174 | } | |
175 | ||
176 | LTTV_MODULE("rt_checker", "Detects scheduling latencies", | |
177 | "detects latencies", | |
178 | init, destroy, "stats", "batchAnalysis", "option") | |
179 |