summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@ludwig.cs.unc.edu.cs.unc.edu>2010-11-30 17:51:38 -0500
committerGlenn Elliott <gelliott@ludwig.cs.unc.edu.cs.unc.edu>2010-11-30 17:51:38 -0500
commitb9a423897d0cb04d682f91bccb277915c37761e7 (patch)
tree51e8f8901c92039013c89c035cfef1062555a65a
parentbb7de78222a2c95e8a5c97c3b0400d0bf3d7510e (diff)
Just some stuff for AEDZL.wip-aedzl-revised
-rw-r--r--SConstruct3
-rw-r--r--include/load.h2
-rw-r--r--include/sched_trace.h10
-rw-r--r--src/showst2.cpp443
-rw-r--r--src/st2pl.c12
5 files changed, 463 insertions, 7 deletions
diff --git a/SConstruct b/SConstruct
index 377297c..c265d89 100644
--- a/SConstruct
+++ b/SConstruct
@@ -19,9 +19,11 @@ if os != 'Linux':
19# base config 19# base config
20env = Environment( 20env = Environment(
21 CC = 'gcc', 21 CC = 'gcc',
22 CXX = 'g++',
22 CCFLAGS = Split(DEBUG_FLAGS), 23 CCFLAGS = Split(DEBUG_FLAGS),
23 CPPPATH = Split(INCLUDE_DIRS), 24 CPPPATH = Split(INCLUDE_DIRS),
24 CPPDEFINES = '-DMAX_TASKS=%d' % MAX_TASKS, 25 CPPDEFINES = '-DMAX_TASKS=%d' % MAX_TASKS,
26 LIBS = Split('blitz m')
25) 27)
26 28
27# ##################################################################### 29# #####################################################################
@@ -29,3 +31,4 @@ env = Environment(
29common = ['src/load.c', 'src/eheap.c', 'src/util.c'] 31common = ['src/load.c', 'src/eheap.c', 'src/util.c']
30env.Program('st_convert', ['src/st2pl.c'] + common) 32env.Program('st_convert', ['src/st2pl.c'] + common)
31env.Program('st_show', ['src/showst.c'] + common) 33env.Program('st_show', ['src/showst.c'] + common)
34env.Program('st_show2', ['src/showst2.cpp'] + common)
diff --git a/include/load.h b/include/load.h
index e4a35c2..6d13d07 100644
--- a/include/load.h
+++ b/include/load.h
@@ -67,7 +67,7 @@ u32 count_tasks(void);
67#define for_each_event_t(t, e, evtype) \ 67#define for_each_event_t(t, e, evtype) \
68 for_each_event(t, e) if (e->rec->hdr.type == evtype) 68 for_each_event(t, e) if (e->rec->hdr.type == evtype)
69 69
70#define find(e, evtype) \ 70#define _find(e, evtype) \
71 while (e && e->rec->hdr.type != evtype) e = e->next; if (!e) break; 71 while (e && e->rec->hdr.type != evtype) e = e->next; if (!e) break;
72 72
73 73
diff --git a/include/sched_trace.h b/include/sched_trace.h
index 8bdd253..6b69827 100644
--- a/include/sched_trace.h
+++ b/include/sched_trace.h
@@ -4,6 +4,7 @@
4#include <stdint.h> 4#include <stdint.h>
5 5
6typedef uint8_t u8; 6typedef uint8_t u8;
7typedef int32_t s32;
7typedef uint32_t u32; 8typedef uint32_t u32;
8typedef uint16_t u16; 9typedef uint16_t u16;
9typedef uint64_t u64; 10typedef uint64_t u64;
@@ -66,6 +67,13 @@ struct st_completion_data { /* A job completed. */
66 u8 __unused[3]; 67 u8 __unused[3];
67}; 68};
68 69
70struct st_completion_adaptive_data {
71 u32 actual_exe;
72 u32 estimated_exe;
73 s32 accumulated_err;
74 u8 __unused[4];
75};
76
69struct st_block_data { /* A task blocks. */ 77struct st_block_data { /* A task blocks. */
70 u64 when; 78 u64 when;
71 u64 __unused; 79 u64 __unused;
@@ -95,6 +103,7 @@ typedef enum {
95 ST_BLOCK, 103 ST_BLOCK,
96 ST_RESUME, 104 ST_RESUME,
97 ST_SYS_RELEASE, 105 ST_SYS_RELEASE,
106 ST_COMPLETION_ADAPTIVE
98} st_event_record_type_t; 107} st_event_record_type_t;
99 108
100struct st_event_record { 109struct st_event_record {
@@ -112,6 +121,7 @@ struct st_event_record {
112 DATA(block); 121 DATA(block);
113 DATA(resume); 122 DATA(resume);
114 DATA(sys_release); 123 DATA(sys_release);
124 DATA(completion_adaptive);
115 125
116 } data; 126 } data;
117}; 127};
diff --git a/src/showst2.cpp b/src/showst2.cpp
new file mode 100644
index 0000000..71f324a
--- /dev/null
+++ b/src/showst2.cpp
@@ -0,0 +1,443 @@
1#include <iostream>
2#include <sstream>
3#include <fstream>
4#include <set>
5#include <vector>
6#include <map>
7
8#include <blitz/array.h>
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <unistd.h>
13
14extern "C"
15{
16#include "load.h"
17#include "sched_trace.h"
18#include "eheap.h"
19}
20
21using namespace std;
22using namespace blitz;
23
24double SCALE = 1000000.0; // ms
25//double SCALE = 1000.0; // us
26
27static void usage(const char *str)
28{
29 fprintf(stderr,
30 "\n USAGE\n"
31 "\n"
32 " st_show [opts] <file.st>+\n"
33 "\n"
34 " OPTIONS\n"
35 " -r -- find task system release and exit\n"
36 " -f -- use first non-zero event as system release\n"
37 " if no system release event is found\n"
38 " -c -- display a count of the number of events\n"
39 "\n\n"
40 );
41 fprintf(stderr, "Aborted: %s\n", str);
42 exit(1);
43}
44
45struct Job
46{
47 u32 jid;
48
49 mutable u32 actual_exe;
50 mutable u32 estimated_exe;
51 mutable s32 accum_err;
52
53 mutable u64 release;
54 mutable u64 deadline;
55 mutable u64 completion;
56
57 bool operator<(const Job& rhs) const
58 {
59 return(jid < rhs.jid);
60 }
61};
62
63struct Task
64{
65 u16 pid;
66
67 mutable u32 wcet;
68 mutable u32 period;
69
70 bool operator<(const Task& rhs) const
71 {
72 return(pid < rhs.pid);
73 }
74};
75
76map<Task, set<Job> > traceData;
77
78template <class T>
79double stddev(const T& arr)
80{
81 double stddev;
82
83 if(arr.size() > 1)
84 {
85 double avg = blitz::mean(arr);
86
87 blitz::Array<double, 1> devs(arr.size());
88 devs = arr - avg;
89 devs *= devs;
90 double devsum = blitz::sum(devs);
91 stddev = sqrt(devsum/(devs.size()-1));
92 }
93 else
94 {
95 stddev = 0.0;
96 }
97
98 return(stddev);
99}
100
101#define OPTSTR "rcf"
102
103int main(int argc, char** argv)
104{
105 unsigned int count;
106 struct heap *h;
107 struct heap_node *hn, *first = NULL;
108 u64 time;
109 struct st_event_record *rec;
110 int find_release = 0;
111 int show_count = 0;
112 int use_first_nonzero = 0;
113 int opt;
114
115 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
116 switch (opt) {
117 case 'r':
118 find_release = 1;
119 break;
120 case 'c':
121 show_count = 1;
122 break;
123 case 'f':
124 use_first_nonzero = 1;
125 break;
126 case ':':
127 usage("Argument missing.");
128 break;
129 case '?':
130 default:
131 usage("Bad argument.");
132 break;
133 }
134 }
135
136 u64 starttime = 0;
137
138 h = load(argv + optind, argc - optind, &count);
139 if (!h)
140 return 1;
141 if (show_count)
142 printf("Loaded %u events.\n", count);
143 while ((hn = heap_take(earlier_event, h))) {
144
145 rec = (st_event_record*)heap_node_value(hn);
146
147 time = event_time(rec);
148 if (time != 0 && !first)
149 first = hn;
150 time /= 1000000; /* convert to milliseconds */
151
152 if(rec->hdr.type == ST_SYS_RELEASE && starttime == 0)
153 {
154 starttime = rec->data.sys_release.when;
155 }
156 else if(rec->hdr.type == ST_PARAM)
157 {
158 Task tsk;
159 tsk.pid = rec->hdr.pid;
160 tsk.wcet = rec->data.param.wcet;
161 tsk.period = rec->data.param.period;
162
163 map<Task, set<Job> >::iterator iter = traceData.find(tsk);
164 if(iter == traceData.end())
165 {
166 traceData[tsk] = set<Job>();
167 }
168 else
169 {
170 iter->first.wcet = rec->data.param.wcet;
171 iter->first.period = rec->data.param.period;
172 }
173 }
174 else if(rec->hdr.type == ST_RELEASE)
175 {
176 Task srch;
177 srch.pid = rec->hdr.pid;
178
179 map<Task, set<Job> >::iterator iter = traceData.find(srch);
180
181 // force the task to be there.
182 if(iter == traceData.end())
183 {
184 traceData[srch] = set<Job>();
185 iter = traceData.find(srch);
186 iter->first.period = rec->data.release.release - rec->data.release.deadline;
187 }
188
189 if(iter != traceData.end())
190 {
191 Job jsrch;
192 jsrch.jid = rec->hdr.job;
193
194 set<Job>::iterator jter = iter->second.find(jsrch);
195 if(jter == iter->second.end())
196 {
197 jsrch.release = rec->data.release.release;
198 jsrch.deadline = rec->data.release.deadline;
199 jsrch.completion = 0;
200 jsrch.actual_exe = 0;
201 jsrch.estimated_exe = 0;
202 jsrch.accum_err = 0;
203 iter->second.insert(jsrch);
204 }
205 else
206 {
207 jter->release = rec->data.release.release;
208 jter->deadline = rec->data.release.deadline;
209 }
210 }
211 else
212 {
213 cerr<<"Could not match release to task."<<endl;
214 }
215 }
216 else if(rec->hdr.type == ST_COMPLETION)
217 {
218 Task srch;
219 srch.pid = rec->hdr.pid;
220
221 map<Task, set<Job> >::iterator iter = traceData.find(srch);
222
223 // force the task to be there.
224 if(iter == traceData.end())
225 {
226 traceData[srch] = set<Job>();
227 iter = traceData.find(srch);
228 iter->first.period = 0;
229 }
230
231 if(iter != traceData.end())
232 {
233 Job jsrch;
234 jsrch.jid = rec->hdr.job;
235 set<Job>::iterator j = iter->second.find(jsrch);
236
237
238 if(j == iter->second.end())
239 {
240 jsrch.release = 0;
241 jsrch.deadline = 0;
242 jsrch.actual_exe = 0;
243 jsrch.estimated_exe = 0;
244 jsrch.accum_err = 0;
245 iter->second.insert(jsrch);
246 j = iter->second.find(jsrch);
247 }
248
249 if(j != iter->second.end())
250 {
251 j->completion = rec->data.completion.when;
252 }
253 else
254 {
255 cerr<<"Could not find the job to complete."<<endl;
256 }
257 }
258 else
259 {
260 cerr<<"Could not find the task for which has a job to complete."<<endl;
261 }
262 }
263 else if(rec->hdr.type == ST_COMPLETION_ADAPTIVE)
264 {
265 Task srch;
266 srch.pid = rec->hdr.pid;
267
268 map<Task, set<Job> >::iterator iter = traceData.find(srch);
269
270 // force the task to be there.
271 if(iter == traceData.end())
272 {
273 traceData[srch] = set<Job>();
274 iter = traceData.find(srch);
275 iter->first.period = 0;
276 }
277
278 if(iter != traceData.end())
279 {
280 Job jsrch;
281 jsrch.jid = rec->hdr.job;
282 set<Job>::iterator j = iter->second.find(jsrch);
283
284 if(j == iter->second.end())
285 {
286 jsrch.release = 0;
287 jsrch.deadline = 0;
288 jsrch.completion = 0;
289 iter->second.insert(jsrch);
290 j = iter->second.find(jsrch);
291 }
292
293 if(j != iter->second.end())
294 {
295 j->actual_exe = rec->data.completion_adaptive.actual_exe;
296 j->estimated_exe = rec->data.completion_adaptive.estimated_exe;
297 j->accum_err = rec->data.completion_adaptive.accumulated_err;
298 }
299 else
300 {
301 cerr<<"Could not find the job to complete."<<endl;
302 }
303 }
304 else
305 {
306 cerr<<"Could not find the task for which has a job to complete."<<endl;
307 }
308 }
309 }
310
311 // data loaded. discard unfinished jobs. and first and last.
312 for(map<Task, set<Job> >::iterator tsk(traceData.begin()), tskEnd(traceData.end());
313 tsk != tskEnd;
314 ++tsk)
315 {
316 if(!tsk->second.empty())
317 {
318 tsk->second.erase(tsk->second.begin());
319 }
320 if(!tsk->second.empty())
321 {
322 set<Job>::iterator last(tsk->second.end());
323 --last;
324 tsk->second.erase(last);
325 }
326
327 for(set<Job>::iterator job(tsk->second.begin()), jobEnd(tsk->second.end());
328 job != jobEnd;
329 )
330 {
331 if(job->completion == 0 || job->release == 0 || job->deadline == 0)
332 {
333 set<Job>::iterator temp(job);
334 ++job;
335 tsk->second.erase(temp);
336 }
337 else
338 {
339 ++job;
340 }
341 }
342 }
343
344
345 ofstream outs;
346 outs.open("summary.csv");
347 outs<<"#period, wcet (us), mean_exe, stdev_exe, min_delta_exe, max_delta_exe, mean_delta_exe, stdev_delta_exe, min_rt, max_rt, mean_rt, stdev_rt, min_tardy, max_tardy, mean_tardy, std_tardy"<<endl;
348
349 // print stats.
350 for(map<Task, set<Job> >::iterator tsk(traceData.begin()), tskEnd(traceData.end());
351 tsk != tskEnd;
352 ++tsk)
353 {
354 size_t sz = tsk->second.size();
355 Array<double, 1> releases(sz);
356 Array<double, 1> completions(sz);
357 Array<double, 1> deadlines(sz);
358
359 Array<double, 1> actual_exes(sz);
360 Array<double, 1> est_exes(sz);
361 Array<double, 1> accum_errs(sz);
362
363 int i = 0;
364 for(set<Job>::iterator job(tsk->second.begin()), jobEnd(tsk->second.end());
365 job != jobEnd;
366 ++job, ++i)
367 {
368 releases(i) = (double)job->release;
369 completions(i) = (double)job->completion;
370 deadlines(i) = (double)job->deadline;
371
372 actual_exes(i) = (double)job->actual_exe;
373 est_exes(i) = (double)job->estimated_exe;
374 accum_errs(i) = (double)job->accum_err;
375 }
376
377 Array<double, 1> rt(sz);
378 Array<double, 1> tardy(sz);
379 Array<double, 1> delta_exe(sz);
380
381 rt = completions - releases;
382 tardy = where(completions > deadlines, completions - deadlines, 0.0);
383 delta_exe = actual_exes - est_exes;
384
385 // done computing data. dump stuff to files.
386
387 // tardiness growth and estimates
388 stringstream filename;
389 double per = ((int)(roundf(tsk->first.period/10000.0)))/100.0;
390 double exe = ((int)(roundf(tsk->first.wcet/10000.0)))/100.0;
391 filename<<"e"<<exe<<"_p"<<per<<"_pid"<<tsk->first.pid;
392 if(stddev(actual_exes)/SCALE > 0.4)
393 {
394 filename<<"+";
395 }
396 filename<<".csv";
397
398 ofstream tardGrowth;
399 tardGrowth.open(filename.str().c_str());
400 tardGrowth<<"#time, tardiness, actual_exe, est_exe, delta_exe, accum_err"<<endl;
401 for(i = 0; i < (int)sz; ++i)
402 {
403 tardGrowth<<(completions(i)-starttime)/SCALE<<", "
404 <<tardy(i)/SCALE<<", "
405 <<actual_exes(i)/SCALE<<", "
406 <<est_exes(i)/SCALE<<", "
407 <<delta_exe(i)/SCALE<<", "
408 <<accum_errs(i)/SCALE<<endl;
409 }
410 tardGrowth.close();
411
412 // task stats
413 outs<<tsk->first.period/SCALE<<", " // id
414 <<tsk->first.wcet/SCALE<<", " // id
415 <<blitz::mean(actual_exes)/SCALE<<", " // avg actual exe
416 <<stddev(actual_exes)/SCALE<<", "
417 <<blitz::min(delta_exe)/SCALE<<", " // estimation accuracy
418 <<blitz::max(delta_exe)/SCALE<<", "
419 <<blitz::mean(delta_exe)/SCALE<<", "
420 <<stddev(delta_exe)/SCALE<<", "
421 <<blitz::min(rt)/SCALE<<", " // response time
422 <<blitz::max(rt)/SCALE<<", "
423 <<blitz::mean(rt)/SCALE<<", "
424 <<stddev(rt)/SCALE<<", "
425 <<blitz::min(tardy)/SCALE<<", " // tardiness
426 <<blitz::max(tardy)/SCALE<<", "
427 <<blitz::mean(tardy)/SCALE<<", "
428 <<stddev(tardy)/SCALE<<endl;
429 }
430 outs.close();
431
432 return 0;
433}
434
435
436
437
438
439
440
441
442
443
diff --git a/src/st2pl.c b/src/st2pl.c
index 6e86c62..90a67ed 100644
--- a/src/st2pl.c
+++ b/src/st2pl.c
@@ -48,9 +48,9 @@ static void write_prolog_kb(void)
48 for_each_task(t) { 48 for_each_task(t) {
49 e = t->events; 49 e = t->events;
50 while (e) { 50 while (e) {
51 find(e, ST_SWITCH_TO); 51 _find(e, ST_SWITCH_TO);
52 e2 = e; 52 e2 = e;
53 find(e, ST_SWITCH_AWAY); 53 _find(e, ST_SWITCH_AWAY);
54 printf("scheduled(job(%u, %u), %f, %f).\n", 54 printf("scheduled(job(%u, %u), %f, %f).\n",
55 e2->rec->hdr.pid, 55 e2->rec->hdr.pid,
56 e2->rec->hdr.job, 56 e2->rec->hdr.job,
@@ -62,9 +62,9 @@ static void write_prolog_kb(void)
62 for_each_task(t) { 62 for_each_task(t) {
63 e = t->events; 63 e = t->events;
64 while (e) { 64 while (e) {
65 find(e, ST_BLOCK); 65 _find(e, ST_BLOCK);
66 e2 = e; 66 e2 = e;
67 find(e, ST_RESUME); 67 _find(e, ST_RESUME);
68 printf("suspended(job(%u, %u), %f, %f).\n", 68 printf("suspended(job(%u, %u), %f, %f).\n",
69 e2->rec->hdr.pid, 69 e2->rec->hdr.pid,
70 e2->rec->hdr.job, 70 e2->rec->hdr.job,
@@ -108,9 +108,9 @@ static void write_asy(double from, double to)
108 for_each_task(t) { 108 for_each_task(t) {
109 e = t->events; 109 e = t->events;
110 while (e) { 110 while (e) {
111 find(e, ST_SWITCH_TO); 111 _find(e, ST_SWITCH_TO);
112 e2 = e; 112 e2 = e;
113 find(e, ST_SWITCH_AWAY); 113 _find(e, ST_SWITCH_AWAY);
114 t1 = ns2ms_adj(e2->rec->data.switch_to.when); 114 t1 = ns2ms_adj(e2->rec->data.switch_to.when);
115 t2 = ns2ms_adj(e->rec->data.switch_away.when); 115 t2 = ns2ms_adj(e->rec->data.switch_away.when);
116 if (intersect(&t1, &t2, from, to)) 116 if (intersect(&t1, &t2, from, to))