Attachment 'MC2_liblitmus_ipdps15.patch'
Download 1 diff --git a/Makefile b/Makefile
2 index db94ffb..a81b010 100644
3 --- a/Makefile
4 +++ b/Makefile
5 @@ -12,14 +12,15 @@ host-arch := $(shell uname -m | \
6 ARCH ?= ${host-arch}
7
8 # LITMUS_KERNEL -- where to find the litmus kernel?
9 -LITMUS_KERNEL ?= ../litmus2010
10 +LITMUS_KERNEL ?= ../litmus-rt
11
12
13 # ##############################################################################
14 # Internal configuration.
15
16 # compiler flags
17 -flags-debug = -Wall -Werror -g -Wdeclaration-after-statement
18 +flags-debug = -Wall -g -Wdeclaration-after-statement
19 +#flags-debug = -Wall -Werror -g -Wdeclaration-after-statement
20 flags-api = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE
21
22 # architecture-specific flags
23 @@ -70,8 +71,8 @@ AR := ${CROSS_COMPILE}${AR}
24 # Targets
25
26 all = lib ${rt-apps}
27 -rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
28 - base_mt_task runtests
29 +rt-apps = cycles base_task rt_launch rtspin rtspinovr rtspin.ovh rtspin.beta \
30 + release_ts measure_syscall base_mt_task runtests monitor cycles_test
31
32 .PHONY: all lib clean dump-config TAGS tags cscope help
33
34 @@ -154,7 +155,7 @@ arch/${include-${ARCH}}/include/asm/%.h: \
35 cp $< $@
36
37 litmus-headers = include/litmus/rt_param.h include/litmus/unistd_32.h \
38 - include/litmus/unistd_64.h
39 + include/litmus/unistd_64.h include/litmus/sched_mc.h
40
41 unistd-headers = \
42 $(foreach file,${unistd-${ARCH}},arch/${include-${ARCH}}/include/asm/$(file))
43 @@ -211,11 +212,26 @@ obj-rt_launch = rt_launch.o common.o
44 obj-rtspin = rtspin.o common.o
45 lib-rtspin = -lrt
46
47 +obj-rtspinovr = rtspinovr.o common.o
48 +lib-rtspinovr = -lrt
49 +
50 +obj-rtspin.ovh = rtspin.ovh.o common.o
51 +lib-rtspin.ovh = -lrt
52 +
53 +obj-rtspin.beta = rtspin.beta.o common.o
54 +lib-rtspin.beta = -lrt $(shell gsl-config --libs)
55 +
56 obj-release_ts = release_ts.o
57
58 obj-measure_syscall = null_call.o
59 lib-measure_syscall = -lm
60
61 +obj-monitor = monitor.o common.o
62 +lib-monitor = -lrt
63 +
64 +obj-cycles_test = cycles_test.o common.o
65 +lib-cycles_test = -lrt
66 +
67 # ##############################################################################
68 # Build everything that depends on liblitmus.
69
70 diff --git a/bin/monitor.c b/bin/monitor.c
71 new file mode 100644
72 index 0000000..9c72397
73 --- /dev/null
74 +++ b/bin/monitor.c
75 @@ -0,0 +1,471 @@
76 +#include <sys/time.h>
77 +
78 +#include <stdio.h>
79 +#include <stdlib.h>
80 +#include <unistd.h>
81 +#include <time.h>
82 +#include <assert.h>
83 +#include <strings.h>
84 +#include <signal.h>
85 +#include <memory.h>
86 +
87 +#include "litmus.h"
88 +#include "common.h"
89 +#include "linkedlist.h"
90 +
91 +#include <litmus/sched_mc.h>
92 +#define CLOCK_PER_MS 2129704
93 +
94 +struct task_info {
95 + int id;
96 + double relative_pp;
97 + double tolerance;
98 + int period;
99 +};
100 +
101 +pid_t task_pid[100];
102 +struct task_info task_set[100];
103 +struct report_data report[2048];
104 +static int recovery_mode = 0;
105 +LinkedList pend_now;
106 +LinkedList pend_idle_cand;
107 +unsigned long long seq = 0;
108 +lt_t idle_cand = 0;
109 +int speed_num = 5, speed_denom = 10;
110 +int current_num, current_denom, num_jobs, num_c_jobs = 0;
111 +cycles_t time_start, time_end;
112 +lt_t t_start, t_end;
113 +int task_mapped = 0;
114 +int map_idx = 0;
115 +int num_transition = 0;
116 +cycles_t total_cycle = 0;
117 +double min_speed = 1, current_speed = 1.0;
118 +
119 +int get_task_value(pid_t pid)
120 +{
121 + int i = 0;
122 + for (i=0; i<num_c_jobs;i++)
123 + {
124 + if (task_pid[i] == pid) {
125 + return i;
126 + }
127 + }
128 + printf("Not a registered task\n");
129 + return 0;
130 +}
131 +
132 +static void usage(char *error) {
133 + fprintf(stderr, "Error: %s\n", error);
134 + fprintf(stderr,
135 + "Usage:\n"
136 + " monitor [COMMON-OPTS] WCET PERIOD DURATION\n"
137 + " monitor [COMMON-OPTS] -f TASK_INFO_FILE [-o COLUMN] WCET PERIOD\n"
138 + "\n"
139 + "COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n"
140 + " [-r CRITICALITY = [a|b|c|d]] [-i MC-LVL-A-ID]\n"
141 + "\n"
142 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n");
143 + exit(EXIT_FAILURE);
144 +}
145 +
146 +/*
147 + * returns the character that made processing stop, newline or EOF
148 + */
149 +static int skip_to_next_line(FILE *fstream)
150 +{
151 + int ch;
152 + for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
153 + return ch;
154 +}
155 +
156 +static void skip_comments(FILE *fstream)
157 +{
158 + int ch;
159 + for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
160 + skip_to_next_line(fstream);
161 + ungetc(ch, fstream);
162 +}
163 +
164 +void get_task_info(const char *file)
165 +{
166 + FILE *fstream;
167 + int cur_job, ch;
168 + int temp1, temp2, id, crit;
169 + float pp, tol;
170 + float temp3, temp4;
171 +
172 + num_jobs = 0;
173 +
174 + fstream = fopen(file, "r");
175 + if (!fstream)
176 + bail_out("could not open execution time file");
177 +
178 + /* figure out the number of jobs */
179 + do {
180 + skip_comments(fstream);
181 + ch = skip_to_next_line(fstream);
182 + if (ch != EOF)
183 + ++(num_jobs);
184 + } while (ch != EOF);
185 +
186 + if (-1 == fseek(fstream, 0L, SEEK_SET))
187 + bail_out("rewinding file failed");
188 + ch = skip_to_next_line(fstream);
189 + /* allocate space for exec times */
190 + for (cur_job = 0; cur_job < num_jobs && !feof(fstream); ++cur_job) {
191 + skip_comments(fstream);
192 +
193 + fscanf(fstream, "%d %d %d %f %f %d %f %f", &id, &temp1, &temp2, &pp, &tol, &crit, &temp3, &temp4);
194 +
195 + if (crit == 2) {
196 + task_set[num_c_jobs].id = id;
197 + task_set[num_c_jobs].relative_pp = (double)pp;
198 + task_set[num_c_jobs].tolerance = (double)tol;
199 + task_set[num_c_jobs].period = (int)temp2;
200 + num_c_jobs++;
201 + crit = 0;
202 + }
203 +
204 + skip_to_next_line(fstream);
205 + }
206 +
207 + assert(cur_job == num_jobs);
208 + fclose(fstream);
209 +}
210 +
211 +static char* progname;
212 +
213 +static int job(double exec_time, double program_end)
214 +{
215 + if (wctime() > program_end)
216 + {
217 + return 0;
218 + }
219 + else {
220 + sleep_next_period();
221 + return 1;
222 + }
223 +}
224 +
225 +enum crit_level str2crit(const char* str)
226 +{
227 + if (0 == strncasecmp("a", str, 1))
228 + return CRIT_LEVEL_A;
229 + else if (0 == strncasecmp("b", str, 1))
230 + return CRIT_LEVEL_B;
231 + else if (0 == strncasecmp("c", str, 1))
232 + return CRIT_LEVEL_C;
233 + /* failure */
234 + return NUM_CRIT_LEVELS;
235 +}
236 +inline void print_job(struct report_data data)
237 +{
238 + printf("[%llu] %d/%d release: %llu, pp: %llu, comp: %llu, queue: %d\n", data.seq, data.pid, data.job_no, data.release_time, data.priority_point, data.now, data.rq_empty);
239 +}
240 +
241 +void init_recovery(lt_t comp_time, int queue_empty)
242 +{
243 + recovery_mode = 1;
244 + if (queue_empty == 1) {
245 + idle_cand = comp_time;
246 + list_copy(&pend_idle_cand, &pend_now);
247 + }
248 + else {
249 + idle_cand = 0;
250 + pend_idle_cand.removeAll(&pend_idle_cand);
251 + }
252 +}
253 +
254 +void handle_miss_adaptive(struct report_data job, double yi, double ksi)
255 +{
256 + double new_speed;
257 + double a_factor = (double)speed_num/10.0;
258 + double a,b;
259 +
260 + if (recovery_mode == 0) {
261 + current_speed = 1.0;
262 + init_recovery(job.now, job.rq_empty);
263 + }
264 + a = (double)(a_factor*(yi+ksi));
265 + b = (double)((double)(job.now-job.release_time)/CLOCK_PER_MS);
266 + new_speed = a/b;
267 + if ( new_speed < current_speed)
268 + {
269 + current_num = (int)a;
270 + current_denom = (int)b;
271 + change_speed(current_num, current_denom);
272 + null_call(&time_start);
273 + current_speed = new_speed;
274 + min_speed = new_speed;
275 + }
276 +}
277 +
278 +void handle_miss(struct report_data job)
279 +{
280 + if (recovery_mode == 0) {
281 + change_speed(speed_num, speed_denom);
282 + null_call(&time_start);
283 + init_recovery(job.now, job.rq_empty);
284 + }
285 +}
286 +
287 +void on_job_complete(struct report_data job)
288 +{
289 + double ksi, yi;
290 +
291 + //print_job(job);
292 + pend_now.remove(&pend_now, job);
293 +
294 + ksi = task_set[get_task_value(job.pid)].tolerance * 1.0;
295 + yi = task_set[get_task_value(job.pid)].relative_pp;
296 + if (((double)(job.now - job.priority_point))/((double)CLOCK_PER_MS) > ksi && job.priority_point != 0) {
297 + //handle_miss(job);
298 + handle_miss_adaptive(job, ksi, yi);
299 + }
300 + if ((recovery_mode == 1) && (idle_cand != 0)) {
301 + if (((double)(job.now - job.priority_point))/((double)CLOCK_PER_MS) > ksi) {
302 + idle_cand = 0;
303 + pend_idle_cand.removeAll(&pend_idle_cand);
304 + }
305 + else {
306 + pend_idle_cand.remove(&pend_idle_cand, job);
307 + }
308 + }
309 +
310 + if ((recovery_mode == 1) && (idle_cand == 0) && (job.rq_empty == 1)) {
311 + idle_cand = job.now;
312 + list_copy(&pend_idle_cand, &pend_now);
313 + }
314 +
315 + if ((recovery_mode == 1) && (idle_cand != 0) && (pend_idle_cand.size == 0)) {
316 + change_speed(1,1);
317 + null_call(&time_end);
318 + num_transition++;
319 + total_cycle += time_end-time_start;
320 + recovery_mode = 0;
321 + }
322 +}
323 +
324 +void sig_handler(int n, siginfo_t *info, void *unused)
325 +{
326 + int nr_report, i;
327 + //if (info->si_int >= 1000)
328 + {
329 + get_job_report(0, &nr_report, report);
330 + if (nr_report != 0) {
331 + for (i = 0; i < nr_report; i++) {
332 + pend_now.addLast(&pend_now, report[i]);
333 + }
334 + }
335 + get_job_report(1, &nr_report, report);
336 + if (nr_report != 0) {
337 + for (i = 0; i < nr_report; i++) {
338 + pend_now.addLast(&pend_now, report[i]);
339 + }
340 + }
341 + }
342 +// else
343 + {
344 + get_job_report(2, &nr_report, report);
345 + for (i = 0; i < nr_report; i++) {
346 + // register jobs
347 + if (map_idx < num_c_jobs) {
348 + if (report[i].job_no == 3) {
349 + task_pid[map_idx] = report[i].pid;
350 + map_idx++;
351 + if (map_idx == num_c_jobs) {
352 + int j,k;
353 + // sort and flush pend_now
354 + pend_now.removeAll(&pend_now);
355 + for (j=1;j<num_c_jobs;j++)
356 + {
357 + for (k=0; k<num_c_jobs-1;k++)
358 + {
359 + if (task_pid[k] > task_pid[k+1])
360 + {
361 + pid_t t = task_pid[k];
362 + task_pid[k] = task_pid[k+1];
363 + task_pid[k+1] = t;
364 + }
365 + }
366 + }
367 + }
368 + }
369 + seq++;
370 + }
371 + else {
372 + if (report[i].seq == seq) {
373 + on_job_complete(report[i]);
374 + seq++;
375 + }
376 + else {
377 + //printf("report[%llu] != seq[%llu]\n", report[i].seq, seq);
378 + if (report[i].seq > seq)
379 + seq++;
380 + }
381 + }
382 + }
383 + }
384 +}
385 +
386 +#define OPTSTR "p:c:weo:f:s:r:i:d:"
387 +
388 +int main(int argc, char** argv)
389 +{
390 + int ret;
391 + lt_t wcet;
392 + lt_t period;
393 + double wcet_ms, period_ms;
394 + int migrate = 0;
395 + int cpu = 0;
396 + int opt;
397 + int wait = 0;
398 + const char *file = NULL;
399 + int want_enforcement = 0;
400 + double duration = 0, start;
401 + double scale = 1.0;
402 + task_class_t class = RT_CLASS_HARD;
403 + struct mc_task mc_task = { .crit = CRIT_LEVEL_C, .lvl_a_id = -1 };
404 + struct sigaction sig;
405 + int numer = 5, nr;
406 +
407 + progname = argv[0];
408 +
409 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
410 + switch (opt) {
411 + case 'w':
412 + wait = 1;
413 + break;
414 + case 'p':
415 + cpu = atoi(optarg);
416 + migrate = 1;
417 + break;
418 + case 'c':
419 + class = str2class(optarg);
420 + if (class == -1)
421 + usage("Unknown task class.");
422 + break;
423 + case 'e':
424 + want_enforcement = 1;
425 + break;
426 + case 'd':
427 + numer = atoi(optarg);
428 + break;
429 + case 'f':
430 + file = optarg;
431 + break;
432 + case 's':
433 + scale = atof(optarg);
434 + break;
435 + case 'r':
436 + mc_task.crit = str2crit(optarg);
437 + if (NUM_CRIT_LEVELS == mc_task.crit)
438 + usage("Bad crit level.");
439 + break;
440 + case 'i':
441 + mc_task.lvl_a_id = atoi(optarg);
442 + break;
443 + case ':':
444 + usage("Argument missing.");
445 + break;
446 + case '?':
447 + default:
448 + usage("Bad argument.");
449 + break;
450 + }
451 + }
452 + ret = register_pid(gettid());
453 +
454 + // flush report buffer
455 + get_job_report(0, &nr, report);
456 + get_job_report(1, &nr, report);
457 + get_job_report(2, &nr, report);
458 +
459 + if (file) {
460 + get_task_info(file);
461 + if (argc - optind < 2)
462 + usage("Arguments missing.");
463 + } else {
464 + /*
465 + * if we're not reading from the CSV file, then we need
466 + * three parameters
467 + */
468 + if (argc - optind < 3)
469 + usage("Arguments missing.");
470 + }
471 +
472 +
473 + speed_num = numer;
474 + wcet_ms = atof(argv[optind + 0]);
475 + period_ms = atof(argv[optind + 1]);
476 + wcet = wcet_ms * __NS_PER_MS;
477 + period = period_ms * __NS_PER_MS;
478 +
479 + if (wcet <= 0)
480 + usage("The worst-case execution time must be a "
481 + "positive number.");
482 + if (period <= 0)
483 + usage("The period must be a positive number.");
484 + if (!file && wcet > period) {
485 + usage("The worst-case execution time must not "
486 + "exceed the period.");
487 + }
488 +
489 + duration = atof(argv[optind + 2]);
490 +
491 + if (migrate) {
492 + ret = be_migrate_to(cpu);
493 + if (ret < 0)
494 + bail_out("could not migrate to target partition");
495 + }
496 +
497 + ret = sporadic_task_ns(wcet, period, 0, cpu, class,
498 + want_enforcement ? PRECISE_ENFORCEMENT
499 + : NO_ENFORCEMENT,
500 + migrate);
501 + if (ret < 0)
502 + bail_out("could not setup rt task params");
503 +
504 + if (NUM_CRIT_LEVELS != mc_task.crit) {
505 + ret = set_rt_task_mc_param(gettid(), &mc_task);
506 + if (ret < 0)
507 + bail_out("could not setup rt mixed criticality params");
508 + }
509 +
510 + if (ret < 0)
511 + bail_out("register pid failed");
512 + sig.sa_sigaction = sig_handler;
513 + sig.sa_flags = SA_SIGINFO;
514 +
515 + sigaction(SIGIO, &sig, NULL);
516 + pend_now = createLinkedList();
517 + pend_idle_cand = createLinkedList();
518 +
519 + init_litmus();
520 +
521 + ret = task_mode(LITMUS_RT_TASK);
522 + if (ret != 0)
523 + bail_out("could not become RT task");
524 +
525 + if (wait) {
526 + ret = wait_for_ts_release();
527 + if (ret != 0)
528 + bail_out("wait_for_ts_release()");
529 + }
530 +
531 + start = wctime();
532 +
533 + /* conver to seconds and scale */
534 + while (job(wcet_ms * 0.001 * scale, start + duration)) ;
535 +
536 + ret = task_mode(BACKGROUND_TASK);
537 + if (ret != 0)
538 + bail_out("could not become regular task (huh?)");
539 +
540 + if (num_transition != 0)
541 + printf("%llu, %f\n", (lt_t)((double)total_cycle/(double)num_transition), min_speed);
542 + else
543 + printf("0, %f\n", min_speed);
544 +
545 + return 0;
546 +}
547 diff --git a/bin/rtspin.beta.c b/bin/rtspin.beta.c
548 new file mode 100644
549 index 0000000..556660e
550 --- /dev/null
551 +++ b/bin/rtspin.beta.c
552 @@ -0,0 +1,283 @@
553 +#include <sys/time.h>
554 +
555 +#include <stdio.h>
556 +#include <stdlib.h>
557 +#include <unistd.h>
558 +#include <time.h>
559 +#include <assert.h>
560 +#include <strings.h>
561 +
562 +#include <gsl/gsl_rng.h>
563 +#include <gsl/gsl_randist.h>
564 +
565 +#include "litmus.h"
566 +#include "common.h"
567 +
568 +#include <litmus/sched_mc.h>
569 +
570 +
571 +static void usage(char *error) {
572 + fprintf(stderr, "Error: %s\n", error);
573 + fprintf(stderr,
574 + "Usage:\n"
575 + " rt_spin [COMMON-OPTS] LVL_C_TIME WCET PERIOD DURATION\n"
576 + " rt_spin -l\n"
577 + "\n"
578 + "COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n"
579 + " [-r CRITICALITY = [a|b|c|d]] [-i MC-LVL-A-ID]\n"
580 + " [-a ALPHA] [-b BETA] [-d SEED]\n"
581 + "\n"
582 + "WCET and PERIOD are nanoseconds, DURATION is seconds.\n");
583 + exit(EXIT_FAILURE);
584 +}
585 +
586 +#define NUMS 4096
587 +static int num[NUMS];
588 +static char* progname;
589 +
590 +static gsl_rng *beta_rng;
591 +static gsl_rng *coin_rng;
592 +
593 +static void setup_rng(unsigned long seed)
594 +{
595 + beta_rng = gsl_rng_alloc(gsl_rng_taus);
596 + coin_rng = gsl_rng_alloc(gsl_rng_taus);
597 + if (!beta_rng || !coin_rng)
598 + bail_out("Could not initialize RNG");
599 + gsl_rng_set(beta_rng, seed);
600 + gsl_rng_set(coin_rng, seed);
601 +}
602 +
603 +static int loop_once(void)
604 +{
605 + int i, j = 0;
606 + for (i = 0; i < NUMS; i++)
607 + j += num[i]++;
608 + return j;
609 +}
610 +
611 +static int loop_for(double exec_time, double emergency_exit)
612 +{
613 + double last_loop = 0, loop_start;
614 + int tmp = 0;
615 +
616 + double start = cputime();
617 + double now = cputime();
618 +
619 + while (now + last_loop < start + exec_time) {
620 + loop_start = now;
621 + tmp += loop_once();
622 + now = cputime();
623 + last_loop = now - loop_start;
624 + if (emergency_exit && wctime() > emergency_exit) {
625 + /* Oops --- this should only be possible if the execution time tracking
626 + * is broken in the LITMUS^RT kernel. */
627 + fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
628 + fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
629 + break;
630 + }
631 + }
632 +
633 + return tmp;
634 +}
635 +
636 +
637 +static void debug_delay_loop(void)
638 +{
639 + double start, end, delay;
640 +
641 + while (1) {
642 + for (delay = 0.5; delay > 0.01; delay -= 0.01) {
643 + start = wctime();
644 + loop_for(delay, 0);
645 + end = wctime();
646 + printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
647 + delay,
648 + end - start,
649 + end - start - delay,
650 + 100 * (end - start - delay) / delay);
651 + }
652 + }
653 +}
654 +
655 +static int job(double exec_time, double program_end)
656 +{
657 + if (wctime() > program_end)
658 + return 0;
659 + else {
660 + loop_for(exec_time, program_end + 1);
661 + sleep_next_period();
662 + return 1;
663 + }
664 +}
665 +
666 +enum crit_level str2crit(const char* str)
667 +{
668 + if (0 == strncasecmp("a", str, 1))
669 + return CRIT_LEVEL_A;
670 + else if (0 == strncasecmp("b", str, 1))
671 + return CRIT_LEVEL_B;
672 + else if (0 == strncasecmp("c", str, 1))
673 + return CRIT_LEVEL_C;
674 + /* failure */
675 + return NUM_CRIT_LEVELS;
676 +}
677 +
678 +#define OPTSTR "a:b:d:p:c:wlves:r:i:"
679 +
680 +#define COIN_PROB 0.5
681 +
682 +int main(int argc, char** argv)
683 +{
684 + int ret;
685 + lt_t wcet;
686 + lt_t period;
687 + lt_t lvl_c_time;
688 + int migrate = 0;
689 + int cpu = 0;
690 + int opt;
691 + int wait = 0;
692 + int test_loop = 0;
693 + int want_enforcement = 0;
694 + unsigned long seed = 1;
695 + double duration = 0, start;
696 + double scale = 1.0;
697 + double alpha = -1, beta = -1, beta_sample, exec_time;
698 + task_class_t class = RT_CLASS_HARD;
699 + struct mc_task mc_task = { .crit = NUM_CRIT_LEVELS, .lvl_a_id = -1 };
700 +
701 + progname = argv[0];
702 +
703 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
704 + switch (opt) {
705 + case 'a':
706 + alpha = atof(optarg);
707 + break;
708 + case 'b':
709 + beta = atof(optarg);
710 + break;
711 + case 'd':
712 + seed = atoi(optarg);
713 + break;
714 + case 'w':
715 + wait = 1;
716 + break;
717 + case 'p':
718 + cpu = atoi(optarg);
719 + migrate = 1;
720 + break;
721 + case 'c':
722 + class = str2class(optarg);
723 + if (class == -1)
724 + usage("Unknown task class.");
725 + break;
726 + case 'e':
727 + want_enforcement = 1;
728 + break;
729 + case 'l':
730 + test_loop = 1;
731 + break;
732 + case 's':
733 + scale = atof(optarg);
734 + break;
735 + case 'r':
736 + mc_task.crit = str2crit(optarg);
737 + if (NUM_CRIT_LEVELS == mc_task.crit)
738 + usage("Bad crit level.");
739 + break;
740 + case 'i':
741 + mc_task.lvl_a_id = atoi(optarg);
742 + break;
743 + case ':':
744 + usage("Argument missing.");
745 + break;
746 + case '?':
747 + default:
748 + usage("Bad argument.");
749 + break;
750 + }
751 + }
752 +
753 + if (test_loop) {
754 + debug_delay_loop();
755 + return 0;
756 + }
757 +
758 + if (argc - optind < 4)
759 + usage("Arguments missing.");
760 +
761 + lvl_c_time = atoi(argv[optind + 0]);
762 + wcet = atoi(argv[optind + 1]);
763 + period = atoi(argv[optind + 2]);
764 +
765 + if (seed < 1)
766 + usage("Seed < 1 not allowed.");
767 + if (alpha <= 0 || beta <= 0)
768 + usage("Need positive alpha and beta.");
769 + if (wcet <= 0)
770 + usage("The worst-case execution time must be a "
771 + "positive number.");
772 + if (period <= 0)
773 + usage("The period must be a positive number.");
774 + if (wcet > period) {
775 + usage("The worst-case execution time must not "
776 + "exceed the period.");
777 + }
778 +
779 + duration = atof(argv[optind + 3]);
780 +
781 + setup_rng(seed);
782 +
783 + if (migrate) {
784 + ret = be_migrate_to(cpu);
785 + if (ret < 0)
786 + bail_out("could not migrate to target partition");
787 + }
788 +
789 + ret = sporadic_task_ns(wcet, period, 0, cpu, class,
790 + want_enforcement ? PRECISE_ENFORCEMENT
791 + : NO_ENFORCEMENT,
792 + migrate);
793 + if (ret < 0)
794 + bail_out("could not setup rt task params");
795 +
796 + if (NUM_CRIT_LEVELS != mc_task.crit) {
797 + ret = set_rt_task_mc_param(gettid(), &mc_task);
798 + if (ret < 0)
799 + bail_out("could not setup rt mixed criticality params");
800 + }
801 +
802 + init_litmus();
803 +
804 + ret = task_mode(LITMUS_RT_TASK);
805 + if (ret != 0)
806 + bail_out("could not become RT task");
807 +
808 + if (wait) {
809 + ret = wait_for_ts_release();
810 + if (ret != 0)
811 + bail_out("wait_for_ts_release()");
812 + }
813 +
814 + start = wctime();
815 +
816 + do {
817 + double coin_flip = gsl_rng_uniform(coin_rng);
818 + if (coin_flip < COIN_PROB) {
819 + beta_sample = gsl_ran_beta(beta_rng, alpha, beta);
820 + exec_time = lvl_c_time * 20.0 * beta_sample * scale;
821 + } else
822 + exec_time = lvl_c_time;
823 + /* convert to seconds */
824 + exec_time = exec_time * 0.000000001;
825 + } while(job(exec_time, start + duration));
826 +
827 + ret = task_mode(BACKGROUND_TASK);
828 + if (ret != 0)
829 + bail_out("could not become regular task (huh?)");
830 +
831 + gsl_rng_free(beta_rng);
832 + gsl_rng_free(coin_rng);
833 +
834 + return 0;
835 +}
836 diff --git a/bin/rtspin.c b/bin/rtspin.c
837 index 649da45..b51924d 100644
838 --- a/bin/rtspin.c
839 +++ b/bin/rtspin.c
840 @@ -4,40 +4,101 @@
841 #include <stdlib.h>
842 #include <unistd.h>
843 #include <time.h>
844 +#include <assert.h>
845 +#include <strings.h>
846
847
848 #include "litmus.h"
849 #include "common.h"
850
851 +#include <litmus/sched_mc.h>
852
853 -static double cputime()
854 +
855 +static void usage(char *error) {
856 + fprintf(stderr, "Error: %s\n", error);
857 + fprintf(stderr,
858 + "Usage:\n"
859 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
860 + " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
861 + " rt_spin -l\n"
862 + "\n"
863 + "COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n"
864 + " [-r CRITICALITY = [a|b|c|d]] [-i MC-LVL-A-ID]\n"
865 + "\n"
866 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n");
867 + exit(EXIT_FAILURE);
868 +}
869 +
870 +/*
871 + * returns the character that made processing stop, newline or EOF
872 + */
873 +static int skip_to_next_line(FILE *fstream)
874 {
875 - struct timespec ts;
876 - int err;
877 - err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
878 - if (err != 0)
879 - perror("clock_gettime");
880 - return (ts.tv_sec + 1E-9 * ts.tv_nsec);
881 + int ch;
882 + for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
883 + return ch;
884 }
885
886 -static double wctime()
887 +static void skip_comments(FILE *fstream)
888 {
889 - struct timeval tv;
890 - gettimeofday(&tv, NULL);
891 - return (tv.tv_sec + 1E-6 * tv.tv_usec);
892 + int ch;
893 + for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
894 + skip_to_next_line(fstream);
895 + ungetc(ch, fstream);
896 }
897
898 -void usage(char *error) {
899 - fprintf(stderr, "Error: %s\n", error);
900 - fprintf(stderr,
901 - "Usage: rt_spin [-w] [-p PARTITION] [-c CLASS] WCET PERIOD DURATION\n"
902 - " rt_spin -l\n");
903 - exit(1);
904 +static void get_exec_times(const char *file, const int column,
905 + int *num_jobs, double **exec_times)
906 +{
907 + FILE *fstream;
908 + int cur_job, cur_col, ch;
909 + *num_jobs = 0;
910 +
911 + fstream = fopen(file, "r");
912 + if (!fstream)
913 + bail_out("could not open execution time file");
914 +
915 + /* figure out the number of jobs */
916 + do {
917 + skip_comments(fstream);
918 + ch = skip_to_next_line(fstream);
919 + if (ch != EOF)
920 + ++(*num_jobs);
921 + } while (ch != EOF);
922 +
923 + if (-1 == fseek(fstream, 0L, SEEK_SET))
924 + bail_out("rewinding file failed");
925 +
926 + /* allocate space for exec times */
927 + *exec_times = calloc(*num_jobs, sizeof(*exec_times));
928 + if (!*exec_times)
929 + bail_out("couldn't allocate memory");
930 +
931 + for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
932 +
933 + skip_comments(fstream);
934 +
935 + for (cur_col = 1; cur_col < column; ++cur_col) {
936 + /* discard input until we get to the column we want */
937 + fscanf(fstream, "%*s,");
938 + }
939 +
940 + /* get the desired exec. time */
941 + if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
942 + fprintf(stderr, "invalid execution time near line %d\n",
943 + cur_job);
944 + exit(EXIT_FAILURE);
945 + }
946 +
947 + skip_to_next_line(fstream);
948 + }
949 +
950 + assert(cur_job == *num_jobs);
951 + fclose(fstream);
952 }
953
954 #define NUMS 4096
955 static int num[NUMS];
956 -static double loop_length = 1.0;
957 static char* progname;
958
959 static int loop_once(void)
960 @@ -50,19 +111,17 @@ static int loop_once(void)
961
962 static int loop_for(double exec_time, double emergency_exit)
963 {
964 - double t = 0;
965 + double last_loop = 0, loop_start;
966 int tmp = 0;
967 -/* while (t + loop_length < exec_time) {
968 - tmp += loop_once();
969 - t += loop_length;
970 - }
971 -*/
972 +
973 double start = cputime();
974 double now = cputime();
975 - while (now + loop_length < start + exec_time) {
976 +
977 + while (now + last_loop < start + exec_time) {
978 + loop_start = now;
979 tmp += loop_once();
980 - t += loop_length;
981 now = cputime();
982 + last_loop = now - loop_start;
983 if (emergency_exit && wctime() > emergency_exit) {
984 /* Oops --- this should only be possible if the execution time tracking
985 * is broken in the LITMUS^RT kernel. */
986 @@ -75,50 +134,11 @@ static int loop_for(double exec_time, double emergency_exit)
987 return tmp;
988 }
989
990 -static void fine_tune(double interval)
991 -{
992 - double start, end, delta;
993 -
994 - start = wctime();
995 - loop_for(interval, 0);
996 - end = wctime();
997 - delta = (end - start - interval) / interval;
998 - if (delta != 0)
999 - loop_length = loop_length / (1 - delta);
1000 -}
1001 -
1002 -static void configure_loop(void)
1003 -{
1004 - double start;
1005 -
1006 - /* prime cache */
1007 - loop_once();
1008 - loop_once();
1009 - loop_once();
1010 -
1011 - /* measure */
1012 - start = wctime();
1013 - loop_once(); /* hope we didn't get preempted */
1014 - loop_length = wctime();
1015 - loop_length -= start;
1016 -
1017 - /* fine tune */
1018 - fine_tune(0.1);
1019 - fine_tune(0.1);
1020 - fine_tune(0.1);
1021 -}
1022 -
1023 -static void show_loop_length(void)
1024 -{
1025 - printf("%s/%d: loop_length=%f (%ldus)\n",
1026 - progname, getpid(), loop_length,
1027 - (long) (loop_length * 1000000));
1028 -}
1029
1030 static void debug_delay_loop(void)
1031 {
1032 double start, end, delay;
1033 - show_loop_length();
1034 +
1035 while (1) {
1036 for (delay = 0.5; delay > 0.01; delay -= 0.01) {
1037 start = wctime();
1038 @@ -144,9 +164,21 @@ static int job(double exec_time, double program_end)
1039 }
1040 }
1041
1042 -#define OPTSTR "p:c:wld:ve"
1043 +enum crit_level str2crit(const char* str)
1044 +{
1045 + if (0 == strncasecmp("a", str, 1))
1046 + return CRIT_LEVEL_A;
1047 + else if (0 == strncasecmp("b", str, 1))
1048 + return CRIT_LEVEL_B;
1049 + else if (0 == strncasecmp("c", str, 1))
1050 + return CRIT_LEVEL_C;
1051 + /* failure */
1052 + return NUM_CRIT_LEVELS;
1053 +}
1054 +
1055 +#define OPTSTR "p:c:wlveo:f:s:r:i:"
1056
1057 -int main(int argc, char** argv)
1058 +int main(int argc, char** argv)
1059 {
1060 int ret;
1061 lt_t wcet;
1062 @@ -157,11 +189,15 @@ int main(int argc, char** argv)
1063 int opt;
1064 int wait = 0;
1065 int test_loop = 0;
1066 - int skip_config = 0;
1067 - int verbose = 0;
1068 + int column = 1;
1069 + const char *file = NULL;
1070 int want_enforcement = 0;
1071 - double duration, start;
1072 + double duration = 0, start;
1073 + double *exec_times = NULL;
1074 + double scale = 1.0;
1075 task_class_t class = RT_CLASS_HARD;
1076 + int cur_job, num_jobs;
1077 + struct mc_task mc_task = { .crit = NUM_CRIT_LEVELS, .lvl_a_id = -1 };
1078
1079 progname = argv[0];
1080
1081 @@ -185,14 +221,22 @@ int main(int argc, char** argv)
1082 case 'l':
1083 test_loop = 1;
1084 break;
1085 - case 'd':
1086 - /* manually configure delay per loop iteration
1087 - * unit: microseconds */
1088 - loop_length = atof(optarg) / 1000000;
1089 - skip_config = 1;
1090 + case 'o':
1091 + column = atoi(optarg);
1092 + break;
1093 + case 'f':
1094 + file = optarg;
1095 + break;
1096 + case 's':
1097 + scale = atof(optarg);
1098 + break;
1099 + case 'r':
1100 + mc_task.crit = str2crit(optarg);
1101 + if (NUM_CRIT_LEVELS == mc_task.crit)
1102 + usage("Bad crit level.");
1103 break;
1104 - case 'v':
1105 - verbose = 1;
1106 + case 'i':
1107 + mc_task.lvl_a_id = atoi(optarg);
1108 break;
1109 case ':':
1110 usage("Argument missing.");
1111 @@ -204,32 +248,50 @@ int main(int argc, char** argv)
1112 }
1113 }
1114
1115 -
1116 - if (!skip_config)
1117 - configure_loop();
1118 -
1119 if (test_loop) {
1120 debug_delay_loop();
1121 return 0;
1122 }
1123
1124 - if (argc - optind < 3)
1125 - usage("Arguments missing.");
1126 + if (file) {
1127 + get_exec_times(file, column, &num_jobs, &exec_times);
1128 +
1129 + if (argc - optind < 1)
1130 + usage("Arguments missing.");
1131 +
1132 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
1133 + /* convert the execution time to seconds */
1134 + duration += exec_times[cur_job] * 0.001;
1135 + }
1136 + } else {
1137 + /*
1138 + * if we're not reading from the CSV file, then we need
1139 + * three parameters
1140 + */
1141 + if (argc - optind < 3)
1142 + usage("Arguments missing.");
1143 + }
1144 +
1145 wcet_ms = atof(argv[optind + 0]);
1146 period_ms = atof(argv[optind + 1]);
1147 - duration = atof(argv[optind + 2]);
1148 +
1149 wcet = wcet_ms * __NS_PER_MS;
1150 period = period_ms * __NS_PER_MS;
1151 if (wcet <= 0)
1152 usage("The worst-case execution time must be a "
1153 - "positive number.");
1154 + "positive number.");
1155 if (period <= 0)
1156 usage("The period must be a positive number.");
1157 - if (wcet > period) {
1158 + if (!file && wcet > period) {
1159 usage("The worst-case execution time must not "
1160 - "exceed the period.");
1161 + "exceed the period.");
1162 }
1163
1164 + if (!file)
1165 + duration = atof(argv[optind + 2]);
1166 + else if (file && num_jobs > 1)
1167 + duration += period_ms * 0.001 * (num_jobs - 1);
1168 +
1169 if (migrate) {
1170 ret = be_migrate_to(cpu);
1171 if (ret < 0)
1172 @@ -240,12 +302,14 @@ int main(int argc, char** argv)
1173 want_enforcement ? PRECISE_ENFORCEMENT
1174 : NO_ENFORCEMENT,
1175 migrate);
1176 -
1177 if (ret < 0)
1178 bail_out("could not setup rt task params");
1179
1180 - if (verbose)
1181 - show_loop_length();
1182 + if (NUM_CRIT_LEVELS != mc_task.crit) {
1183 + ret = set_rt_task_mc_param(gettid(), &mc_task);
1184 + if (ret < 0)
1185 + bail_out("could not setup rt mixed criticality params");
1186 + }
1187
1188 init_litmus();
1189
1190 @@ -261,12 +325,24 @@ int main(int argc, char** argv)
1191
1192 start = wctime();
1193
1194 - /* 90% wcet, in seconds */
1195 - while (job(wcet_ms * 0.0009, start + duration));
1196 + if (file) {
1197 + /* use times read from the CSV file */
1198 + for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
1199 + /* convert job's length to seconds */
1200 + job(exec_times[cur_job] * 0.001 * scale,
1201 + start + duration);
1202 + }
1203 + } else {
1204 + /* conver to seconds and scale */
1205 + while (job(wcet_ms * 0.001 * scale, start + duration));
1206 + }
1207
1208 ret = task_mode(BACKGROUND_TASK);
1209 if (ret != 0)
1210 bail_out("could not become regular task (huh?)");
1211
1212 + if (file)
1213 + free(exec_times);
1214 +
1215 return 0;
1216 }
1217 diff --git a/bin/rtspin.ovh.c b/bin/rtspin.ovh.c
1218 new file mode 100644
1219 index 0000000..d130eac
1220 --- /dev/null
1221 +++ b/bin/rtspin.ovh.c
1222 @@ -0,0 +1,239 @@
1223 +#include <sys/time.h>
1224 +
1225 +#include <stdio.h>
1226 +#include <stdlib.h>
1227 +#include <unistd.h>
1228 +#include <time.h>
1229 +#include <assert.h>
1230 +#include <strings.h>
1231 +
1232 +
1233 +#include "litmus.h"
1234 +#include "common.h"
1235 +
1236 +#include <litmus/sched_mc.h>
1237 +
1238 +
1239 +static void usage(char *error) {
1240 + fprintf(stderr, "Error: %s\n", error);
1241 + fprintf(stderr,
1242 + "Usage:\n"
1243 + " rt_spin [COMMON-OPTS] EXEC_TIME WCET PERIOD DURATION\n"
1244 + " rt_spin -l\n"
1245 + "\n"
1246 + "COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n"
1247 + " [-r CRITICALITY = [a|b|c|d]] [-i MC-LVL-A-ID]\n"
1248 + "\n"
1249 + "WCET and PERIOD are nanoseconds, DURATION is seconds.\n");
1250 + exit(EXIT_FAILURE);
1251 +}
1252 +
1253 +#define NUMS 4096
1254 +static int num[NUMS];
1255 +static char* progname;
1256 +
1257 +static int loop_once(void)
1258 +{
1259 + int i, j = 0;
1260 + for (i = 0; i < NUMS; i++)
1261 + j += num[i]++;
1262 + return j;
1263 +}
1264 +
1265 +static int loop_for(double exec_time, double emergency_exit)
1266 +{
1267 + double last_loop = 0, loop_start;
1268 + int tmp = 0;
1269 +
1270 + double start = cputime();
1271 + double now = cputime();
1272 +
1273 + while (now + last_loop < start + exec_time) {
1274 + loop_start = now;
1275 + tmp += loop_once();
1276 + now = cputime();
1277 + last_loop = now - loop_start;
1278 + if (emergency_exit && wctime() > emergency_exit) {
1279 + /* Oops --- this should only be possible if the execution time tracking
1280 + * is broken in the LITMUS^RT kernel. */
1281 + fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
1282 + fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
1283 + break;
1284 + }
1285 + }
1286 +
1287 + return tmp;
1288 +}
1289 +
1290 +
1291 +static void debug_delay_loop(void)
1292 +{
1293 + double start, end, delay;
1294 +
1295 + while (1) {
1296 + for (delay = 0.5; delay > 0.01; delay -= 0.01) {
1297 + start = wctime();
1298 + loop_for(delay, 0);
1299 + end = wctime();
1300 + printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
1301 + delay,
1302 + end - start,
1303 + end - start - delay,
1304 + 100 * (end - start - delay) / delay);
1305 + }
1306 + }
1307 +}
1308 +
1309 +static int job(double exec_time, double program_end)
1310 +{
1311 + if (wctime() > program_end)
1312 + return 0;
1313 + else {
1314 + loop_for(exec_time, program_end + 1);
1315 + sleep_next_period();
1316 + return 1;
1317 + }
1318 +}
1319 +
1320 +enum crit_level str2crit(const char* str)
1321 +{
1322 + if (0 == strncasecmp("a", str, 1))
1323 + return CRIT_LEVEL_A;
1324 + else if (0 == strncasecmp("b", str, 1))
1325 + return CRIT_LEVEL_B;
1326 + else if (0 == strncasecmp("c", str, 1))
1327 + return CRIT_LEVEL_C;
1328 + /* failure */
1329 + return NUM_CRIT_LEVELS;
1330 +}
1331 +
1332 +#define OPTSTR "p:c:wlves:r:i:"
1333 +
1334 +int main(int argc, char** argv)
1335 +{
1336 + int ret;
1337 + lt_t exec_time;
1338 + lt_t wcet;
1339 + lt_t period;
1340 + int migrate = 0;
1341 + int cpu = 0;
1342 + int opt;
1343 + int wait = 0;
1344 + int test_loop = 0;
1345 + int want_enforcement = 0;
1346 + double duration = 0, start;
1347 + double scale = 1.0;
1348 + task_class_t class = RT_CLASS_HARD;
1349 + struct mc_task mc_task = { .crit = NUM_CRIT_LEVELS, .lvl_a_id = -1 };
1350 +
1351 + progname = argv[0];
1352 +
1353 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1354 + switch (opt) {
1355 + case 'w':
1356 + wait = 1;
1357 + break;
1358 + case 'p':
1359 + cpu = atoi(optarg);
1360 + migrate = 1;
1361 + break;
1362 + case 'c':
1363 + class = str2class(optarg);
1364 + if (class == -1)
1365 + usage("Unknown task class.");
1366 + break;
1367 + case 'e':
1368 + want_enforcement = 1;
1369 + break;
1370 + case 'l':
1371 + test_loop = 1;
1372 + break;
1373 + case 's':
1374 + scale = atof(optarg);
1375 + break;
1376 + case 'r':
1377 + mc_task.crit = str2crit(optarg);
1378 + if (NUM_CRIT_LEVELS == mc_task.crit)
1379 + usage("Bad crit level.");
1380 + break;
1381 + case 'i':
1382 + mc_task.lvl_a_id = atoi(optarg);
1383 + break;
1384 + case ':':
1385 + usage("Argument missing.");
1386 + break;
1387 + case '?':
1388 + default:
1389 + usage("Bad argument.");
1390 + break;
1391 + }
1392 + }
1393 +
1394 + if (test_loop) {
1395 + debug_delay_loop();
1396 + return 0;
1397 + }
1398 +
1399 + if (argc - optind < 4)
1400 + usage("Arguments missing.");
1401 +
1402 + exec_time = atoi(argv[optind + 0]);
1403 + wcet = atoi(argv[optind + 1]);
1404 + period = atoi(argv[optind + 2]);
1405 +
1406 + if (exec_time <= 0 || exec_time > period)
1407 + usage("bad execution time");
1408 + if (wcet <= 0)
1409 + usage("The worst-case execution time must be a "
1410 + "positive number.");
1411 + if (period <= 0)
1412 + usage("The period must be a positive number.");
1413 + if (wcet > period) {
1414 + usage("The worst-case execution time must not "
1415 + "exceed the period.");
1416 + }
1417 +
1418 + duration = atof(argv[optind + 3]);
1419 +
1420 + if (migrate) {
1421 + ret = be_migrate_to(cpu);
1422 + if (ret < 0)
1423 + bail_out("could not migrate to target partition");
1424 + }
1425 +
1426 + ret = sporadic_task_ns(wcet, period, 0, cpu, class,
1427 + want_enforcement ? PRECISE_ENFORCEMENT
1428 + : NO_ENFORCEMENT,
1429 + migrate);
1430 + if (ret < 0)
1431 + bail_out("could not setup rt task params");
1432 +
1433 + if (NUM_CRIT_LEVELS != mc_task.crit) {
1434 + ret = set_rt_task_mc_param(gettid(), &mc_task);
1435 + if (ret < 0)
1436 + bail_out("could not setup rt mixed criticality params");
1437 + }
1438 +
1439 + init_litmus();
1440 +
1441 + ret = task_mode(LITMUS_RT_TASK);
1442 + if (ret != 0)
1443 + bail_out("could not become RT task");
1444 +
1445 + if (wait) {
1446 + ret = wait_for_ts_release();
1447 + if (ret != 0)
1448 + bail_out("wait_for_ts_release()");
1449 + }
1450 +
1451 + start = wctime();
1452 +
1453 + /* conver to seconds and scale */
1454 + while (job(exec_time * 0.000000001 * scale, start + duration));
1455 +
1456 + ret = task_mode(BACKGROUND_TASK);
1457 + if (ret != 0)
1458 + bail_out("could not become regular task (huh?)");
1459 +
1460 + return 0;
1461 +}
1462 diff --git a/bin/rtspinovr.c b/bin/rtspinovr.c
1463 new file mode 100644
1464 index 0000000..df7004a
1465 --- /dev/null
1466 +++ b/bin/rtspinovr.c
1467 @@ -0,0 +1,365 @@
1468 +#include <sys/time.h>
1469 +
1470 +#include <stdio.h>
1471 +#include <stdlib.h>
1472 +#include <unistd.h>
1473 +#include <time.h>
1474 +#include <assert.h>
1475 +#include <strings.h>
1476 +
1477 +
1478 +#include "litmus.h"
1479 +#include "common.h"
1480 +
1481 +#include <litmus/sched_mc.h>
1482 +
1483 +#define max(a,b) \
1484 + ({ __typeof__ (a) _a = (a); \
1485 + __typeof__ (b) _b = (b); \
1486 + _a > _b ? _a : _b; })
1487 +
1488 +int migrate = 0;
1489 +int cpu = 0;
1490 +int want_enforcement = 0;
1491 +double wcet_ms, period_ms, over_wcet_ms = 0, real_wcet_b = 0, real_wcet_b_ms;
1492 +struct mc_task mc_task = { .crit = NUM_CRIT_LEVELS, .lvl_a_id = -1 };
1493 +
1494 +static void usage(char *error) {
1495 + fprintf(stderr, "Error: %s\n", error);
1496 + fprintf(stderr,
1497 + "Usage:\n"
1498 + " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
1499 + " rt_spin [COMMON-OPTS] -f FILE WCET PERIOD\n"
1500 + " rt_spin -l\n"
1501 + "\n"
1502 + "COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n"
1503 + " [-r CRITICALITY = [a|b|c|d]] [-i MC-LVL-A-ID]\n"
1504 + " [-v OVERRUN_START]"
1505 + "\n"
1506 + "WCET and PERIOD are milliseconds, DURATION is seconds.\n");
1507 + exit(EXIT_FAILURE);
1508 +}
1509 +
1510 +/*
1511 + * returns the character that made processing stop, newline or EOF
1512 + */
1513 +static int skip_to_next_line(FILE *fstream)
1514 +{
1515 + int ch;
1516 + for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
1517 + return ch;
1518 +}
1519 +
1520 +static void skip_comments(FILE *fstream)
1521 +{
1522 + int ch;
1523 + for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
1524 + skip_to_next_line(fstream);
1525 + ungetc(ch, fstream);
1526 +}
1527 +
1528 +void get_task_info(const char *file, int my_id)
1529 +{
1530 + FILE *fstream;
1531 + int cur_job, ch;
1532 + int temp1, temp2, id, crit;
1533 + float pp, tol;
1534 + float wcet_b, wcet_c;
1535 +
1536 + int num_jobs = 0;
1537 +
1538 + fstream = fopen(file, "r");
1539 + if (!fstream)
1540 + bail_out("could not open execution time file");
1541 +
1542 + /* figure out the number of jobs */
1543 + do {
1544 + skip_comments(fstream);
1545 + ch = skip_to_next_line(fstream);
1546 + if (ch != EOF)
1547 + ++(num_jobs);
1548 + } while (ch != EOF);
1549 +
1550 + if (-1 == fseek(fstream, 0L, SEEK_SET))
1551 + bail_out("rewinding file failed");
1552 +
1553 + ch = skip_to_next_line(fstream);
1554 + /* allocate space for exec times */
1555 + for (cur_job = 0; cur_job < num_jobs && !feof(fstream); ++cur_job) {
1556 + skip_comments(fstream);
1557 +
1558 + fscanf(fstream, "%d %d %d %f %f %d %f %f", &id, &temp1, &temp2, &pp, &tol, &crit, &wcet_b, &wcet_c);
1559 + if (id == my_id)
1560 + {
1561 + cpu = temp1;
1562 + wcet_ms = wcet_c;
1563 + period_ms = (double)temp2;
1564 + over_wcet_ms = wcet_b;
1565 + real_wcet_b_ms = wcet_b;
1566 + if (crit == 1) {
1567 + mc_task.crit = CRIT_LEVEL_B;
1568 + migrate = 1;
1569 + real_wcet_b_ms = wcet_b;
1570 + want_enforcement = 1;
1571 + }
1572 + else if (crit == 2) {
1573 + mc_task.crit = CRIT_LEVEL_C;
1574 + over_wcet_ms = period_ms;
1575 + real_wcet_b_ms = period_ms;
1576 + }
1577 + break;
1578 + }
1579 + skip_to_next_line(fstream);
1580 + }
1581 +
1582 + fclose(fstream);
1583 +}
1584 +
1585 +
1586 +#define NUMS 4096
1587 +static int num[NUMS];
1588 +static char* progname;
1589 +
1590 +static int loop_once(void)
1591 +{
1592 + int i, j = 0;
1593 + for (i = 0; i < NUMS; i++)
1594 + j += num[i]++;
1595 + return j;
1596 +}
1597 +
1598 +static int loop_for(double exec_time, double emergency_exit)
1599 +{
1600 + double last_loop = 0, loop_start;
1601 + int tmp = 0;
1602 +
1603 + double start = cputime();
1604 + double now = cputime();
1605 +
1606 + while (now + last_loop < start + exec_time) {
1607 + loop_start = now;
1608 + tmp += loop_once();
1609 + now = cputime();
1610 + last_loop = now - loop_start;
1611 +
1612 + if (emergency_exit && wctime() > emergency_exit) {
1613 + fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
1614 + fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
1615 + break;
1616 + }
1617 + }
1618 +
1619 + return tmp;
1620 +}
1621 +
1622 +
1623 +static void debug_delay_loop(void)
1624 +{
1625 + double start, end, delay;
1626 +
1627 + while (1) {
1628 + for (delay = 0.5; delay > 0.01; delay -= 0.01) {
1629 + start = wctime();
1630 + loop_for(delay, 0);
1631 + end = wctime();
1632 + printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
1633 + delay,
1634 + end - start,
1635 + end - start - delay,
1636 + 100 * (end - start - delay) / delay);
1637 + }
1638 + }
1639 +}
1640 +
1641 +static int job(double exec_time, double program_end)
1642 +{
1643 + if (wctime() > program_end)
1644 + return 0;
1645 + else {
1646 + loop_for(exec_time, program_end + 1);
1647 + sleep_next_period();
1648 + return 1;
1649 + }
1650 +}
1651 +
1652 +enum crit_level str2crit(const char* str)
1653 +{
1654 + if (0 == strncasecmp("a", str, 1))
1655 + return CRIT_LEVEL_A;
1656 + else if (0 == strncasecmp("b", str, 1))
1657 + return CRIT_LEVEL_B;
1658 + else if (0 == strncasecmp("c", str, 1))
1659 + return CRIT_LEVEL_C;
1660 + /* failure */
1661 + return NUM_CRIT_LEVELS;
1662 +}
1663 +
1664 +#define OPTSTR "p:c:wle:f:s:r:i:v:j:d:"
1665 +
1666 +int main(int argc, char** argv)
1667 +{
1668 + int ret;
1669 + lt_t wcet;
1670 + lt_t period;
1671 + lt_t over_wcet;
1672 + double prev_wcet_ms;
1673 +
1674 + int opt;
1675 + int wait = 0;
1676 + int test_loop = 0;
1677 + const char *file = NULL;
1678 + double duration = 0, start;
1679 + double *exec_times = NULL;
1680 + double scale = 1.0;
1681 + task_class_t class = RT_CLASS_HARD;
1682 + int my_id;
1683 + int overloaded = 0;
1684 + double overload_start = 0.0;
1685 +
1686 + progname = argv[0];
1687 +
1688 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1689 + switch (opt) {
1690 + case 'w':
1691 + wait = 1;
1692 + break;
1693 + case 'p':
1694 + cpu = atoi(optarg);
1695 + migrate = 1;
1696 + break;
1697 + case 'c':
1698 + class = str2class(optarg);
1699 + if (class == -1)
1700 + usage("Unknown task class.");
1701 + break;
1702 + case 'e':
1703 + want_enforcement = 1;
1704 + break;
1705 + case 'l':
1706 + test_loop = 1;
1707 + break;
1708 + case 'f':
1709 + file = optarg;
1710 + break;
1711 + case 's':
1712 + scale = atof(optarg);
1713 + break;
1714 + case 'r':
1715 + mc_task.crit = str2crit(optarg);
1716 + if (NUM_CRIT_LEVELS == mc_task.crit)
1717 + usage("Bad crit level.");
1718 + break;
1719 + case 'i':
1720 + my_id = atoi(optarg);
1721 + break;
1722 + case 'v':
1723 + overload_start = atoi(optarg);
1724 + break;
1725 + case ':':
1726 + usage("Argument missing.");
1727 + break;
1728 + case '?':
1729 + default:
1730 + usage("Bad argument.");
1731 + break;
1732 + }
1733 + }
1734 +
1735 + if (test_loop) {
1736 + debug_delay_loop();
1737 + return 0;
1738 + }
1739 +
1740 + if (file) {
1741 + get_task_info(file, my_id);
1742 + }
1743 +
1744 + prev_wcet_ms = wcet_ms;
1745 + wcet = wcet_ms * __NS_PER_MS;
1746 + period = period_ms * __NS_PER_MS;
1747 + if (over_wcet_ms == 0)
1748 + over_wcet = wcet_ms * __NS_PER_MS;
1749 + else
1750 + over_wcet = over_wcet_ms * __NS_PER_MS;
1751 + real_wcet_b = real_wcet_b_ms * __NS_PER_MS;
1752 + if (wcet <= 0)
1753 + usage("The worst-case execution time must be a "
1754 + "positive number.");
1755 + if (period <= 0)
1756 + usage("The period must be a positive number.");
1757 + if (over_wcet <= 0)
1758 + usage("The overrun worst-case execution time must be a "
1759 + "positive number.");
1760 + if (!file && wcet > period) {
1761 + usage("The worst-case execution time must not "
1762 + "exceed the period.");
1763 + }
1764 +
1765 + duration = atof(argv[optind]);
1766 +
1767 + if (migrate) {
1768 + ret = be_migrate_to(cpu);
1769 + if (ret < 0)
1770 + bail_out("could not migrate to target partition");
1771 + }
1772 +
1773 + ret = sporadic_task_ns(over_wcet, period, 0, cpu, class,
1774 + want_enforcement ? PRECISE_ENFORCEMENT
1775 + : NO_ENFORCEMENT,
1776 + migrate);
1777 + if (ret < 0)
1778 + bail_out("could not setup rt task params");
1779 +
1780 + if (NUM_CRIT_LEVELS != mc_task.crit) {
1781 + ret = set_rt_task_mc_param(gettid(), &mc_task);
1782 + if (ret < 0)
1783 + bail_out("could not setup rt mixed criticality params");
1784 + }
1785 +
1786 + init_litmus();
1787 + ret = task_mode(LITMUS_RT_TASK);
1788 + if (ret != 0)
1789 + bail_out("could not become RT task");
1790 +
1791 + if (wait) {
1792 + ret = wait_for_ts_release();
1793 + if (ret != 0)
1794 + bail_out("wait_for_ts_release()");
1795 + }
1796 +
1797 + start = wctime();
1798 +
1799 +
1800 + /* conver to seconds and scale */
1801 + while (job(wcet_ms * 0.001 * scale, start + duration))
1802 + {
1803 + if (wctime() - start > overload_start && overloaded < 1) {
1804 + wcet_ms = over_wcet_ms;
1805 + overloaded = 1;
1806 + }
1807 + if ((wctime() - start > overload_start + 0.5) &&
1808 + (overloaded == 1)) {
1809 + wcet_ms = prev_wcet_ms;
1810 + }
1811 +/*
1812 + if ((wctime() - start > overload_start + 1.5) &&
1813 + (overloaded == 1)) {
1814 + wcet_ms = over_wcet_ms;
1815 + overloaded = 2;
1816 + }
1817 + if ((wctime() - start > overload_start + 2) &&
1818 + (overloaded == 2)) {
1819 + wcet_ms = prev_wcet_ms;
1820 + }
1821 +*/
1822 + }
1823 +
1824 + ret = task_mode(BACKGROUND_TASK);
1825 + if (ret != 0)
1826 + bail_out("could not become regular task (huh?)");
1827 +
1828 + if (file)
1829 + free(exec_times);
1830 +
1831 + return 0;
1832 +}
1833 diff --git a/include/linkedlist.h b/include/linkedlist.h
1834 new file mode 100644
1835 index 0000000..028d10f
1836 --- /dev/null
1837 +++ b/include/linkedlist.h
1838 @@ -0,0 +1,239 @@
1839 +#include <stdio.h>
1840 +#include <stdarg.h>
1841 +#include <stdlib.h>
1842 +
1843 +#include "litmus/rt_param.h"
1844 +
1845 +typedef struct Node {
1846 + struct report_data item;
1847 + // previous node
1848 + struct Node* prev;
1849 + // next node
1850 + struct Node* next;
1851 +} Node;
1852 +
1853 +typedef struct LinkedList {
1854 + Node* head;
1855 + Node* tail;
1856 + // size of this LinkedList
1857 + int size;
1858 +
1859 + // add item after tail
1860 + void (*addLast) (struct LinkedList*, struct report_data);
1861 + // get item from any position
1862 + struct report_data (*get) (struct LinkedList*, int);
1863 +
1864 + // remove item from any position
1865 + void (*remove) (struct LinkedList*, struct report_data);
1866 + // remove all
1867 + void (*removeAll) (struct LinkedList*);
1868 +
1869 + // display all element in the LinkedList
1870 + void (*display) (struct LinkedList*);
1871 + // create a node with item
1872 + Node* (*createNode) (struct report_data);
1873 +} LinkedList;
1874 +
1875 +/** add item to tail
1876 + */
1877 +void addLast (LinkedList* _this, struct report_data item);
1878 +/** get item from specific position
1879 + */
1880 +struct report_data get (LinkedList* _this, int position);
1881 +/** get item and remove it from any position
1882 + */
1883 +void _remove (LinkedList* _this, struct report_data data);
1884 +void _removeAll(LinkedList* _this);
1885 +/** display the items in the list
1886 + */
1887 +void display (LinkedList* _this);
1888 +/** create a LinkedList
1889 + */
1890 +LinkedList createLinkedList ();
1891 +/** create a Node
1892 + */
1893 +Node* createNode (struct report_data item);
1894 +
1895 +/** add item to tail
1896 + */
1897 +void addLast (LinkedList* _this, struct report_data item) {
1898 + Node* newNode = _this->createNode(item);
1899 + int is_exist = 0;
1900 + // list is empty
1901 + if (_this->head == NULL) {
1902 + _this->head = newNode;
1903 + newNode->next = NULL;
1904 + newNode->prev = newNode;
1905 + _this->size = 1;
1906 + return;
1907 + }
1908 + else { // has item(s)
1909 + Node* curNode = _this->head;;
1910 + while(curNode->next != NULL) {
1911 + if (item.pid == curNode->item.pid && item.job_no == curNode->item.job_no)
1912 + is_exist = 1;
1913 + curNode = curNode->next;
1914 + }
1915 + if (is_exist == 1) {
1916 + //printf("%d/%d is already in the list\n", item.pid, item.job_no);
1917 + free(newNode);
1918 + return;
1919 + }
1920 + curNode->next = newNode;
1921 + newNode->prev = curNode;
1922 + newNode->next = NULL;
1923 + _this->size++;
1924 + return;
1925 + }
1926 + return;
1927 +}
1928 +
1929 +/** get item from specific position
1930 + */
1931 +struct report_data get(LinkedList* _this, int position) {
1932 +
1933 + Node* node;
1934 + int i = 0;
1935 +
1936 + // list is empty
1937 + if (_this->size == 0) {
1938 + //printf("LinkedList#get: The list is empty.");
1939 + //system("PAUSE");
1940 + exit(0);
1941 + } else if (position >= _this->size) {
1942 + // out of bound
1943 + //printf("LinkedList#get: Index out of bound");
1944 + //system("PAUSE");
1945 + exit(0);
1946 + }
1947 + node = _this->head;
1948 + // loop until position
1949 + while (i < position) {
1950 + node = node->next;
1951 + i++;
1952 + }
1953 + return node->item;
1954 +}
1955 +
1956 +void list_copy (struct LinkedList* dst, struct LinkedList* src)
1957 +{
1958 + struct report_data item;
1959 + int i;
1960 +
1961 + if (dst->size != 0)
1962 + dst->removeAll(dst);
1963 +
1964 + if (src->size == 0) {
1965 + return;
1966 + }
1967 +
1968 + for (i=0; i< src->size; i++) {
1969 + item = src->get(src, i);
1970 + //printf("add %d/%d to dst\n", item.pid, item.job_no);
1971 + dst->addLast(dst, item);
1972 + }
1973 + return;
1974 +}
1975 +
1976 +/** get item and remove it from any position
1977 + */
1978 +void _remove (LinkedList* _this, struct report_data data)
1979 +{
1980 + Node* node = _this->head;
1981 +
1982 + // list is empty
1983 + if (_this->size == 0) {
1984 + return;
1985 + }
1986 +
1987 + // head
1988 + if (data.pid == node->item.pid && data.job_no == node->item.job_no) {
1989 + _this->head = node->next;
1990 + if (node->next != NULL)
1991 + _this->head->prev = _this->head;
1992 + _this->size--;
1993 + return;
1994 + }
1995 +
1996 + while (data.pid != node->item.pid || data.job_no != node->item.job_no) {
1997 + node = node->next;
1998 + if (node == NULL) {
1999 + return;
2000 + }
2001 + }
2002 + if (node->next == NULL) {
2003 + node->prev->next = NULL;
2004 + free(node);
2005 + _this->size--;
2006 + return;
2007 + }
2008 +
2009 + node->prev->next = node->next;
2010 + node->next->prev = node->prev;
2011 + free(node);
2012 + _this->size--;
2013 + return;
2014 +}
2015 +
2016 +void _removeAll (LinkedList* _this)
2017 +{
2018 + Node* node;
2019 + Node* nextNode;
2020 +
2021 + // list is empty
2022 + if (_this->size == 0) {
2023 + return;
2024 + }
2025 + node = _this->head;
2026 + while (node->next != NULL) {
2027 + nextNode = node->next;
2028 + free(node);
2029 + node = nextNode;
2030 + }
2031 + _this->head = NULL;
2032 + _this->size = 0;
2033 + return;
2034 +}
2035 +
2036 +/** display the items in the list
2037 + */
2038 +void display (LinkedList* _this) {
2039 + int i, size = _this->size;
2040 + if (size == 0)
2041 + printf("has 0 item\n");
2042 + else {
2043 + Node* node = _this->head;
2044 + printf("has %d items\n", size);
2045 +
2046 + for (i = 0; i < size; i++) {
2047 + if (i > 0)
2048 + printf(", ");
2049 + printf("%d/%d", node->item.pid, node->item.job_no);
2050 + node = node->next;
2051 + }
2052 + printf("\n");
2053 + }
2054 +}
2055 +/** create a LinkedList
2056 + */
2057 +LinkedList createLinkedList () {
2058 + LinkedList list;
2059 + list.head = NULL;
2060 + list.tail = NULL;
2061 + list.addLast = &addLast;
2062 + list.remove = &_remove;
2063 + list.removeAll = &_removeAll;
2064 + list.display = &display;
2065 + list.createNode = &createNode;
2066 + list.size = 0;
2067 + return list;
2068 +}
2069 +/** create a Node
2070 + */
2071 +Node* createNode (struct report_data item) {
2072 + Node* node = (Node*) malloc (sizeof(Node));
2073 + node->item = item;
2074 + node->prev = NULL;
2075 + node->next = NULL;
2076 + return node;
2077 +}
2078 \ No newline at end of file
2079 diff --git a/include/litmus.h b/include/litmus.h
2080 index 2a26a4a..2b82212 100644
2081 --- a/include/litmus.h
2082 +++ b/include/litmus.h
2083 @@ -6,6 +6,7 @@ extern "C" {
2084 #endif
2085
2086 #include <sys/types.h>
2087 +#include <stdint.h>
2088
2089 /* Include kernel header.
2090 * This is required for the rt_param
2091 @@ -25,6 +26,12 @@ int be_migrate_to(int target_cpu);
2092
2093 int set_rt_task_param(pid_t pid, struct rt_task* param);
2094 int get_rt_task_param(pid_t pid, struct rt_task* param);
2095 +int register_pid(pid_t pid);
2096 +int get_job_report(int type, int *num_report, struct report_data *param);
2097 +int change_speed(int num, int denom);
2098 +
2099 +struct mc_task;
2100 +int set_rt_task_mc_param(pid_t pid, struct mc_task *param);
2101
2102 /* setup helper */
2103
2104 @@ -60,13 +67,9 @@ static inline int od_open(int fd, obj_type_t type, int obj_id)
2105 return od_openx(fd, type, obj_id, 0);
2106 }
2107
2108 -/* FMLP binary semaphore support */
2109 -int fmlp_down(int od);
2110 -int fmlp_up(int od);
2111 -
2112 -/* SRP binary semaphore support */
2113 -int srp_down(int od);
2114 -int srp_up(int od);
2115 +/* real-time locking protocol support */
2116 +int litmus_lock(int od);
2117 +int litmus_unlock(int od);
2118
2119 /* job control*/
2120 int get_job_no(unsigned int* job_no);
2121 @@ -111,6 +114,12 @@ static inline lt_t ms2lt(unsigned long milliseconds)
2122 return __NS_PER_MS * milliseconds;
2123 }
2124
2125 +/* CPU time consumed so far in seconds */
2126 +double cputime(void);
2127 +
2128 +/* wall-clock time in seconds */
2129 +double wctime(void);
2130 +
2131 /* semaphore allocation */
2132
2133 static inline int open_fmlp_sem(int fd, int name)
2134 diff --git a/src/clocks.c b/src/clocks.c
2135 new file mode 100644
2136 index 0000000..fcb94e5
2137 --- /dev/null
2138 +++ b/src/clocks.c
2139 @@ -0,0 +1,23 @@
2140 +#include <stdio.h>
2141 +
2142 +#include <sys/time.h>
2143 +#include <time.h>
2144 +
2145 +/* CPU time consumed so far in seconds */
2146 +double cputime(void)
2147 +{
2148 + struct timespec ts;
2149 + int err;
2150 + err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
2151 + if (err != 0)
2152 + perror("clock_gettime");
2153 + return (ts.tv_sec + 1E-9 * ts.tv_nsec);
2154 +}
2155 +
2156 +/* wall-clock time in seconds */
2157 +double wctime(void)
2158 +{
2159 + struct timeval tv;
2160 + gettimeofday(&tv, NULL);
2161 + return (tv.tv_sec + 1E-6 * tv.tv_usec);
2162 +}
2163 diff --git a/src/syscalls.c b/src/syscalls.c
2164 index c738ac4..f78475e 100644
2165 --- a/src/syscalls.c
2166 +++ b/src/syscalls.c
2167 @@ -44,24 +44,14 @@ int od_close(int od)
2168 return syscall(__NR_od_close, od);
2169 }
2170
2171 -int fmlp_down(int od)
2172 +int litmus_lock(int od)
2173 {
2174 - return syscall(__NR_fmlp_down, od);
2175 + return syscall(__NR_litmus_lock, od);
2176 }
2177
2178 -int fmlp_up(int od)
2179 +int litmus_unlock(int od)
2180 {
2181 - return syscall(__NR_fmlp_up, od);
2182 -}
2183 -
2184 -int srp_down(int od)
2185 -{
2186 - return syscall(__NR_srp_down, od);
2187 -}
2188 -
2189 -int srp_up(int od)
2190 -{
2191 - return syscall(__NR_srp_up, od);
2192 + return syscall(__NR_litmus_unlock, od);
2193 }
2194
2195 int get_job_no(unsigned int *job_no)
2196 @@ -98,3 +88,23 @@ int null_call(cycles_t *timestamp)
2197 {
2198 return syscall(__NR_null_call, timestamp);
2199 }
2200 +
2201 +int set_rt_task_mc_param(pid_t pid, struct mc_task *param)
2202 +{
2203 + return syscall(__NR_set_rt_task_mc_param, pid, param);
2204 +}
2205 +
2206 +int change_speed(int num, int denom)
2207 +{
2208 + return syscall(__NR_change_speed, num, denom);
2209 +}
2210 +
2211 +int register_pid(pid_t pid)
2212 +{
2213 + return syscall(__NR_register_pid, pid);
2214 +}
2215 +
2216 +int get_job_report(int type, int *num_report, struct report_data *param)
2217 +{
2218 + return syscall(__NR_get_job_report, type, num_report, param);
2219 +}
2220 \ No newline at end of file
2221 diff --git a/tests/core_api.c b/tests/core_api.c
2222 index d858f1f..7f7a099 100644
2223 --- a/tests/core_api.c
2224 +++ b/tests/core_api.c
2225 @@ -1,5 +1,8 @@
2226 -#include "tests.h"
2227 +#include <sys/wait.h> /* for waitpid() */
2228 +#include <unistd.h>
2229 +#include <stdio.h>
2230
2231 +#include "tests.h"
2232 #include "litmus.h"
2233
2234
2235 @@ -19,6 +22,7 @@ TESTCASE(set_rt_task_param_invalid_params, ALL,
2236 params.period = 100;
2237 params.phase = 0;
2238 params.cls = RT_CLASS_HARD;
2239 + params.budget_policy = NO_ENFORCEMENT;
2240
2241 /* over utilize */
2242 params.exec_cost = 110;
2243 @@ -49,3 +53,40 @@ TESTCASE(job_control_non_rt, ALL,
2244
2245 SYSCALL_FAILS( EPERM, get_job_no(&job_no) );
2246 }
2247 +
2248 +
2249 +TESTCASE(rt_fork_non_rt, LITMUS,
2250 + "children of RT tasks are not automatically RT tasks")
2251 +{
2252 + unsigned int pid, job_no;
2253 + int status;
2254 +
2255 + SYSCALL( sporadic_partitioned(10, 100, 0) );
2256 + SYSCALL( task_mode(LITMUS_RT_TASK) );
2257 +
2258 + pid = fork();
2259 +
2260 + ASSERT( pid != -1 );
2261 +
2262 + if (pid == 0) {
2263 + /* child */
2264 +
2265 + SYSCALL_FAILS( EINVAL, sleep_next_period() );
2266 + SYSCALL_FAILS( EINVAL, wait_for_job_release(0) );
2267 + SYSCALL_FAILS( EPERM, get_job_no(&job_no) );
2268 +
2269 + exit(0);
2270 + } else {
2271 + /* parent */
2272 +
2273 + SYSCALL( sleep_next_period() );
2274 + SYSCALL( wait_for_job_release(20) );
2275 + SYSCALL( get_job_no(&job_no) );
2276 +
2277 + SYSCALL( task_mode(BACKGROUND_TASK) );
2278 +
2279 + SYSCALL( waitpid(pid, &status, 0) );
2280 +
2281 + ASSERT(WEXITSTATUS(status) == 0);
2282 + }
2283 +}
2284 diff --git a/tests/fdso.c b/tests/fdso.c
2285 index d60e9ef..8a2a0d0 100644
2286 --- a/tests/fdso.c
2287 +++ b/tests/fdso.c
2288 @@ -20,7 +20,7 @@ TESTCASE(fmlp_not_active, C_EDF | PFAIR | LINUX,
2289
2290 ASSERT(fd != -1);
2291
2292 - SYSCALL_FAILS(EBUSY, open_fmlp_sem(fd, 0) );
2293 + SYSCALL_FAILS(ENXIO, open_fmlp_sem(fd, 0) );
2294
2295 SYSCALL( close(fd) );
2296
2297 @@ -31,16 +31,16 @@ TESTCASE(fmlp_not_active, C_EDF | PFAIR | LINUX,
2298 TESTCASE(invalid_od, ALL,
2299 "reject invalid object descriptors")
2300 {
2301 - SYSCALL_FAILS( EINVAL, fmlp_down(3) );
2302 + SYSCALL_FAILS( EINVAL, litmus_lock(3) );
2303
2304 - SYSCALL_FAILS( EINVAL, fmlp_up(3) );
2305 + SYSCALL_FAILS( EINVAL, litmus_unlock(3) );
2306
2307 SYSCALL_FAILS( EINVAL, od_close(3) );
2308
2309
2310 - SYSCALL_FAILS( EINVAL, fmlp_down(-1) );
2311 + SYSCALL_FAILS( EINVAL, litmus_lock(-1) );
2312
2313 - SYSCALL_FAILS( EINVAL, fmlp_up(-1) );
2314 + SYSCALL_FAILS( EINVAL, litmus_unlock(-1) );
2315
2316 SYSCALL_FAILS( EINVAL, od_close(-1) );
2317 }
2318 @@ -61,23 +61,34 @@ TESTCASE(not_inherit_od, GSN_EDF | PSN_EDF,
2319
2320 SYSCALL( od = open_fmlp_sem(fd, 0) );
2321
2322 - SYSCALL( fmlp_down(od) );
2323 -
2324 - SYSCALL( fmlp_up(od) );
2325 -
2326 pid = fork();
2327
2328 ASSERT( pid != -1 );
2329
2330 + /* must be an RT task to lock at all */
2331 + SYSCALL( sporadic_partitioned(10, 100, 0) );
2332 + SYSCALL( task_mode(LITMUS_RT_TASK) );
2333 +
2334 if (pid == 0) {
2335 /* child */
2336 - SYSCALL_FAILS(EINVAL, fmlp_down(od) );
2337 - SYSCALL_FAILS(EINVAL, fmlp_up(od) );
2338 + SYSCALL_FAILS(EINVAL, litmus_lock(od) );
2339 + SYSCALL_FAILS(EINVAL, litmus_unlock(od) );
2340 +
2341 + SYSCALL( task_mode(BACKGROUND_TASK) );
2342 +
2343 exit(0);
2344 } else {
2345 - SYSCALL( fmlp_down(od) );
2346 - SYSCALL( fmlp_up(od) );
2347 +
2348 + SYSCALL( litmus_lock(od) );
2349 + SYSCALL( litmus_unlock(od) );
2350 +
2351 + SYSCALL( litmus_lock(od) );
2352 + SYSCALL( litmus_unlock(od) );
2353 +
2354 + SYSCALL( task_mode(BACKGROUND_TASK) );
2355 +
2356 SYSCALL( waitpid(pid, &status, 0) );
2357 +
2358 ASSERT(WEXITSTATUS(status) == 0);
2359 }
2360
2361 diff --git a/tests/locks.c b/tests/locks.c
2362 new file mode 100644
2363 index 0000000..65b932a
2364 --- /dev/null
2365 +++ b/tests/locks.c
2366 @@ -0,0 +1,110 @@
2367 +#include <fcntl.h>
2368 +#include <unistd.h>
2369 +#include <stdio.h>
2370 +
2371 +#include "tests.h"
2372 +#include "litmus.h"
2373 +
2374 +
2375 +TESTCASE(not_lock_fmlp_be, GSN_EDF | PSN_EDF,
2376 + "don't let best-effort tasks lock FMLP semaphores")
2377 +{
2378 + int fd, od;
2379 +
2380 + SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT) );
2381 +
2382 + SYSCALL( od = open_fmlp_sem(fd, 0) );
2383 +
2384 + /* BE tasks may not lock FMLP semaphores */
2385 + SYSCALL_FAILS(EPERM, litmus_lock(od) );
2386 +
2387 + /* tasks may not unlock resources they don't own */
2388 + SYSCALL_FAILS(EINVAL, litmus_unlock(od) );
2389 +
2390 + SYSCALL( od_close(od) );
2391 +
2392 + SYSCALL( close(fd) );
2393 +
2394 + SYSCALL( remove(".fmlp_locks") );
2395 +
2396 +}
2397 +
2398 +TESTCASE(not_lock_srp_be, PSN_EDF,
2399 + "don't let best-effort tasks open SRP semaphores")
2400 +{
2401 + int fd, od;
2402 +
2403 + SYSCALL( fd = open(".srp_locks", O_RDONLY | O_CREAT) );
2404 +
2405 + /* BE tasks may not open SRP semaphores */
2406 +
2407 + SYSCALL_FAILS(EPERM, od = open_srp_sem(fd, 0) );
2408 +
2409 + SYSCALL( close(fd) );
2410 +
2411 + SYSCALL( remove(".srp_locks") );
2412 +
2413 +}
2414 +
2415 +TESTCASE(lock_srp, PSN_EDF,
2416 + "SRP acquisition and release")
2417 +{
2418 + int fd, od;
2419 +
2420 + SYSCALL( fd = open(".srp_locks", O_RDONLY | O_CREAT) );
2421 +
2422 + SYSCALL( sporadic_partitioned(10, 100, 0) );
2423 + SYSCALL( task_mode(LITMUS_RT_TASK) );
2424 +
2425 + SYSCALL( od = open_srp_sem(fd, 0) );
2426 +
2427 + SYSCALL( litmus_lock(od) );
2428 + SYSCALL( litmus_unlock(od) );
2429 +
2430 + SYSCALL( litmus_lock(od) );
2431 + SYSCALL( litmus_unlock(od) );
2432 +
2433 + SYSCALL( litmus_lock(od) );
2434 + SYSCALL( litmus_unlock(od) );
2435 +
2436 + /* tasks may not unlock resources they don't own */
2437 + SYSCALL_FAILS(EINVAL, litmus_unlock(od) );
2438 +
2439 + SYSCALL( od_close(od) );
2440 +
2441 + SYSCALL( close(fd) );
2442 +
2443 + SYSCALL( remove(".srp_locks") );
2444 +}
2445 +
2446 +
2447 +TESTCASE(lock_fmlp, PSN_EDF | GSN_EDF,
2448 + "FMLP acquisition and release")
2449 +{
2450 + int fd, od;
2451 +
2452 + SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT) );
2453 +
2454 + SYSCALL( sporadic_partitioned(10, 100, 0) );
2455 + SYSCALL( task_mode(LITMUS_RT_TASK) );
2456 +
2457 + SYSCALL( od = open_fmlp_sem(fd, 0) );
2458 +
2459 + SYSCALL( litmus_lock(od) );
2460 + SYSCALL( litmus_unlock(od) );
2461 +
2462 + SYSCALL( litmus_lock(od) );
2463 + SYSCALL( litmus_unlock(od) );
2464 +
2465 + SYSCALL( litmus_lock(od) );
2466 + SYSCALL( litmus_unlock(od) );
2467 +
2468 + /* tasks may not unlock resources they don't own */
2469 + SYSCALL_FAILS(EINVAL, litmus_unlock(od) );
2470 +
2471 + SYSCALL( od_close(od) );
2472 +
2473 + SYSCALL( close(fd) );
2474 +
2475 + SYSCALL( remove(".fmlp_locks") );
2476 +}
2477 diff --git a/tests/make_catalog.py b/tests/make_catalog.py
2478 index 75b6aca..96f9b23 100755
2479 --- a/tests/make_catalog.py
2480 +++ b/tests/make_catalog.py
2481 @@ -63,6 +63,7 @@ def create_tc_tables(out=sys.stdout):
2482 plugins.add(p)
2483
2484 plugins.discard('ALL')
2485 + plugins.discard('LITMUS')
2486
2487 _('#include "tests.h"')
2488
2489 @@ -78,7 +79,9 @@ def create_tc_tables(out=sys.stdout):
2490 count = 0
2491 _('int %s_TESTS[] = {' % p)
2492 for (i, tc) in enumerate(tests):
2493 - if p in tc.plugins or 'ALL' in tc.plugins:
2494 + if p in tc.plugins or \
2495 + 'ALL' in tc.plugins or \
2496 + 'LITMUS' in tc.plugins and p != 'LINUX':
2497 _('\t%d,' % i)
2498 count += 1
2499 _('};')
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.