Attachment 'liblitmus-semi-part-with-edfos.patch'
Download 1 diff --git a/.gitignore b/.gitignore
2 index f420aa3..3df27f8 100644
3 --- a/.gitignore
4 +++ b/.gitignore
5 @@ -8,6 +8,10 @@ tests/__test_catalog.inc
6 # executables
7 runtests
8 rt_launch
9 +rt_launch_edffm
10 +rt_launch_edfos
11 +rt_launch_edfwm
12 +rt_launch_npsf
13 wait_test
14 np_test
15 stdump
16 @@ -17,8 +21,14 @@ base_mt_task
17 release_ts
18 showst
19 rtspin
20 +rtspin_edffm
21 +rtspin_edfos
22 +rtspin_edfwm
23 +rtspin_npsf
24 cycles
25 measure_syscall
26 +npsf_add_server
27 +
28
29 # scons files
30 .sconsign.dblite
31 diff --git a/SConstruct b/SConstruct
32 index c41e41e..617948d 100644
33 --- a/SConstruct
34 +++ b/SConstruct
35 @@ -160,10 +160,10 @@ if not (env.GetOption('clean') or env.GetOption('help')):
36 abort("Cannot find kernel headers in '$LITMUS_KERNEL'",
37 "Please ensure that LITMUS_KERNEL in .config is set to a valid path.")
38
39 - conf.CheckCHeader('litmus/rt_param.h') or \
40 - abort("Cannot find LITMUS^RT headers in '$LITMUS_KERNEL'",
41 - "Please ensure sure that the kernel in '$LITMUS_KERNEL'"
42 - " is a LITMUS^RT kernel.")
43 +# conf.CheckCHeader('litmus/rt_param.h') or \
44 +# abort("Cannot find LITMUS^RT headers in '$LITMUS_KERNEL'",
45 +# "Please ensure sure that the kernel in '$LITMUS_KERNEL'"
46 +# " is a LITMUS^RT kernel.")
47
48 conf.CheckSyscallNr() or \
49 abort("The LITMUS^RT syscall numbers are not available.",
50 @@ -208,6 +208,15 @@ rt.Program('base_task', 'bin/base_task.c')
51 mtrt.Program('base_mt_task', 'bin/base_mt_task.c')
52 rt.Program('rt_launch', ['bin/rt_launch.c', 'bin/common.c'])
53 rt.Program('rtspin', ['bin/rtspin.c', 'bin/common.c'])
54 +rt.Program('rtspin_edffm', ['bin/rtspin_edffm.c', 'bin/common.c'])
55 +rt.Program('rtspin_edfos', ['bin/rtspin_edfos.c', 'bin/common.c'])
56 +rt.Program('rt_launch_edffm', ['bin/rt_launch_edffm.c', 'bin/common.c'])
57 +rt.Program('rt_launch_edfos', ['bin/rt_launch_edfos.c', 'bin/common.c'])
58 +rt.Program('rtspin_npsf', ['bin/rtspin_npsf.c', 'bin/common.c'])
59 +rt.Program('npsf_add_server', ['bin/npsf_add_server.c', 'bin/common.c'])
60 +rt.Program('rt_launch_npsf', ['bin/rt_launch_npsf.c', 'bin/common.c'])
61 +rt.Program('rtspin_edfwm', ['bin/rtspin_edfwm.c', 'bin/common.c'])
62 +rt.Program('rt_launch_edfwm', ['bin/rt_launch_edfwm.c', 'bin/common.c'])
63 rt.Program('release_ts', 'bin/release_ts.c')
64 rtm.Program('measure_syscall', 'bin/null_call.c')
65
66 diff --git a/bin/common.c b/bin/common.c
67 index 452b882..167344a 100644
68 --- a/bin/common.c
69 +++ b/bin/common.c
70 @@ -1,6 +1,7 @@
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <errno.h>
74 +#include <string.h>
75
76 #include "common.h"
77
78 @@ -9,3 +10,120 @@ void bail_out(const char* msg)
79 perror(msg);
80 exit(-1 * errno);
81 }
82 +
83 +/* EDF-WM helper functions to parse a custom text file format to "easily"
84 + * launch tests with rtspin and rt_launch:
85 + *
86 + * Format for task:
87 + *
88 + * <task_id execution_cost period phase cpu slices_number> .
89 + *
90 + * If the task is split on multiple slices, slices_number is non 0
91 + * and we scan a list of slice parameters up to slices_number:
92 + *
93 + * Format for slices:
94 + *
95 + * <task_id cpu deadline(from job release) budget offset> .
96 + *
97 + * The offset is the start time for the slice relative to the job release.
98 + *
99 + * Example:
100 + * 14 2.26245771754 10 0 5 2
101 + * 14 5 5.000000 1.497306 0.000000
102 + * 14 7 10.000000 0.765152 5.000000
103 + */
104 +
105 +#define fms_to_ns(x) (lt_t)(((x) * __NS_PER_MS))
106 +/*
107 + * <task_id, cpu, deadline (from job release), budget, offset> .
108 + */
109 +int parse_edfwm_slice(FILE *ts, int slices_no, int task_id,
110 + struct rt_task *rt)
111 +{
112 + int i, tid;
113 + unsigned int cpu;
114 + double deadline, budget, offset;
115 +
116 + lt_t total_budget = 0;
117 +
118 + struct edf_wm_params* wm = (struct edf_wm_params*) &rt->semi_part;
119 +
120 + for (i = 0; i < slices_no; i++) {
121 +
122 + if (fscanf(ts, "%d %u %lf %lf %lf\n", &tid, &cpu,
123 + &deadline, &budget, &offset) != EOF) {
124 +
125 + if (task_id != tid) {
126 + fprintf(stderr, "task_id %d != tid %d\n",
127 + task_id, tid);
128 + return -1;
129 + }
130 +
131 + wm->slices[i].deadline = fms_to_ns(deadline);
132 + wm->slices[i].budget = fms_to_ns(budget);
133 + wm->slices[i].offset = fms_to_ns(offset);
134 + wm->slices[i].cpu = cpu;
135 +
136 + printf("slice(tid, cpu, d, e, ph) = (%d, %u, %llu, %llu, %llu)\n",
137 + tid, cpu, wm->slices[i].deadline,
138 + wm->slices[i].budget, wm->slices[i].offset);
139 +
140 + total_budget += wm->slices[i].budget;
141 + if (wm->slices[i].budget < MIN_EDF_WM_SLICE_SIZE) {
142 +
143 + fprintf(stderr, "Slice %llu is too small\n",
144 + wm->slices[i].budget);
145 + return -1;
146 + }
147 + }
148 +
149 + if (ferror(ts)) {
150 + fprintf(stderr, "Cannot read file\n");
151 + return -1;
152 + }
153 + }
154 + wm->count = slices_no;
155 + rt->exec_cost = total_budget;
156 + printf("--- total %u slices ---\n", wm->count);
157 + return 0;
158 +}
159 +
160 +/*
161 + * <task_id, execution_cost, period, phase, cpu, slices_number> .
162 + */
163 +int parse_edfwm_ts_file(FILE *ts, struct rt_task *rt)
164 +{
165 + int task_id, ret = 1;
166 + unsigned int cpu, sliceno;
167 + double fwcet, fperiod, fphase;
168 +
169 + ret = fscanf(ts, "%d %lf %lf %lf %d %d\n",
170 + &task_id, &fwcet, &fperiod, &fphase, &cpu, &sliceno);
171 +
172 + if (ferror(ts))
173 + goto err;
174 +
175 + rt->exec_cost = fms_to_ns(fwcet);
176 + rt->period = fms_to_ns(fperiod);
177 + rt->phase = fms_to_ns(fphase);
178 + rt->cpu = cpu;
179 + rt->cls = RT_CLASS_HARD;
180 + rt->budget_policy = PRECISE_ENFORCEMENT;
181 +
182 + printf("(tid, wcet, period, ph, cpu, slices) = "
183 + "(%d, %llu, %llu, %llu, %u, %u)\n",
184 + task_id, rt->exec_cost, rt->period, rt->phase, cpu, sliceno);
185 + if (sliceno > 0) {
186 + memset(&rt->semi_part, 0, sizeof(struct edf_wm_params));
187 + ret = parse_edfwm_slice(ts, sliceno, task_id, rt);
188 + if (ret < 0)
189 + goto err;
190 + }
191 +
192 + return 0;
193 +
194 +err:
195 + fprintf(stderr, "Error parsing file\n");
196 + return -1;
197 +}
198 +
199 diff --git a/bin/npsf_add_server.c b/bin/npsf_add_server.c
200 new file mode 100644
201 index 0000000..9f3f92c
202 --- /dev/null
203 +++ b/bin/npsf_add_server.c
204 @@ -0,0 +1,108 @@
205 +/* wrapper for sys_add_server
206 + *
207 + * Input: a file with on each line:
208 + * npsf_id cpu budget(us)
209 + */
210 +#include <stdio.h>
211 +#include <stdlib.h>
212 +#include <unistd.h>
213 +
214 +#include "litmus.h"
215 +#include "common.h"
216 +
217 +void usage(char *error) {
218 + fprintf(stderr, "Error: %s\n", error);
219 + fprintf(stderr,
220 + "Usage: npsf_add_server SERVERS-FILE MAX-SPLITS-PER-NPSFID\n");
221 + exit(1);
222 +}
223 +
224 +int main(int argc, char** argv)
225 +{
226 + int ret;
227 + FILE *file;
228 + int i,j;
229 + int npsf_id, curr_id = -1;
230 + int cpu, max_splits_server;
231 + int budget_us;
232 + struct npsf_budgets *budgets;
233 +
234 + if (argc < 3)
235 + usage("Arguments missing.");
236 +
237 + max_splits_server = atoi(argv[2]);
238 +
239 + if ((file = fopen(argv[1], "r")) == NULL) {
240 + fprintf(stderr, "Cannot open %s\n", argv[1]);
241 + return -1;
242 + }
243 +
244 + /* format: npsf_id cpu budget-us */
245 + i = 0;
246 + while (fscanf(file, "%d %d %d\n", &npsf_id, &cpu, &budget_us) != EOF) {
247 +
248 + printf("Read: %d %d %d\n", npsf_id, cpu, budget_us);
249 +
250 + if (curr_id == -1) {
251 + curr_id = npsf_id;
252 + budgets = malloc(max_splits_server *
253 + sizeof(struct npsf_budgets));
254 + for(j = 0; j < max_splits_server; j++) {
255 + budgets[j].cpu = -1;
256 + budgets[j].budget = 0;
257 + }
258 + }
259 +
260 + if (npsf_id == curr_id) {
261 + /* same notional processor, different cpu and budget */
262 + budgets[i].cpu = cpu;
263 + budgets[i].budget = (lt_t) (budget_us * 1000);
264 + i++;
265 + } else {
266 + /* different notional processor */
267 + /* add server */
268 + printf("Adding npsf_id = %d\n", curr_id);
269 + ret = add_server(&curr_id, budgets, 0);
270 +
271 + if (ret < 0) {
272 + fclose(file);
273 + free(budgets);
274 + printf("Cannot add Notional Processor %d\n",
275 + curr_id);
276 + return ret;
277 + }
278 +
279 + /* reinit new */
280 + i = 0;
281 + budgets = malloc(max_splits_server *
282 + sizeof(struct npsf_budgets));
283 + for(j = 0; j < max_splits_server; j++) {
284 + budgets[j].cpu = -1;
285 + budgets[j].budget = 0;
286 + }
287 + curr_id = npsf_id;
288 + budgets[i].cpu = cpu;
289 + budgets[i].budget = (lt_t) (budget_us * 1000);
290 + i++;
291 + }
292 + }
293 +
294 + if (ferror(file)) {
295 + fprintf(stderr, "Error while reading\n");
296 + fclose(file);
297 + return -1;
298 + }
299 +
300 + /* save the last entry */
301 + ret = add_server(&curr_id, budgets, 1);
302 + printf("Adding npsf_id = %d\n", curr_id);
303 + if (ret < 0) {
304 + fclose(file);
305 + free(budgets);
306 + bail_out("Cannot add Notional Processor: ");
307 + }
308 +
309 + fclose(file);
310 +
311 + return 0;
312 +}
313 diff --git a/bin/rt_launch_edffm.c b/bin/rt_launch_edffm.c
314 new file mode 100644
315 index 0000000..ddde7dd
316 --- /dev/null
317 +++ b/bin/rt_launch_edffm.c
318 @@ -0,0 +1,133 @@
319 +#include <stdio.h>
320 +#include <stdlib.h>
321 +#include <string.h>
322 +#include <unistd.h>
323 +#include <limits.h>
324 +#include <signal.h>
325 +
326 +#include "litmus.h"
327 +#include "common.h"
328 +
329 +typedef struct {
330 + int wait;
331 + char * exec_path;
332 + char ** argv;
333 +} startup_info_t;
334 +
335 +
336 +int launch(void *task_info_p) {
337 + startup_info_t *info = (startup_info_t*) task_info_p;
338 + int ret;
339 + if (info->wait) {
340 + ret = wait_for_ts_release();
341 + if (ret != 0)
342 + perror("wait_for_ts_release()");
343 + }
344 + ret = execvp(info->exec_path, info->argv);
345 + perror("execv failed");
346 + return ret;
347 +}
348 +
349 +void usage(char *error) {
350 + fprintf(stderr, "%s\nUsage: rt_launch [-w][-v][-p cpu][-c hrt | srt | be] wcet period"
351 + " fracnum1 fracden1 cpu1 fracnum2 fracden2 cpu2 program [arg1 arg2 ...]\n"
352 + "\t-w\tSynchronous release\n"
353 + "\t-v\tVerbose\n"
354 + "\t-p\tcpu (or initial cpu)\n"
355 + "\t-c\tClass\n"
356 + "\twcet, period in ms\n"
357 + "\tprogram to be launched\n",
358 + error);
359 + exit(1);
360 +}
361 +
362 +
363 +#define OPTSTR "p:c:vw"
364 +
365 +int main(int argc, char** argv)
366 +{
367 + int ret;
368 + lt_t wcet;
369 + lt_t period;
370 + /* [num,den] */
371 + lt_t frac1[2], frac2[2];
372 + int cpu1, cpu2;
373 + int migrate = 0;
374 + int cpu = 0;
375 + int opt;
376 + int verbose = 0;
377 + int wait = 0;
378 + startup_info_t info;
379 + task_class_t class = RT_CLASS_HARD;
380 +
381 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
382 + switch (opt) {
383 + case 'w':
384 + wait = 1;
385 + break;
386 + case 'v':
387 + verbose = 1;
388 + break;
389 + case 'p':
390 + cpu = atoi(optarg);
391 + migrate = 1;
392 + break;
393 + case 'c':
394 + class = str2class(optarg);
395 + if (class == -1)
396 + usage("Unknown task class.");
397 + break;
398 +
399 + case ':':
400 + usage("Argument missing.");
401 + break;
402 + case '?':
403 + default:
404 + usage("Bad argument.");
405 + break;
406 + }
407 + }
408 +
409 + signal(SIGUSR1, SIG_IGN);
410 +
411 + if (argc - optind < 8)
412 + usage("Arguments missing.");
413 + wcet = ms2lt(atoi(argv[optind + 0]));
414 + period = ms2lt(atoi(argv[optind + 1]));
415 + /* frac num, den = 0 means fixed task */
416 + frac1[0] = atoi(argv[optind + 2]);
417 + frac1[1] = atoi(argv[optind + 3]);
418 + cpu1 = atoi(argv[optind + 4]);
419 + frac2[0] = atoi(argv[optind + 5]);
420 + frac2[1] = atoi(argv[optind + 6]);
421 + cpu2 = atoi(argv[optind + 7]);
422 + if (wcet <= 0)
423 + usage("The worst-case execution time must be a "
424 + "positive number.");
425 + if (period <= 0)
426 + usage("The period must be a positive number.");
427 + if (wcet > period) {
428 + usage("The worst-case execution time must not "
429 + "exceed the period.");
430 + }
431 + info.exec_path = argv[optind + 8];
432 + info.argv = argv + optind + 8;
433 + info.wait = wait;
434 + if (migrate) {
435 + ret = be_migrate_to(cpu);
436 + if (ret < 0)
437 + bail_out("could not migrate to target partition");
438 + }
439 + /* create in src/task.c a new wrapper for the __launch_rt_task
440 + * which takes the fraction and the cpus */
441 + ret = __create_rt_task_edffm(launch, &info, cpu, wcet, period, frac1,
442 + frac2, cpu1, cpu2, class);
443 +
444 +
445 + if (ret < 0)
446 + bail_out("could not create rt child process");
447 + else if (verbose)
448 + printf("%d\n", ret);
449 +
450 + return 0;
451 +}
452 diff --git a/bin/rt_launch_edfos.c b/bin/rt_launch_edfos.c
453 new file mode 100644
454 index 0000000..2b26fb2
455 --- /dev/null
456 +++ b/bin/rt_launch_edfos.c
457 @@ -0,0 +1,135 @@
458 +#include <stdio.h>
459 +#include <stdlib.h>
460 +#include <string.h>
461 +#include <unistd.h>
462 +#include <limits.h>
463 +#include <signal.h>
464 +
465 +#include "litmus.h"
466 +#include "common.h"
467 +
468 +typedef struct {
469 + int wait;
470 + char * exec_path;
471 + char ** argv;
472 +} startup_info_t;
473 +
474 +
475 +int launch(void *task_info_p) {
476 + startup_info_t *info = (startup_info_t*) task_info_p;
477 + int ret;
478 + if (info->wait) {
479 + ret = wait_for_ts_release();
480 + if (ret != 0)
481 + perror("wait_for_ts_release()");
482 + }
483 + ret = execvp(info->exec_path, info->argv);
484 + perror("execv failed");
485 + return ret;
486 +}
487 +
488 +void usage(char *error) {
489 + fprintf(stderr, "%s\nUsage: rt_launch [-w][-v][-p cpu][-c hrt | srt | be] wcet period"
490 + " fracnum1 fracden1 cpu1 fracnum2 fracden2 cpu2 program [arg1 arg2 ...]\n"
491 + "\t-w\tSynchronous release\n"
492 + "\t-v\tVerbose\n"
493 + "\t-p\tcpu (or initial cpu)\n"
494 + "\t-c\tClass\n"
495 + "\twcet, period in ms\n"
496 + "\tprogram to be launched\n",
497 + error);
498 + exit(1);
499 +}
500 +
501 +
502 +#define OPTSTR "p:c:vw"
503 +
504 +int main(int argc, char** argv)
505 +{
506 + int ret;
507 + lt_t wcet;
508 + lt_t period;
509 + /* [num,den] */
510 + lt_t fracs[NR_CPUS_EDF_OS][2];
511 + int cpu = -1;
512 + int opt;
513 + int verbose = 0;
514 + int wait = 0;
515 + int i;
516 + startup_info_t info;
517 + task_class_t class = RT_CLASS_HARD;
518 +
519 + for (i = 0; i < NR_CPUS_EDF_OS; i++) {
520 + fracs[i][0] = 0;
521 + fracs[i][1] = 0;
522 + }
523 +
524 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
525 + switch (opt) {
526 + case 'w':
527 + wait = 1;
528 + break;
529 + case 'v':
530 + verbose = 1;
531 + break;
532 + case 'p':
533 + cpu = atoi(optarg);
534 + fracs[cpu][0] = 1;
535 + fracs[cpu][1] = 1;
536 + break;
537 + case 'c':
538 + class = str2class(optarg);
539 + if (class == -1)
540 + usage("Unknown task class.");
541 + break;
542 + case ':':
543 + usage("Argument missing.");
544 + break;
545 + case '?':
546 + default:
547 + usage("Bad argument.");
548 + break;
549 + }
550 + }
551 +
552 + signal(SIGUSR1, SIG_IGN);
553 +
554 + if ((argc - (optind + 2)) % 3 != 0)
555 + usage("Arguments missing.");
556 + wcet = ms2lt(atoi(argv[optind + 0]));
557 + period = ms2lt(atoi(argv[optind + 1]));
558 +
559 + for (i = optind + 1; i < argc; i+= 3) {
560 + cpu = atoi(argv[i+2]);
561 + fracs[cpu][0] = atoi(argv[i]);
562 + fracs[cpu][1] = atoi(argv[i+1]);
563 + }
564 + if (cpu == -1)
565 + cpu = compute_initial_cpu_edfos(fracs);
566 + if (wcet <= 0)
567 + usage("The worst-case execution time must be a "
568 + "positive number.");
569 + if (period <= 0)
570 + usage("The period must be a positive number.");
571 + if (wcet > period) {
572 + usage("The worst-case execution time must not "
573 + "exceed the period.");
574 + }
575 + info.exec_path = argv[optind + 8];
576 + info.argv = argv + optind + 8;
577 + info.wait = wait;
578 + ret = be_migrate_to(cpu);
579 + if (ret < 0)
580 + bail_out("could not migrate to target partition");
581 + /* create in src/task.c a new wrapper for the __launch_rt_task
582 + * which takes the fraction and the cpus */
583 + ret = __create_rt_task_edfos(launch, &info, cpu, wcet, period, fracs,
584 + class);
585 +
586 + if (ret < 0)
587 + bail_out("could not create rt child process");
588 + else if (verbose)
589 + printf("%d\n", ret);
590 +
591 + return 0;
592 +}
593 diff --git a/bin/rt_launch_edfwm.c b/bin/rt_launch_edfwm.c
594 new file mode 100644
595 index 0000000..9e8a322
596 --- /dev/null
597 +++ b/bin/rt_launch_edfwm.c
598 @@ -0,0 +1,98 @@
599 +#include <stdio.h>
600 +#include <stdlib.h>
601 +#include <string.h>
602 +#include <unistd.h>
603 +#include <limits.h>
604 +#include <signal.h>
605 +
606 +#include "litmus.h"
607 +#include "common.h"
608 +
609 +typedef struct {
610 + int wait;
611 + char * exec_path;
612 + char ** argv;
613 +} startup_info_t;
614 +
615 +
616 +int launch(void *task_info_p) {
617 + startup_info_t *info = (startup_info_t*) task_info_p;
618 + int ret;
619 + if (info->wait) {
620 + ret = wait_for_ts_release();
621 + if (ret != 0)
622 + perror("wait_for_ts_release()");
623 + }
624 + ret = execvp(info->exec_path, info->argv);
625 + perror("execv failed");
626 + return ret;
627 +}
628 +
629 +void usage(char *error) {
630 + fprintf(stderr, "%s\nUsage: rt_launch [-w] task_parameters_file "
631 + "program [arg1 arg2 ...]\n"
632 + "\t-w\tSynchronous release\n"
633 + "\tprogram to be launched\n",
634 + error);
635 + exit(1);
636 +}
637 +
638 +#define OPTSTR "w"
639 +
640 +int main(int argc, char** argv)
641 +{
642 + int ret;
643 + int wait = 0;
644 + int opt;
645 + startup_info_t info;
646 +
647 + struct rt_task rt;
648 + FILE *file;
649 +
650 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
651 + switch (opt) {
652 + case 'w':
653 + wait = 1;
654 + break;
655 + case ':':
656 + usage("Argument missing.");
657 + break;
658 + case '?':
659 + default:
660 + usage("Bad argument.");
661 + break;
662 + }
663 + }
664 +
665 + signal(SIGUSR1, SIG_IGN);
666 +
667 + if (argc - optind < 2)
668 + usage("Arguments missing.");
669 +
670 + if ((file = fopen(argv[optind + 0], "r")) == NULL) {
671 + fprintf(stderr, "Cannot open %s\n", argv[1]);
672 + return -1;
673 + }
674 +
675 + memset(&rt, 0, sizeof(struct rt_task));
676 +
677 + if (parse_edfwm_ts_file(file, &rt) < 0)
678 + bail_out("Could not parse file\n");
679 +
680 + if (sporadic_task_ns_semi(&rt) < 0)
681 + bail_out("could not setup rt task params");
682 +
683 + fclose(file);
684 +
685 + info.exec_path = argv[optind + 1];
686 + info.argv = argv + optind + 1;
687 + info.wait = wait;
688 +
689 + ret = create_rt_task_semi(launch, &info, &rt);
690 +
691 + if (ret < 0)
692 + bail_out("could not create rt child process");
693 +
694 + return 0;
695 +}
696 +
697 diff --git a/bin/rt_launch_npsf.c b/bin/rt_launch_npsf.c
698 new file mode 100644
699 index 0000000..97ad361
700 --- /dev/null
701 +++ b/bin/rt_launch_npsf.c
702 @@ -0,0 +1,110 @@
703 +#include <stdio.h>
704 +#include <stdlib.h>
705 +#include <string.h>
706 +#include <unistd.h>
707 +#include <limits.h>
708 +#include <signal.h>
709 +
710 +#include "litmus.h"
711 +#include "common.h"
712 +
713 +typedef struct {
714 + int wait;
715 + char * exec_path;
716 + char ** argv;
717 +} startup_info_t;
718 +
719 +
720 +int launch(void *task_info_p) {
721 + startup_info_t *info = (startup_info_t*) task_info_p;
722 + int ret;
723 + if (info->wait) {
724 + ret = wait_for_ts_release();
725 + if (ret != 0)
726 + perror("wait_for_ts_release()");
727 + }
728 + ret = execvp(info->exec_path, info->argv);
729 + perror("execv failed");
730 + return ret;
731 +}
732 +
733 +void usage(char *error) {
734 + fprintf(stderr, "%s\nUsage: rt_launch [-w][-v] wcet period cpu npsf-id program [arg1 arg2 ...]\n"
735 + "\t-w\tSynchronous release\n"
736 + "\t-v\tVerbose\n"
737 + "\twcet, period in ms\n"
738 + "\tprogram to be launched\n",
739 + error);
740 + exit(1);
741 +}
742 +
743 +
744 +#define OPTSTR "vw"
745 +
746 +int main(int argc, char** argv)
747 +{
748 + int ret;
749 + lt_t wcet;
750 + lt_t period;
751 + int migrate = 0;
752 + int cpu = 0;
753 + int npsf_id;
754 + int opt;
755 + int verbose = 0;
756 + int wait = 0;
757 + startup_info_t info;
758 +
759 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
760 + switch (opt) {
761 + case 'w':
762 + wait = 1;
763 + break;
764 + case 'v':
765 + verbose = 1;
766 + break;
767 + case ':':
768 + usage("Argument missing.");
769 + break;
770 + case '?':
771 + default:
772 + usage("Bad argument.");
773 + break;
774 + }
775 + }
776 +
777 + signal(SIGUSR1, SIG_IGN);
778 +
779 + if (argc - optind < 5)
780 + usage("Arguments missing.");
781 + wcet = ms2lt(atoi(argv[optind + 0]));
782 + period = ms2lt(atoi(argv[optind + 1]));
783 + cpu = atoi(argv[optind + 2]);
784 + migrate = 1;
785 + npsf_id = atoi(argv[optind + 3]);
786 + if (wcet <= 0)
787 + usage("The worst-case execution time must be a "
788 + "positive number.");
789 + if (period <= 0)
790 + usage("The period must be a positive number.");
791 + if (wcet > period) {
792 + usage("The worst-case execution time must not "
793 + "exceed the period.");
794 + }
795 + info.exec_path = argv[optind + 4];
796 + info.argv = argv + optind + 4;
797 + info.wait = wait;
798 + if (migrate) {
799 + ret = be_migrate_to(cpu);
800 + if (ret < 0)
801 + bail_out("could not migrate to target partition");
802 + }
803 + ret = __create_rt_task_npsf(launch, &info, cpu, wcet, period, npsf_id, RT_CLASS_HARD);
804 +
805 +
806 + if (ret < 0)
807 + bail_out("could not create rt child process");
808 + else if (verbose)
809 + printf("%d\n", ret);
810 +
811 + return 0;
812 +}
813 diff --git a/bin/rtspin_edffm.c b/bin/rtspin_edffm.c
814 new file mode 100644
815 index 0000000..5db79b8
816 --- /dev/null
817 +++ b/bin/rtspin_edffm.c
818 @@ -0,0 +1,263 @@
819 +#include <sys/time.h>
820 +
821 +#include <stdio.h>
822 +#include <stdlib.h>
823 +#include <unistd.h>
824 +#include <time.h>
825 +
826 +
827 +#include "litmus.h"
828 +#include "common.h"
829 +
830 +
831 +static double cputime()
832 +{
833 + struct timespec ts;
834 + int err;
835 + err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
836 + if (err != 0)
837 + perror("clock_gettime");
838 + return (ts.tv_sec + 1E-9 * ts.tv_nsec);
839 +}
840 +
841 +static double wctime()
842 +{
843 + struct timeval tv;
844 + gettimeofday(&tv, NULL);
845 + return (tv.tv_sec + 1E-6 * tv.tv_usec);
846 +}
847 +
848 +void usage(char *error) {
849 + fprintf(stderr, "Error: %s\n", error);
850 + fprintf(stderr,
851 + "Usage: rt_spin [-w] [-p PARTITION] [-c CLASS] WCET PERIOD DURATION fracnum1 fracden1 cpu1 fracnum2 fracden2 cpu2\n"
852 + " rt_spin -l\n");
853 + exit(1);
854 +}
855 +
856 +#define NUMS 4096
857 +static int num[NUMS];
858 +static double loop_length = 1.0;
859 +static char* progname;
860 +
861 +static int loop_once(void)
862 +{
863 + int i, j = 0;
864 + for (i = 0; i < NUMS; i++)
865 + j += num[i]++;
866 + return j;
867 +}
868 +
869 +static int loop_for(double exec_time)
870 +{
871 + double t = 0;
872 + int tmp = 0;
873 +/* while (t + loop_length < exec_time) {
874 + tmp += loop_once();
875 + t += loop_length;
876 + }
877 +*/
878 + double start = cputime();
879 + double now = cputime();
880 + while (now + loop_length < start + exec_time) {
881 + tmp += loop_once();
882 + t += loop_length;
883 + now = cputime();
884 + }
885 +
886 + return tmp;
887 +}
888 +
889 +static void fine_tune(double interval)
890 +{
891 + double start, end, delta;
892 +
893 + start = wctime();
894 + loop_for(interval);
895 + end = wctime();
896 + delta = (end - start - interval) / interval;
897 + if (delta != 0)
898 + loop_length = loop_length / (1 - delta);
899 +}
900 +
901 +static void configure_loop(void)
902 +{
903 + double start;
904 +
905 + /* prime cache */
906 + loop_once();
907 + loop_once();
908 + loop_once();
909 +
910 + /* measure */
911 + start = wctime();
912 + loop_once(); /* hope we didn't get preempted */
913 + loop_length = wctime();
914 + loop_length -= start;
915 +
916 + /* fine tune */
917 + fine_tune(0.1);
918 + fine_tune(0.1);
919 + fine_tune(0.1);
920 +}
921 +
922 +static void show_loop_length(void)
923 +{
924 + printf("%s/%d: loop_length=%f (%ldus)\n",
925 + progname, getpid(), loop_length,
926 + (long) (loop_length * 1000000));
927 +}
928 +
929 +static void debug_delay_loop(void)
930 +{
931 + double start, end, delay;
932 + show_loop_length();
933 + while (1) {
934 + for (delay = 0.5; delay > 0.01; delay -= 0.01) {
935 + start = wctime();
936 + loop_for(delay);
937 + end = wctime();
938 + printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
939 + delay,
940 + end - start,
941 + end - start - delay,
942 + 100 * (end - start - delay) / delay);
943 + }
944 + }
945 +}
946 +
947 +static int job(double exec_time)
948 +{
949 + loop_for(exec_time);
950 + sleep_next_period();
951 + return 0;
952 +}
953 +
954 +#define OPTSTR "p:c:wld:v"
955 +
956 +int main(int argc, char** argv)
957 +{
958 + int ret;
959 + lt_t wcet;
960 + lt_t period;
961 + /* [num,den] */
962 + lt_t frac1[2], frac2[2];
963 + int cpu1, cpu2;
964 + double wcet_ms, period_ms;
965 + int migrate = 0;
966 + int cpu = 0;
967 + int opt;
968 + int wait = 0;
969 + int test_loop = 0;
970 + int skip_config = 0;
971 + int verbose = 0;
972 + double duration, start;
973 + task_class_t class = RT_CLASS_HARD;
974 +
975 + progname = argv[0];
976 +
977 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
978 + switch (opt) {
979 + case 'w':
980 + wait = 1;
981 + break;
982 + case 'p':
983 + cpu = atoi(optarg);
984 + migrate = 1;
985 + break;
986 + case 'c':
987 + class = str2class(optarg);
988 + if (class == -1)
989 + usage("Unknown task class.");
990 + break;
991 + case 'l':
992 + test_loop = 1;
993 + break;
994 + case 'd':
995 + /* manually configure delay per loop iteration
996 + * unit: microseconds */
997 + loop_length = atof(optarg) / 1000000;
998 + skip_config = 1;
999 + break;
1000 + case 'v':
1001 + verbose = 1;
1002 + break;
1003 + case ':':
1004 + usage("Argument missing.");
1005 + break;
1006 + case '?':
1007 + default:
1008 + usage("Bad argument.");
1009 + break;
1010 + }
1011 + }
1012 +
1013 +
1014 + if (!skip_config)
1015 + configure_loop();
1016 +
1017 + if (test_loop) {
1018 + debug_delay_loop();
1019 + return 0;
1020 + }
1021 +
1022 + if (argc - optind < 9)
1023 + usage("Arguments missing.");
1024 + wcet_ms = atof(argv[optind + 0]);
1025 + period_ms = atof(argv[optind + 1]);
1026 + duration = atof(argv[optind + 2]);
1027 + /* frac num, den = 0 means fixed task */
1028 + frac1[0] = atoi(argv[optind + 3]);
1029 + frac1[1] = atoi(argv[optind + 4]);
1030 + cpu1 = atoi(argv[optind + 5]);
1031 + frac2[0] = atoi(argv[optind + 6]);
1032 + frac2[1] = atoi(argv[optind + 7]);
1033 + cpu2 = atoi(argv[optind + 8]);
1034 + wcet = wcet_ms * __NS_PER_MS;
1035 + period = period_ms * __NS_PER_MS;
1036 + if (wcet <= 0)
1037 + usage("The worst-case execution time must be a "
1038 + "positive number.");
1039 + if (period <= 0)
1040 + usage("The period must be a positive number.");
1041 + if (wcet > period) {
1042 + usage("The worst-case execution time must not "
1043 + "exceed the period.");
1044 + }
1045 +
1046 + if (migrate) {
1047 + ret = be_migrate_to(cpu);
1048 + if (ret < 0)
1049 + bail_out("could not migrate to target partition");
1050 + }
1051 +
1052 + ret = sporadic_task_ns_edffm(wcet, period, 0, cpu,
1053 + frac1, frac2, cpu1, cpu2,
1054 + class, NO_ENFORCEMENT, migrate);
1055 +
1056 + if (ret < 0)
1057 + bail_out("could not setup rt task params");
1058 +
1059 + if (verbose)
1060 + show_loop_length();
1061 +
1062 + init_litmus();
1063 +
1064 + ret = task_mode(LITMUS_RT_TASK);
1065 + if (ret != 0)
1066 + bail_out("could not become RT task");
1067 +
1068 + if (wait) {
1069 + ret = wait_for_ts_release();
1070 + if (ret != 0)
1071 + bail_out("wait_for_ts_release()");
1072 + }
1073 +
1074 + start = wctime();
1075 +
1076 + while (start + duration > wctime()) {
1077 + job(wcet_ms * 0.0009); /* 90% wcet, in seconds */
1078 + }
1079 +
1080 + return 0;
1081 +}
1082 diff --git a/bin/rtspin_edfos.c b/bin/rtspin_edfos.c
1083 new file mode 100644
1084 index 0000000..3ea41c7
1085 --- /dev/null
1086 +++ b/bin/rtspin_edfos.c
1087 @@ -0,0 +1,267 @@
1088 +#include <sys/time.h>
1089 +
1090 +#include <stdio.h>
1091 +#include <stdlib.h>
1092 +#include <unistd.h>
1093 +#include <time.h>
1094 +
1095 +
1096 +#include "litmus.h"
1097 +#include "common.h"
1098 +
1099 +
1100 +static double cputime()
1101 +{
1102 + struct timespec ts;
1103 + int err;
1104 + err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
1105 + if (err != 0)
1106 + perror("clock_gettime");
1107 + return (ts.tv_sec + 1E-9 * ts.tv_nsec);
1108 +}
1109 +
1110 +static double wctime()
1111 +{
1112 + struct timeval tv;
1113 + gettimeofday(&tv, NULL);
1114 + return (tv.tv_sec + 1E-6 * tv.tv_usec);
1115 +}
1116 +
1117 +void usage(char *error) {
1118 + fprintf(stderr, "Error: %s\n", error);
1119 + fprintf(stderr,
1120 + "Usage: rt_spin [-w] [-p PARTITION] [-c CLASS] WCET PERIOD DURATION fracnum1 fracden1 cpu1 fracnum2 fracden2 cpu2\n"
1121 + " rt_spin -l\n");
1122 + exit(1);
1123 +}
1124 +
1125 +#define NUMS 4096
1126 +static int num[NUMS];
1127 +static double loop_length = 1.0;
1128 +static char* progname;
1129 +
1130 +static int loop_once(void)
1131 +{
1132 + int i, j = 0;
1133 + for (i = 0; i < NUMS; i++)
1134 + j += num[i]++;
1135 + return j;
1136 +}
1137 +
1138 +static int loop_for(double exec_time)
1139 +{
1140 + double t = 0;
1141 + int tmp = 0;
1142 +/* while (t + loop_length < exec_time) {
1143 + tmp += loop_once();
1144 + t += loop_length;
1145 + }
1146 +*/
1147 + double start = cputime();
1148 + double now = cputime();
1149 + while (now + loop_length < start + exec_time) {
1150 + tmp += loop_once();
1151 + t += loop_length;
1152 + now = cputime();
1153 + }
1154 +
1155 + return tmp;
1156 +}
1157 +
1158 +static void fine_tune(double interval)
1159 +{
1160 + double start, end, delta;
1161 +
1162 + start = wctime();
1163 + loop_for(interval);
1164 + end = wctime();
1165 + delta = (end - start - interval) / interval;
1166 + if (delta != 0)
1167 + loop_length = loop_length / (1 - delta);
1168 +}
1169 +
1170 +static void configure_loop(void)
1171 +{
1172 + double start;
1173 +
1174 + /* prime cache */
1175 + loop_once();
1176 + loop_once();
1177 + loop_once();
1178 +
1179 + /* measure */
1180 + start = wctime();
1181 + loop_once(); /* hope we didn't get preempted */
1182 + loop_length = wctime();
1183 + loop_length -= start;
1184 +
1185 + /* fine tune */
1186 + fine_tune(0.1);
1187 + fine_tune(0.1);
1188 + fine_tune(0.1);
1189 +}
1190 +
1191 +static void show_loop_length(void)
1192 +{
1193 + printf("%s/%d: loop_length=%f (%ldus)\n",
1194 + progname, getpid(), loop_length,
1195 + (long) (loop_length * 1000000));
1196 +}
1197 +
1198 +static void debug_delay_loop(void)
1199 +{
1200 + double start, end, delay;
1201 + show_loop_length();
1202 + while (1) {
1203 + for (delay = 0.5; delay > 0.01; delay -= 0.01) {
1204 + start = wctime();
1205 + loop_for(delay);
1206 + end = wctime();
1207 + printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
1208 + delay,
1209 + end - start,
1210 + end - start - delay,
1211 + 100 * (end - start - delay) / delay);
1212 + }
1213 + }
1214 +}
1215 +
1216 +static int job(double exec_time)
1217 +{
1218 + loop_for(exec_time);
1219 + sleep_next_period();
1220 + return 0;
1221 +}
1222 +
1223 +#define OPTSTR "p:c:wld:v"
1224 +
1225 +int main(int argc, char** argv)
1226 +{
1227 + int ret;
1228 + lt_t wcet;
1229 + lt_t period;
1230 + /* [num,den] */
1231 + lt_t fracs[NR_CPUS_EDF_OS][2];
1232 + double wcet_ms, period_ms;
1233 + int cpu = -1;
1234 + int ccpu;
1235 + int opt;
1236 + int wait = 0;
1237 + int test_loop = 0;
1238 + int skip_config = 0;
1239 + int verbose = 0;
1240 + int i;
1241 + double duration, start;
1242 + task_class_t class = RT_CLASS_HARD;
1243 +
1244 + progname = argv[0];
1245 +
1246 + for (i = 0; i < NR_CPUS_EDF_OS; i++) {
1247 + fracs[i][0] = 0;
1248 + fracs[i][1] = 0;
1249 + }
1250 +
1251 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1252 + switch (opt) {
1253 + case 'w':
1254 + wait = 1;
1255 + break;
1256 + case 'p':
1257 + cpu = atoi(optarg);
1258 + fracs[cpu][0] = 1;
1259 + fracs[cpu][1] = 1;
1260 + break;
1261 + case 'c':
1262 + class = str2class(optarg);
1263 + if (class == -1)
1264 + usage("Unknown task class.");
1265 + break;
1266 + case 'l':
1267 + test_loop = 1;
1268 + break;
1269 + case 'd':
1270 + /* manually configure delay per loop iteration
1271 + * unit: microseconds */
1272 + loop_length = atof(optarg) / 1000000;
1273 + skip_config = 1;
1274 + break;
1275 + case 'v':
1276 + verbose = 1;
1277 + break;
1278 + case ':':
1279 + usage("Argument missing.");
1280 + break;
1281 + case '?':
1282 + default:
1283 + usage("Bad argument.");
1284 + break;
1285 + }
1286 + }
1287 +
1288 +
1289 + if (!skip_config)
1290 + configure_loop();
1291 +
1292 + if (test_loop) {
1293 + debug_delay_loop();
1294 + return 0;
1295 + }
1296 +
1297 + if ((argc - (optind + 3)) % 3 != 0)
1298 + usage("Arguments missing.");
1299 + wcet_ms = atof(argv[optind + 0]);
1300 + period_ms = atof(argv[optind + 1]);
1301 + duration = atof(argv[optind + 2]);
1302 + /* frac num, den = 0 means fixed task */
1303 + for (i = optind + 3; i < argc; i += 3) {
1304 + ccpu = atof(argv[i]);
1305 + fracs[ccpu][0] = argv[i+1];
1306 + fracs[ccpu][1] = argv[i+2];
1307 + }
1308 + if (cpu == -1)
1309 + cpu = compute_initial_cpu_edfos(fracs);
1310 + wcet = wcet_ms * __NS_PER_MS;
1311 + period = period_ms * __NS_PER_MS;
1312 + if (wcet <= 0)
1313 + usage("The worst-case execution time must be a "
1314 + "positive number.");
1315 + if (period <= 0)
1316 + usage("The period must be a positive number.");
1317 + if (wcet > period) {
1318 + usage("The worst-case execution time must not "
1319 + "exceed the period.");
1320 + }
1321 +
1322 + ret = be_migrate_to(cpu);
1323 + if (ret < 0)
1324 + bail_out("could not migrate to target partition");
1325 +
1326 + ret = sporadic_task_ns_edfos(wcet, period, 0, cpu, fracs, class,
1327 + NO_ENFORCEMENT);
1328 +
1329 + if (ret < 0)
1330 + bail_out("could not setup rt task params");
1331 +
1332 + if (verbose)
1333 + show_loop_length();
1334 +
1335 + init_litmus();
1336 +
1337 + ret = task_mode(LITMUS_RT_TASK);
1338 + if (ret != 0)
1339 + bail_out("could not become RT task");
1340 +
1341 + if (wait) {
1342 + ret = wait_for_ts_release();
1343 + if (ret != 0)
1344 + bail_out("wait_for_ts_release()");
1345 + }
1346 +
1347 + start = wctime();
1348 +
1349 + while (start + duration > wctime()) {
1350 + job(wcet_ms * 0.0009); /* 90% wcet, in seconds */
1351 + }
1352 +
1353 + return 0;
1354 +}
1355 diff --git a/bin/rtspin_edfwm.c b/bin/rtspin_edfwm.c
1356 new file mode 100644
1357 index 0000000..21a5f3b
1358 --- /dev/null
1359 +++ b/bin/rtspin_edfwm.c
1360 @@ -0,0 +1,233 @@
1361 +#include <sys/time.h>
1362 +
1363 +#include <stdio.h>
1364 +#include <stdlib.h>
1365 +#include <unistd.h>
1366 +#include <time.h>
1367 +#include <string.h>
1368 +
1369 +#include "litmus.h"
1370 +#include "common.h"
1371 +
1372 +
1373 +static double cputime()
1374 +{
1375 + struct timespec ts;
1376 + int err;
1377 + err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
1378 + if (err != 0)
1379 + perror("clock_gettime");
1380 + return (ts.tv_sec + 1E-9 * ts.tv_nsec);
1381 +}
1382 +
1383 +static double wctime()
1384 +{
1385 + struct timeval tv;
1386 + gettimeofday(&tv, NULL);
1387 + return (tv.tv_sec + 1E-6 * tv.tv_usec);
1388 +}
1389 +
1390 +void usage(char *error) {
1391 + fprintf(stderr, "Error: %s\n", error);
1392 + fprintf(stderr,
1393 + "Usage: rt_spin [-w] task_parameters_file duration\n"
1394 + " rt_spin -l\n");
1395 + exit(1);
1396 +}
1397 +
1398 +#define NUMS 4096
1399 +static int num[NUMS];
1400 +static double loop_length = 1.0;
1401 +static char* progname;
1402 +
1403 +static int loop_once(void)
1404 +{
1405 + int i, j = 0;
1406 + for (i = 0; i < NUMS; i++)
1407 + j += num[i]++;
1408 + return j;
1409 +}
1410 +
1411 +static int loop_for(double exec_time)
1412 +{
1413 + double t = 0;
1414 + int tmp = 0;
1415 +/* while (t + loop_length < exec_time) {
1416 + tmp += loop_once();
1417 + t += loop_length;
1418 + }
1419 +*/
1420 + double start = cputime();
1421 + double now = cputime();
1422 + while (now + loop_length < start + exec_time) {
1423 + tmp += loop_once();
1424 + t += loop_length;
1425 + now = cputime();
1426 + }
1427 +
1428 + return tmp;
1429 +}
1430 +
1431 +static void fine_tune(double interval)
1432 +{
1433 + double start, end, delta;
1434 +
1435 + start = wctime();
1436 + loop_for(interval);
1437 + end = wctime();
1438 + delta = (end - start - interval) / interval;
1439 + if (delta != 0)
1440 + loop_length = loop_length / (1 - delta);
1441 +}
1442 +
1443 +static void configure_loop(void)
1444 +{
1445 + double start;
1446 +
1447 + /* prime cache */
1448 + loop_once();
1449 + loop_once();
1450 + loop_once();
1451 +
1452 + /* measure */
1453 + start = wctime();
1454 + loop_once(); /* hope we didn't get preempted */
1455 + loop_length = wctime();
1456 + loop_length -= start;
1457 +
1458 + /* fine tune */
1459 + fine_tune(0.1);
1460 + fine_tune(0.1);
1461 + fine_tune(0.1);
1462 +}
1463 +
1464 +static void show_loop_length(void)
1465 +{
1466 + printf("%s/%d: loop_length=%f (%ldus)\n",
1467 + progname, getpid(), loop_length,
1468 + (long) (loop_length * 1000000));
1469 +}
1470 +
1471 +static void debug_delay_loop(void)
1472 +{
1473 + double start, end, delay;
1474 + show_loop_length();
1475 + while (1) {
1476 + for (delay = 0.5; delay > 0.01; delay -= 0.01) {
1477 + start = wctime();
1478 + loop_for(delay);
1479 + end = wctime();
1480 + printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
1481 + delay,
1482 + end - start,
1483 + end - start - delay,
1484 + 100 * (end - start - delay) / delay);
1485 + }
1486 + }
1487 +}
1488 +
1489 +static int job(double exec_time)
1490 +{
1491 + loop_for(exec_time);
1492 + sleep_next_period();
1493 + return 0;
1494 +}
1495 +
1496 +#define OPTSTR "wld:v"
1497 +
1498 +int main(int argc, char** argv)
1499 +{
1500 + int ret;
1501 +
1502 + int opt;
1503 + int wait = 0;
1504 + int test_loop = 0;
1505 + int skip_config = 0;
1506 + int verbose = 0;
1507 + double wcet_ms;
1508 + double duration, start;
1509 +
1510 + struct rt_task rt;
1511 + FILE *file;
1512 +
1513 + progname = argv[0];
1514 +
1515 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1516 + switch (opt) {
1517 + case 'w':
1518 + wait = 1;
1519 + break;
1520 + case 'l':
1521 + test_loop = 1;
1522 + break;
1523 + case 'd':
1524 + /* manually configure delay per loop iteration
1525 + * unit: microseconds */
1526 + loop_length = atof(optarg) / 1000000;
1527 + skip_config = 1;
1528 + break;
1529 + case 'v':
1530 + verbose = 1;
1531 + break;
1532 + case ':':
1533 + usage("Argument missing.");
1534 + break;
1535 + case '?':
1536 + default:
1537 + usage("Bad argument.");
1538 + break;
1539 + }
1540 + }
1541 +
1542 +
1543 + if (!skip_config)
1544 + configure_loop();
1545 +
1546 + if (test_loop) {
1547 + debug_delay_loop();
1548 + return 0;
1549 + }
1550 +
1551 + if (argc - optind < 2)
1552 + usage("Arguments missing.");
1553 +
1554 + if ((file = fopen(argv[optind + 0], "r")) == NULL) {
1555 + fprintf(stderr, "Cannot open %s\n", argv[1]);
1556 + return -1;
1557 + }
1558 + duration = atof(argv[optind + 1]);
1559 +
1560 + memset(&rt, 0, sizeof(struct rt_task));
1561 +
1562 + if (parse_edfwm_ts_file(file, &rt) < 0)
1563 + bail_out("Could not parse file\n");
1564 +
1565 + if (sporadic_task_ns_semi(&rt) < 0)
1566 + bail_out("could not setup rt task params");
1567 +
1568 + fclose(file);
1569 +
1570 + if (verbose)
1571 + show_loop_length();
1572 +
1573 + init_litmus();
1574 +
1575 + ret = task_mode(LITMUS_RT_TASK);
1576 + if (ret != 0)
1577 + bail_out("could not become RT task");
1578 +
1579 + if (wait) {
1580 + ret = wait_for_ts_release();
1581 + if (ret != 0)
1582 + bail_out("wait_for_ts_release()");
1583 + }
1584 +
1585 + wcet_ms = ((double) rt.exec_cost ) / __NS_PER_MS;
1586 + start = wctime();
1587 +
1588 + while (start + duration > wctime()) {
1589 + job(wcet_ms * 0.0009); /* 90% wcet, in seconds */
1590 + }
1591 +
1592 + return 0;
1593 +}
1594 diff --git a/bin/rtspin_npsf.c b/bin/rtspin_npsf.c
1595 new file mode 100644
1596 index 0000000..d5dff3d
1597 --- /dev/null
1598 +++ b/bin/rtspin_npsf.c
1599 @@ -0,0 +1,252 @@
1600 +#include <sys/time.h>
1601 +
1602 +#include <stdio.h>
1603 +#include <stdlib.h>
1604 +#include <unistd.h>
1605 +#include <time.h>
1606 +
1607 +
1608 +#include "litmus.h"
1609 +#include "common.h"
1610 +
1611 +
1612 +static double cputime()
1613 +{
1614 + struct timespec ts;
1615 + int err;
1616 + err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
1617 + if (err != 0)
1618 + perror("clock_gettime");
1619 + return (ts.tv_sec + 1E-9 * ts.tv_nsec);
1620 +}
1621 +
1622 +static double wctime()
1623 +{
1624 + struct timeval tv;
1625 + gettimeofday(&tv, NULL);
1626 + return (tv.tv_sec + 1E-6 * tv.tv_usec);
1627 +}
1628 +
1629 +void usage(char *error) {
1630 + fprintf(stderr, "Error: %s\n", error);
1631 + fprintf(stderr,
1632 + "Usage: rt_spin [-w] WCET PERIOD DURATION CPU NPSF-ID\n"
1633 + " rt_spin -l\n");
1634 + exit(1);
1635 +}
1636 +
1637 +#define NUMS 4096
1638 +static int num[NUMS];
1639 +static double loop_length = 1.0;
1640 +static char* progname;
1641 +
1642 +static int loop_once(void)
1643 +{
1644 + int i, j = 0;
1645 + for (i = 0; i < NUMS; i++)
1646 + j += num[i]++;
1647 + return j;
1648 +}
1649 +
1650 +static int loop_for(double exec_time)
1651 +{
1652 + double t = 0;
1653 + int tmp = 0;
1654 +/* while (t + loop_length < exec_time) {
1655 + tmp += loop_once();
1656 + t += loop_length;
1657 + }
1658 +*/
1659 + double start = cputime();
1660 + double now = cputime();
1661 + while (now + loop_length < start + exec_time) {
1662 + tmp += loop_once();
1663 + t += loop_length;
1664 + now = cputime();
1665 + }
1666 +
1667 + return tmp;
1668 +}
1669 +
1670 +static void fine_tune(double interval)
1671 +{
1672 + double start, end, delta;
1673 +
1674 + start = wctime();
1675 + loop_for(interval);
1676 + end = wctime();
1677 + delta = (end - start - interval) / interval;
1678 + if (delta != 0)
1679 + loop_length = loop_length / (1 - delta);
1680 +}
1681 +
1682 +static void configure_loop(void)
1683 +{
1684 + double start;
1685 +
1686 + /* prime cache */
1687 + loop_once();
1688 + loop_once();
1689 + loop_once();
1690 +
1691 + /* measure */
1692 + start = wctime();
1693 + loop_once(); /* hope we didn't get preempted */
1694 + loop_length = wctime();
1695 + loop_length -= start;
1696 +
1697 + /* fine tune */
1698 + fine_tune(0.1);
1699 + fine_tune(0.1);
1700 + fine_tune(0.1);
1701 +}
1702 +
1703 +static void show_loop_length(void)
1704 +{
1705 + printf("%s/%d: loop_length=%f (%ldus)\n",
1706 + progname, getpid(), loop_length,
1707 + (long) (loop_length * 1000000));
1708 +}
1709 +
1710 +static void debug_delay_loop(void)
1711 +{
1712 + double start, end, delay;
1713 + show_loop_length();
1714 + while (1) {
1715 + for (delay = 0.5; delay > 0.01; delay -= 0.01) {
1716 + start = wctime();
1717 + loop_for(delay);
1718 + end = wctime();
1719 + printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
1720 + delay,
1721 + end - start,
1722 + end - start - delay,
1723 + 100 * (end - start - delay) / delay);
1724 + }
1725 + }
1726 +}
1727 +
1728 +static int job(double exec_time)
1729 +{
1730 + loop_for(exec_time);
1731 + sleep_next_period();
1732 + return 0;
1733 +}
1734 +
1735 +#define OPTSTR "c:wld:v"
1736 +
1737 +int main(int argc, char** argv)
1738 +{
1739 + int ret;
1740 + lt_t wcet;
1741 + lt_t period;
1742 + double wcet_ms, period_ms;
1743 + int migrate = 0;
1744 + int cpu = 0;
1745 + int npsf_id = 0;
1746 + int opt;
1747 + int wait = 0;
1748 + int test_loop = 0;
1749 + int skip_config = 0;
1750 + int verbose = 0;
1751 + double duration, start;
1752 + task_class_t class = RT_CLASS_HARD;
1753 +
1754 + progname = argv[0];
1755 +
1756 + while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1757 + switch (opt) {
1758 + case 'w':
1759 + wait = 1;
1760 + break;
1761 + case 'c':
1762 + class = str2class(optarg);
1763 + if (class == -1)
1764 + usage("Unknown task class.");
1765 + break;
1766 + case 'l':
1767 + test_loop = 1;
1768 + break;
1769 + case 'd':
1770 + /* manually configure delay per loop iteration
1771 + * unit: microseconds */
1772 + loop_length = atof(optarg) / 1000000;
1773 + skip_config = 1;
1774 + break;
1775 + case 'v':
1776 + verbose = 1;
1777 + break;
1778 + case ':':
1779 + usage("Argument missing.");
1780 + break;
1781 + case '?':
1782 + default:
1783 + usage("Bad argument.");
1784 + break;
1785 + }
1786 + }
1787 +
1788 +
1789 + if (!skip_config)
1790 + configure_loop();
1791 +
1792 + if (test_loop) {
1793 + debug_delay_loop();
1794 + return 0;
1795 + }
1796 +
1797 + if (argc - optind < 5)
1798 + usage("Arguments missing.");
1799 + wcet_ms = atof(argv[optind + 0]);
1800 + period_ms = atof(argv[optind + 1]);
1801 + duration = atof(argv[optind + 2]);
1802 + cpu = atoi(argv[optind + 3]);
1803 + migrate = 1;
1804 + npsf_id = atoi(argv[optind + 4]);
1805 + wcet = wcet_ms * __NS_PER_MS;
1806 + period = period_ms * __NS_PER_MS;
1807 + if (wcet <= 0)
1808 + usage("The worst-case execution time must be a "
1809 + "positive number.");
1810 + if (period <= 0)
1811 + usage("The period must be a positive number.");
1812 + if (wcet > period) {
1813 + usage("The worst-case execution time must not "
1814 + "exceed the period.");
1815 + }
1816 +
1817 + if (migrate) {
1818 + ret = be_migrate_to(cpu);
1819 + if (ret < 0)
1820 + bail_out("could not migrate to target partition");
1821 + }
1822 +
1823 + ret = sporadic_task_ns_npsf(wcet, period, 0, cpu, class, npsf_id,
1824 + NO_ENFORCEMENT, migrate);
1825 +
1826 + if (ret < 0)
1827 + bail_out("could not setup rt task params");
1828 +
1829 + if (verbose)
1830 + show_loop_length();
1831 +
1832 + init_litmus();
1833 +
1834 + ret = task_mode(LITMUS_RT_TASK);
1835 + if (ret != 0)
1836 + bail_out("could not become RT task");
1837 +
1838 + if (wait) {
1839 + ret = wait_for_ts_release();
1840 + if (ret != 0)
1841 + bail_out("wait_for_ts_release()");
1842 + }
1843 +
1844 + start = wctime();
1845 +
1846 + while (start + duration > wctime()) {
1847 + job(wcet_ms * 0.0009); /* 90% wcet, in seconds */
1848 + }
1849 +
1850 + return 0;
1851 +}
1852 diff --git a/include/common.h b/include/common.h
1853 index d1234ba..dbcfd34 100644
1854 --- a/include/common.h
1855 +++ b/include/common.h
1856 @@ -1,7 +1,11 @@
1857 #ifndef COMMON_H
1858 #define COMMON_H
1859
1860 +#include "litmus.h"
1861
1862 void bail_out(const char* msg);
1863
1864 +/* EDF-WM helper functions to parse task parameters from file */
1865 +int parse_edfwm_ts_file(FILE *ts, struct rt_task *rt);
1866 +
1867 #endif
1868 diff --git a/include/litmus.h b/include/litmus.h
1869 index b798c92..0139d25 100644
1870 --- a/include/litmus.h
1871 +++ b/include/litmus.h
1872 @@ -5,10 +5,12 @@
1873 extern "C" {
1874 #endif
1875
1876 +#include <limits.h>
1877 /* Include kernel header.
1878 * This is required for the rt_param
1879 * and control_page structures.
1880 */
1881 +#include <linux/threads.h>
1882 #include <litmus/rt_param.h>
1883
1884 #include <sys/types.h>
1885 @@ -28,6 +30,8 @@ int get_rt_task_param(pid_t pid, struct rt_task* param);
1886
1887 /* setup helper */
1888
1889 +unsigned int compute_initial_cpu_edfos(lt_t fracs[][2]);
1890 +
1891 /* times are given in ms */
1892 int sporadic_task(
1893 lt_t e, lt_t p, lt_t phase,
1894 @@ -40,6 +44,23 @@ int sporadic_task_ns(
1895 int cpu, task_class_t cls,
1896 budget_policy_t budget_policy, int set_cpu_set);
1897
1898 +int sporadic_task_ns_edffm(lt_t e, lt_t p, lt_t phase, int cpu,
1899 + lt_t *frac1, lt_t *frac2, int cpu1, int cpu2,
1900 + task_class_t cls, budget_policy_t budget_policy,
1901 + int set_cpu_set);
1902 +
1903 +int sporadic_task_ns_edfos(lt_t e, lt_t p, lt_t phase, int cpu,
1904 + lt_t fracs[][2], task_class_t cls,
1905 + budget_policy_t budget_policy);
1906 +
1907 +int sporadic_task_ns_npsf(
1908 + lt_t e, lt_t p, lt_t phase,
1909 + int cpu, task_class_t cls, int npsf_id,
1910 + budget_policy_t budget_policy, int set_cpu_set);
1911 +
1912 +/* times are in ns, specific helper for semi-partitioned algos */
1913 +int sporadic_task_ns_semi(struct rt_task *rt);
1914 +
1915 /* budget enforcement off by default in these macros */
1916 #define sporadic_global(e, p) \
1917 sporadic_task(e, p, 0, 0, RT_CLASS_SOFT, NO_ENFORCEMENT, 0)
1918 @@ -85,6 +106,19 @@ typedef int (*rt_fn_t)(void*);
1919 int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period);
1920 int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
1921 int period, task_class_t cls);
1922 +int __create_rt_task_edffm(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
1923 + int period, lt_t *frac1, lt_t *frac2,
1924 + int cpu1, int cpu2, task_class_t class);
1925 +int __create_rt_task_edfos(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
1926 + int period, lt_t fracs[][2], task_class_t class);
1927 +int __create_rt_task_npsf(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
1928 + int period, int npsf_id, task_class_t class);
1929 +
1930 +/* wrapper to mask __launch_rt_task() for semi-partitioned algorithms
1931 + * (it can be extended to cover all algorithms that directly submit
1932 + * an rt_task structure instead of a set of values).
1933 + */
1934 +int create_rt_task_semi(rt_fn_t rt_prog, void *arg, struct rt_task *params);
1935
1936 /* per-task modes */
1937 enum rt_task_mode_t {
1938 @@ -134,6 +168,21 @@ int null_call(cycles_t *timestamp);
1939 */
1940 struct control_page* get_ctrl_page(void);
1941
1942 +/* NPS-F syscall to add a notional processor (a server) to a cpu.
1943 + * A notional processor may span across multiple cpu.
1944 + *
1945 + * @npsf_id: a "unique" identifier for the notional processor.
1946 + * @budgets: array of (cpu, budget-ns) that describes this np.
1947 + * on possibly more than one cpu.
1948 + * @last: marks the end of servers initialization and trigger
1949 + * the switching of servers in the plugin.
1950 + * Should be set to 1 only once at the end of the sequence
1951 + * of add_server() calls
1952 + *
1953 + * Currently implemented on x86_64 only.
1954 + */
1955 +int add_server(int *npsf_id, struct npsf_budgets *budgets, int last);
1956 +
1957 #ifdef __cplusplus
1958 }
1959 #endif
1960 diff --git a/src/litmus.c b/src/litmus.c
1961 index d3cc6bb..f7c91de 100644
1962 --- a/src/litmus.c
1963 +++ b/src/litmus.c
1964 @@ -29,8 +29,6 @@ task_class_t str2class(const char* str)
1965 return -1;
1966 }
1967
1968 -#define NS_PER_MS 1000000
1969 -
1970 /* only for best-effort execution: migrate to target_cpu */
1971 int be_migrate_to(int target_cpu)
1972 {
1973 @@ -41,11 +39,38 @@ int be_migrate_to(int target_cpu)
1974 return sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set);
1975 }
1976
1977 +static unsigned int compute_pfair_deadline(lt_t wt_num, lt_t wt_den)
1978 +{
1979 + int dead;
1980 + dead = wt_den / wt_num;
1981 + if (wt_den % wt_num > 0)
1982 + dead++;
1983 + return dead;
1984 +}
1985 +
1986 +unsigned int compute_initial_cpu_edfos(lt_t fracs[][2])
1987 +{
1988 + int initial_cpu = -1;
1989 + int lowest_deadline = UINT_MAX;
1990 + int current_deadline, i;
1991 + for (i = 0; i < NR_CPUS_EDF_OS; i++) {
1992 + if (fracs[i][0] > 0) {
1993 + current_deadline = compute_pfair_deadline(fracs[i][0],
1994 + fracs[i][1]);
1995 + if (current_deadline < lowest_deadline) {
1996 + lowest_deadline = current_deadline;
1997 + initial_cpu = i;
1998 + }
1999 + }
2000 + }
2001 + return initial_cpu;
2002 +}
2003 +
2004 int sporadic_task(lt_t e, lt_t p, lt_t phase,
2005 int cpu, task_class_t cls,
2006 budget_policy_t budget_policy, int set_cpu_set)
2007 {
2008 - return sporadic_task_ns(e * NS_PER_MS, p * NS_PER_MS, phase * NS_PER_MS,
2009 + return sporadic_task_ns(e * __NS_PER_MS, p * __NS_PER_MS, phase * __NS_PER_MS,
2010 cpu, cls, budget_policy, set_cpu_set);
2011 }
2012
2013 @@ -75,6 +100,101 @@ int sporadic_task_ns(lt_t e, lt_t p, lt_t phase,
2014 return set_rt_task_param(gettid(), ¶m);
2015 }
2016
2017 +int sporadic_task_ns_edffm(lt_t e, lt_t p, lt_t phase, int cpu,
2018 + lt_t *frac1, lt_t *frac2, int cpu1, int cpu2,
2019 + task_class_t cls, budget_policy_t budget_policy,
2020 + int set_cpu_set)
2021 +{
2022 + struct rt_task param;
2023 + struct edffm_params fm;
2024 + int ret;
2025 + param.exec_cost = e;
2026 + param.period = p;
2027 + param.cpu = cpu;
2028 + /* check on denominators */
2029 + if (frac1[1] != 0 && frac2[1] != 0) {
2030 + /* edf-fm migrat task */
2031 + fm.nr_cpus = 1;
2032 + fm.cpus[0] = cpu1;
2033 + fm.cpus[1] = cpu2;
2034 + fm.fraction[0][0] = frac1[0];
2035 + fm.fraction[1][0] = frac1[1];
2036 + fm.fraction[0][1] = frac2[0];
2037 + fm.fraction[1][1] = frac2[1];
2038 + }
2039 + param.semi_part.fm = fm;
2040 + param.cls = cls;
2041 + param.phase = phase;
2042 + param.budget_policy = budget_policy;
2043 +
2044 + if (set_cpu_set) {
2045 + ret = be_migrate_to(cpu);
2046 + check("migrate to cpu");
2047 + }
2048 + return set_rt_task_param(gettid(), ¶m);
2049 +}
2050 +
2051 +int sporadic_task_ns_edfos(lt_t e, lt_t p, lt_t phase, int cpu,
2052 + lt_t fracs[][2], task_class_t cls,
2053 + budget_policy_t budget_policy)
2054 +{
2055 + struct rt_task param;
2056 + struct edfos_params os;
2057 + int ret, i;
2058 + os.migrat = 0;
2059 + os.first_cpu = UINT_MAX;
2060 + param.exec_cost = e;
2061 + param.period = p;
2062 + param.cpu = cpu;
2063 + for (i = 0; i < NR_CPUS_EDF_OS; i++) {
2064 + if (fracs[i][0] > 0) {
2065 + os.migrat++;
2066 + if (os.first_cpu == UINT_MAX)
2067 + os.first_cpu = i;
2068 + }
2069 + os.fraction[i][0] = fracs[i][0];
2070 + os.fraction[i][1] = fracs[i][1];
2071 + }
2072 + param.semi_part.os = os;
2073 + param.cls = cls;
2074 + param.phase = phase;
2075 + param.budget_policy = budget_policy;
2076 +
2077 + return set_rt_task_param(gettid(), ¶m);
2078 +}
2079 +
2080 +int sporadic_task_ns_npsf(lt_t e, lt_t p, lt_t phase,
2081 + int cpu, task_class_t cls, int npsf_id,
2082 + budget_policy_t budget_policy, int set_cpu_set)
2083 +{
2084 + struct rt_task param;
2085 + int ret;
2086 + param.exec_cost = e;
2087 + param.period = p;
2088 + param.cpu = cpu;
2089 + param.cls = cls;
2090 + param.phase = phase;
2091 + param.budget_policy = budget_policy;
2092 + param.semi_part.npsf_id = (int) npsf_id;
2093 +
2094 + if (set_cpu_set) {
2095 + ret = be_migrate_to(cpu);
2096 + check("migrate to cpu");
2097 + }
2098 + return set_rt_task_param(gettid(), ¶m);
2099 +}
2100 +
2101 +/* Sporadic task helper function for Semi-Partitioned algorithms. */
2102 +int sporadic_task_ns_semi(struct rt_task *param)
2103 +{
2104 + int ret;
2105 +
2106 + ret = be_migrate_to(param->cpu);
2107 + check("migrate to cpu");
2108 +
2109 + return set_rt_task_param(gettid(), param);
2110 +}
2111 +
2112 int init_kernel_iface(void);
2113
2114 int init_litmus(void)
2115 diff --git a/src/syscalls.c b/src/syscalls.c
2116 index 77a6277..7ac488a 100644
2117 --- a/src/syscalls.c
2118 +++ b/src/syscalls.c
2119 @@ -95,3 +95,8 @@ int null_call(cycles_t *timestamp)
2120 {
2121 return syscall(__NR_null_call, timestamp);
2122 }
2123 +
2124 +int add_server(int *npsf_id, struct npsf_budgets *budgets, int last)
2125 +{
2126 + return syscall(__NR_add_server, npsf_id, budgets, last);
2127 +}
2128 diff --git a/src/task.c b/src/task.c
2129 index 4d237bd..8b4287c 100644
2130 --- a/src/task.c
2131 +++ b/src/task.c
2132 @@ -40,6 +40,85 @@ int __launch_rt_task(rt_fn_t rt_prog, void *rt_arg, rt_setup_fn_t setup,
2133 return rt_task;
2134 }
2135
2136 +int __create_rt_task_edffm(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
2137 + int period, lt_t *frac1, lt_t *frac2,
2138 + int cpu1, int cpu2, task_class_t class)
2139 +{
2140 + struct rt_task params;
2141 + struct edffm_params fm;
2142 + params.cpu = cpu;
2143 + params.period = period;
2144 + params.exec_cost = wcet;
2145 + params.cls = class;
2146 + params.phase = 0;
2147 + /* enforce budget for tasks that might not use sleep_next_period() */
2148 + params.budget_policy = QUANTUM_ENFORCEMENT;
2149 +
2150 + /* edf-fm check on denominators for migratory tasks */
2151 + if (frac1[1] != 0 && frac2[1] != 0) {
2152 + /* edf-fm migrat task */
2153 + fm.nr_cpus = 1;
2154 + fm.cpus[0] = cpu1;
2155 + fm.cpus[1] = cpu2;
2156 + fm.fraction[0][0] = frac1[0];
2157 + fm.fraction[1][0] = frac1[1];
2158 + fm.fraction[0][1] = frac2[0];
2159 + fm.fraction[1][1] = frac2[1];
2160 + }
2161 + params.semi_part.fm = fm;
2162 +
2163 + return __launch_rt_task(rt_prog, arg,
2164 + (rt_setup_fn_t) set_rt_task_param, ¶ms);
2165 +}
2166 +
2167 +int __create_rt_task_edfos(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
2168 + int period, lt_t fracs[][2], task_class_t class)
2169 +{
2170 + struct rt_task params;
2171 + struct edfos_params os;
2172 + int i;
2173 + params.cpu = cpu;
2174 + params.period = period;
2175 + params.exec_cost = wcet;
2176 + params.cls = class;
2177 + params.phase = 0;
2178 + /* enforce budget for tasks that might not use sleep_next_period() */
2179 + params.budget_policy = QUANTUM_ENFORCEMENT;
2180 +
2181 + os.migrat = 0;
2182 + os.first_cpu = UINT_MAX;
2183 + for (i = 0; i < NR_CPUS_EDF_OS; i++) {
2184 + if (fracs[i][0] > 0) {
2185 + os.migrat++;
2186 + if (os.first_cpu == UINT_MAX)
2187 + os.first_cpu = i;
2188 + }
2189 + os.fraction[i][0] = fracs[i][0];
2190 + os.fraction[i][1] = fracs[i][1];
2191 + }
2192 + params.semi_part.os = os;
2193 +
2194 + return __launch_rt_task(rt_prog, arg,
2195 + (rt_setup_fn_t) set_rt_task_param, ¶ms);
2196 +}
2197 +
2198 +int __create_rt_task_npsf(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
2199 + int period, int npsf_id, task_class_t class)
2200 +{
2201 + struct rt_task params;
2202 + params.cpu = cpu;
2203 + params.period = period;
2204 + params.exec_cost = wcet;
2205 + params.cls = class;
2206 + params.phase = 0;
2207 + /* enforce budget for tasks that might not use sleep_next_period() */
2208 + params.budget_policy = QUANTUM_ENFORCEMENT;
2209 + params.semi_part.npsf_id = (int) npsf_id;
2210 +
2211 + return __launch_rt_task(rt_prog, arg,
2212 + (rt_setup_fn_t) set_rt_task_param, ¶ms);
2213 +}
2214 +
2215 int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period,
2216 task_class_t class)
2217 {
2218 @@ -60,6 +139,11 @@ int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period) {
2219 return __create_rt_task(rt_prog, arg, cpu, wcet, period, RT_CLASS_HARD);
2220 }
2221
2222 +int create_rt_task_semi(rt_fn_t rt_prog, void *arg, struct rt_task *params)
2223 +{
2224 + return __launch_rt_task(rt_prog, arg,
2225 + (rt_setup_fn_t) set_rt_task_param, params);
2226 +}
2227
2228 #define SCHED_NORMAL 0
2229 #define SCHED_LITMUS 6
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.