diff options
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | bin/mc2spin.c | 541 | ||||
-rw-r--r-- | include/litmus.h | 3 | ||||
-rwxr-xr-x | mc2spin | bin | 0 -> 102692 bytes | |||
-rw-r--r-- | src/syscalls.c | 5 |
5 files changed, 554 insertions, 2 deletions
@@ -73,7 +73,7 @@ AR := ${CROSS_COMPILE}${AR} | |||
73 | 73 | ||
74 | all = lib ${rt-apps} | 74 | all = lib ${rt-apps} |
75 | rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \ | 75 | rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \ |
76 | base_mt_task uncache runtests resctrl | 76 | base_mt_task uncache runtests resctrl mc2spin |
77 | 77 | ||
78 | .PHONY: all lib clean dump-config TAGS tags cscope help doc | 78 | .PHONY: all lib clean dump-config TAGS tags cscope help doc |
79 | 79 | ||
@@ -168,7 +168,8 @@ litmus-headers = \ | |||
168 | include/litmus/rt_param.h \ | 168 | include/litmus/rt_param.h \ |
169 | include/litmus/fpmath.h \ | 169 | include/litmus/fpmath.h \ |
170 | include/litmus/unistd_32.h \ | 170 | include/litmus/unistd_32.h \ |
171 | include/litmus/unistd_64.h | 171 | include/litmus/unistd_64.h \ |
172 | include/litmus/mc2_common.h | ||
172 | 173 | ||
173 | unistd-headers = \ | 174 | unistd-headers = \ |
174 | $(foreach file,${unistd-${ARCH}},arch/${include-${ARCH}}/include/$(file)) | 175 | $(foreach file,${unistd-${ARCH}},arch/${include-${ARCH}}/include/$(file)) |
@@ -236,6 +237,8 @@ lib-measure_syscall = -lm | |||
236 | 237 | ||
237 | obj-resctrl = resctrl.o | 238 | obj-resctrl = resctrl.o |
238 | 239 | ||
240 | obj-mc2spin = mc2spin.o common.o | ||
241 | lib-mc2spin = -lrt | ||
239 | 242 | ||
240 | # ############################################################################## | 243 | # ############################################################################## |
241 | # Build everything that depends on liblitmus. | 244 | # Build everything that depends on liblitmus. |
diff --git a/bin/mc2spin.c b/bin/mc2spin.c new file mode 100644 index 0000000..1ef3082 --- /dev/null +++ b/bin/mc2spin.c | |||
@@ -0,0 +1,541 @@ | |||
1 | #include <sys/time.h> | ||
2 | |||
3 | #include <stdio.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <unistd.h> | ||
6 | #include <time.h> | ||
7 | #include <string.h> | ||
8 | #include <assert.h> | ||
9 | #include <limits.h> | ||
10 | |||
11 | |||
12 | #include "litmus.h" | ||
13 | #include "common.h" | ||
14 | |||
15 | |||
16 | |||
17 | static void usage(char *error) { | ||
18 | fprintf(stderr, "Error: %s\n", error); | ||
19 | fprintf(stderr, | ||
20 | "Usage:\n" | ||
21 | " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n" | ||
22 | " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n" | ||
23 | " rt_spin -l\n" | ||
24 | "\n" | ||
25 | "COMMON-OPTS = [-w] [-s SCALE]\n" | ||
26 | " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n" | ||
27 | " [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n" | ||
28 | " [-i [start,end]:[start,end]...]\n" | ||
29 | "\n" | ||
30 | "WCET and PERIOD are milliseconds, DURATION is seconds.\n" | ||
31 | "CRITICAL SECTION LENGTH is in milliseconds.\n"); | ||
32 | exit(EXIT_FAILURE); | ||
33 | } | ||
34 | |||
35 | /* | ||
36 | * returns the character that made processing stop, newline or EOF | ||
37 | */ | ||
38 | static int skip_to_next_line(FILE *fstream) | ||
39 | { | ||
40 | int ch; | ||
41 | for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream)); | ||
42 | return ch; | ||
43 | } | ||
44 | |||
45 | static void skip_comments(FILE *fstream) | ||
46 | { | ||
47 | int ch; | ||
48 | for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream)) | ||
49 | skip_to_next_line(fstream); | ||
50 | ungetc(ch, fstream); | ||
51 | } | ||
52 | |||
53 | static void get_exec_times(const char *file, const int column, | ||
54 | int *num_jobs, double **exec_times) | ||
55 | { | ||
56 | FILE *fstream; | ||
57 | int cur_job, cur_col, ch; | ||
58 | *num_jobs = 0; | ||
59 | |||
60 | fstream = fopen(file, "r"); | ||
61 | if (!fstream) | ||
62 | bail_out("could not open execution time file"); | ||
63 | |||
64 | /* figure out the number of jobs */ | ||
65 | do { | ||
66 | skip_comments(fstream); | ||
67 | ch = skip_to_next_line(fstream); | ||
68 | if (ch != EOF) | ||
69 | ++(*num_jobs); | ||
70 | } while (ch != EOF); | ||
71 | |||
72 | if (-1 == fseek(fstream, 0L, SEEK_SET)) | ||
73 | bail_out("rewinding file failed"); | ||
74 | |||
75 | /* allocate space for exec times */ | ||
76 | *exec_times = calloc(*num_jobs, sizeof(*exec_times)); | ||
77 | if (!*exec_times) | ||
78 | bail_out("couldn't allocate memory"); | ||
79 | |||
80 | for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) { | ||
81 | |||
82 | skip_comments(fstream); | ||
83 | |||
84 | for (cur_col = 1; cur_col < column; ++cur_col) { | ||
85 | /* discard input until we get to the column we want */ | ||
86 | int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,"); | ||
87 | } | ||
88 | |||
89 | /* get the desired exec. time */ | ||
90 | if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) { | ||
91 | fprintf(stderr, "invalid execution time near line %d\n", | ||
92 | cur_job); | ||
93 | exit(EXIT_FAILURE); | ||
94 | } | ||
95 | |||
96 | skip_to_next_line(fstream); | ||
97 | } | ||
98 | |||
99 | assert(cur_job == *num_jobs); | ||
100 | fclose(fstream); | ||
101 | } | ||
102 | |||
103 | #define NUMS 4096 | ||
104 | static int num[NUMS]; | ||
105 | static char* progname; | ||
106 | |||
107 | static int loop_once(void) | ||
108 | { | ||
109 | int i, j = 0; | ||
110 | for (i = 0; i < NUMS; i++) | ||
111 | j += num[i]++; | ||
112 | return j; | ||
113 | } | ||
114 | |||
115 | static int loop_for(double exec_time, double emergency_exit) | ||
116 | { | ||
117 | double last_loop = 0, loop_start; | ||
118 | int tmp = 0; | ||
119 | |||
120 | double start = cputime(); | ||
121 | double now = cputime(); | ||
122 | |||
123 | while (now + last_loop < start + exec_time) { | ||
124 | loop_start = now; | ||
125 | tmp += loop_once(); | ||
126 | now = cputime(); | ||
127 | last_loop = now - loop_start; | ||
128 | if (emergency_exit && wctime() > emergency_exit) { | ||
129 | /* Oops --- this should only be possible if the execution time tracking | ||
130 | * is broken in the LITMUS^RT kernel. */ | ||
131 | fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid()); | ||
132 | fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n"); | ||
133 | break; | ||
134 | } | ||
135 | } | ||
136 | |||
137 | return tmp; | ||
138 | } | ||
139 | |||
140 | |||
141 | static void debug_delay_loop(void) | ||
142 | { | ||
143 | double start, end, delay; | ||
144 | |||
145 | while (1) { | ||
146 | for (delay = 0.5; delay > 0.01; delay -= 0.01) { | ||
147 | start = wctime(); | ||
148 | loop_for(delay, 0); | ||
149 | end = wctime(); | ||
150 | printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n", | ||
151 | delay, | ||
152 | end - start, | ||
153 | end - start - delay, | ||
154 | 100 * (end - start - delay) / delay); | ||
155 | } | ||
156 | } | ||
157 | } | ||
158 | |||
159 | static int job(double exec_time, double program_end, int lock_od, double cs_length) | ||
160 | { | ||
161 | double chunk1, chunk2; | ||
162 | |||
163 | if (wctime() > program_end) | ||
164 | return 0; | ||
165 | else { | ||
166 | if (lock_od >= 0) { | ||
167 | /* simulate critical section somewhere in the middle */ | ||
168 | chunk1 = drand48() * (exec_time - cs_length); | ||
169 | chunk2 = exec_time - cs_length - chunk1; | ||
170 | |||
171 | /* non-critical section */ | ||
172 | loop_for(chunk1, program_end + 1); | ||
173 | |||
174 | /* critical section */ | ||
175 | litmus_lock(lock_od); | ||
176 | loop_for(cs_length, program_end + 1); | ||
177 | litmus_unlock(lock_od); | ||
178 | |||
179 | /* non-critical section */ | ||
180 | loop_for(chunk2, program_end + 2); | ||
181 | } else { | ||
182 | loop_for(exec_time, program_end + 1); | ||
183 | } | ||
184 | sleep_next_period(); | ||
185 | return 1; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | struct lt_interval* parse_td_intervals(int num, char* optarg, unsigned int *num_intervals) | ||
190 | { | ||
191 | int i, matched; | ||
192 | struct lt_interval *slots = malloc(sizeof(slots[0]) * num); | ||
193 | char** arg = (char**)malloc(sizeof(char*) * num); | ||
194 | char *token, *saveptr; | ||
195 | double start, end; | ||
196 | |||
197 | for (i = 0; i < num; i++) { | ||
198 | arg[i] = (char*)malloc(sizeof(char)*100); | ||
199 | } | ||
200 | |||
201 | i = 0; | ||
202 | token = strtok_r(optarg, ":", &saveptr); | ||
203 | while(token != NULL) { | ||
204 | sprintf(arg[i++], "%s", token); | ||
205 | token = strtok_r(NULL, ":", &saveptr); | ||
206 | } | ||
207 | |||
208 | *num_intervals = 0; | ||
209 | |||
210 | for (i=0; i<num; i++) { | ||
211 | matched = sscanf(arg[i], "[%lf,%lf]", &start, &end); | ||
212 | if (matched != 2) { | ||
213 | fprintf(stderr, "could not parse '%s' as interval\n", arg[i]); | ||
214 | exit(5); | ||
215 | } | ||
216 | if (start < 0) { | ||
217 | fprintf(stderr, "interval %s: must not start before zero\n", arg[i]); | ||
218 | exit(5); | ||
219 | } | ||
220 | if (end <= start) { | ||
221 | fprintf(stderr, "interval %s: end before start\n", arg[i]); | ||
222 | exit(5); | ||
223 | } | ||
224 | |||
225 | slots[i].start = ms2ns(start); | ||
226 | slots[i].end = ms2ns(end); | ||
227 | |||
228 | if (i > 0 && slots[i - 1].end >= slots[i].start) { | ||
229 | fprintf(stderr, "interval %s: overlaps with previous interval\n", arg[i]); | ||
230 | exit(5); | ||
231 | } | ||
232 | |||
233 | (*num_intervals)++; | ||
234 | } | ||
235 | |||
236 | for (i=0; i<num; i++) { | ||
237 | free(arg[i]); | ||
238 | } | ||
239 | free(arg); | ||
240 | return slots; | ||
241 | } | ||
242 | |||
243 | #define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:vh:m:i:b:" | ||
244 | int main(int argc, char** argv) | ||
245 | { | ||
246 | int ret; | ||
247 | lt_t wcet; | ||
248 | lt_t period; | ||
249 | lt_t hyperperiod; | ||
250 | lt_t budget; | ||
251 | double wcet_ms, period_ms, hyperperiod_ms, budget_ms; | ||
252 | unsigned int priority = LITMUS_LOWEST_PRIORITY; | ||
253 | int migrate = 0; | ||
254 | int cluster = 0; | ||
255 | int opt; | ||
256 | int wait = 0; | ||
257 | int test_loop = 0; | ||
258 | int column = 1; | ||
259 | const char *file = NULL; | ||
260 | int want_enforcement = 0; | ||
261 | double duration = 0, start = 0; | ||
262 | double *exec_times = NULL; | ||
263 | double scale = 1.0; | ||
264 | task_class_t class = RT_CLASS_HARD; | ||
265 | int cur_job = 0, num_jobs = 0; | ||
266 | struct rt_task param; | ||
267 | struct mc2_task mc2_param; | ||
268 | struct reservation_config config; | ||
269 | int res_type = SPORADIC_POLLING; | ||
270 | int n_str, num_int = 0; | ||
271 | |||
272 | int verbose = 0; | ||
273 | unsigned int job_no; | ||
274 | |||
275 | /* locking */ | ||
276 | int lock_od = -1; | ||
277 | int resource_id = 0; | ||
278 | const char *lock_namespace = "./rtspin-locks"; | ||
279 | int protocol = -1; | ||
280 | double cs_length = 1; /* millisecond */ | ||
281 | |||
282 | progname = argv[0]; | ||
283 | |||
284 | /* default for reservation */ | ||
285 | config.id = 0; | ||
286 | config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */ | ||
287 | config.cpu = 0; | ||
288 | |||
289 | mc2_param.crit = CRIT_LEVEL_C; | ||
290 | |||
291 | hyperperiod_ms = 1000; | ||
292 | budget_ms = 10; | ||
293 | |||
294 | while ((opt = getopt(argc, argv, OPTSTR)) != -1) { | ||
295 | switch (opt) { | ||
296 | case 'w': | ||
297 | wait = 1; | ||
298 | break; | ||
299 | case 'p': | ||
300 | cluster = atoi(optarg); | ||
301 | migrate = 1; | ||
302 | config.cpu = cluster; | ||
303 | break; | ||
304 | case 'q': | ||
305 | priority = atoi(optarg); | ||
306 | if (!litmus_is_valid_fixed_prio(priority)) | ||
307 | usage("Invalid priority."); | ||
308 | break; | ||
309 | case 'c': | ||
310 | class = str2class(optarg); | ||
311 | if (class == -1) | ||
312 | usage("Unknown task class."); | ||
313 | break; | ||
314 | case 'e': | ||
315 | want_enforcement = 1; | ||
316 | break; | ||
317 | case 'l': | ||
318 | test_loop = 1; | ||
319 | break; | ||
320 | case 'o': | ||
321 | column = atoi(optarg); | ||
322 | break; | ||
323 | case 'f': | ||
324 | file = optarg; | ||
325 | break; | ||
326 | case 's': | ||
327 | scale = atof(optarg); | ||
328 | break; | ||
329 | case 'X': | ||
330 | protocol = lock_protocol_for_name(optarg); | ||
331 | if (protocol < 0) | ||
332 | usage("Unknown locking protocol specified."); | ||
333 | break; | ||
334 | case 'L': | ||
335 | cs_length = atof(optarg); | ||
336 | if (cs_length <= 0) | ||
337 | usage("Invalid critical section length."); | ||
338 | break; | ||
339 | case 'Q': | ||
340 | resource_id = atoi(optarg); | ||
341 | if (resource_id <= 0 && strcmp(optarg, "0")) | ||
342 | usage("Invalid resource ID."); | ||
343 | break; | ||
344 | case 'v': | ||
345 | verbose = 1; | ||
346 | break; | ||
347 | case 'm': | ||
348 | mc2_param.crit = atoi(optarg); | ||
349 | if (mc2_param.crit == CRIT_LEVEL_A) { | ||
350 | res_type = TABLE_DRIVEN; | ||
351 | } | ||
352 | else if (mc2_param.crit == CRIT_LEVEL_B) { | ||
353 | res_type = PERIODIC_POLLING; | ||
354 | } | ||
355 | else | ||
356 | usage("Invalid criticality level."); | ||
357 | break; | ||
358 | case 'h': | ||
359 | hyperperiod_ms = atof(optarg); | ||
360 | break; | ||
361 | case 'b': | ||
362 | budget_ms = atof(optarg); | ||
363 | break; | ||
364 | case 'i': | ||
365 | n_str = strlen(optarg); | ||
366 | while(n_str--) { | ||
367 | if (optarg[n_str] == ',') | ||
368 | num_int++; | ||
369 | } | ||
370 | if (!num_int) | ||
371 | usage("Bad argument."); | ||
372 | config.table_driven_params.intervals = parse_td_intervals(num_int, optarg, &config.table_driven_params.num_intervals); | ||
373 | break; | ||
374 | case ':': | ||
375 | usage("Argument missing."); | ||
376 | break; | ||
377 | case '?': | ||
378 | default: | ||
379 | usage("Bad argument."); | ||
380 | break; | ||
381 | } | ||
382 | } | ||
383 | |||
384 | if (test_loop) { | ||
385 | debug_delay_loop(); | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | srand(getpid()); | ||
390 | |||
391 | if (file) { | ||
392 | get_exec_times(file, column, &num_jobs, &exec_times); | ||
393 | |||
394 | if (argc - optind < 2) | ||
395 | usage("Arguments missing."); | ||
396 | |||
397 | for (cur_job = 0; cur_job < num_jobs; ++cur_job) { | ||
398 | /* convert the execution time to seconds */ | ||
399 | duration += exec_times[cur_job] * 0.001; | ||
400 | } | ||
401 | } else { | ||
402 | /* | ||
403 | * if we're not reading from the CSV file, then we need | ||
404 | * three parameters | ||
405 | */ | ||
406 | if (argc - optind < 3) | ||
407 | usage("Arguments missing."); | ||
408 | } | ||
409 | |||
410 | wcet_ms = atof(argv[optind + 0]); | ||
411 | period_ms = atof(argv[optind + 1]); | ||
412 | |||
413 | wcet = ms2ns(wcet_ms); | ||
414 | period = ms2ns(period_ms); | ||
415 | budget = ms2ns(budget_ms); | ||
416 | hyperperiod = ms2ns(hyperperiod_ms); | ||
417 | |||
418 | if (wcet <= 0) | ||
419 | usage("The worst-case execution time must be a " | ||
420 | "positive number."); | ||
421 | if (period <= 0) | ||
422 | usage("The period must be a positive number."); | ||
423 | if (!file && wcet > period) { | ||
424 | usage("The worst-case execution time must not " | ||
425 | "exceed the period."); | ||
426 | } | ||
427 | |||
428 | if (!file) | ||
429 | duration = atof(argv[optind + 2]); | ||
430 | else if (file && num_jobs > 1) | ||
431 | duration += period_ms * 0.001 * (num_jobs - 1); | ||
432 | |||
433 | if (migrate) { | ||
434 | ret = be_migrate_to_domain(cluster); | ||
435 | if (ret < 0) | ||
436 | bail_out("could not migrate to target partition or cluster."); | ||
437 | } | ||
438 | |||
439 | /* reservation config */ | ||
440 | config.id = gettid(); | ||
441 | |||
442 | if (hyperperiod%period != 0 ) { | ||
443 | bail_out("hyperperiod must be multiple of period"); | ||
444 | } | ||
445 | |||
446 | if (mc2_param.crit == CRIT_LEVEL_A) { | ||
447 | config.table_driven_params.major_cycle_length = period; | ||
448 | } | ||
449 | else if (mc2_param.crit == CRIT_LEVEL_B) { | ||
450 | config.polling_params.budget = budget; | ||
451 | config.polling_params.period = period; | ||
452 | config.polling_params.offset = 0; | ||
453 | config.polling_params.relative_deadline = 0; | ||
454 | if (config.polling_params.budget > config.polling_params.period) { | ||
455 | usage("The budget must not exceed the period."); | ||
456 | } | ||
457 | } | ||
458 | |||
459 | /* create a reservation */ | ||
460 | ret = reservation_create(res_type, &config); | ||
461 | if (ret < 0) { | ||
462 | bail_out("failed to create reservation."); | ||
463 | } | ||
464 | |||
465 | init_rt_task_param(¶m); | ||
466 | param.exec_cost = wcet; | ||
467 | param.period = period; | ||
468 | param.priority = priority; | ||
469 | param.cls = class; | ||
470 | param.release_policy = TASK_PERIODIC; | ||
471 | param.budget_policy = (want_enforcement) ? | ||
472 | PRECISE_ENFORCEMENT : NO_ENFORCEMENT; | ||
473 | if (migrate) { | ||
474 | param.cpu = gettid(); | ||
475 | } | ||
476 | ret = set_rt_task_param(gettid(), ¶m); | ||
477 | if (ret < 0) | ||
478 | bail_out("could not setup rt task params"); | ||
479 | |||
480 | mc2_param.pid = gettid(); | ||
481 | mc2_param.hyperperiod = hyperperiod; | ||
482 | ret = set_mc2_task_param(gettid(), &mc2_param); | ||
483 | if (ret < 0) | ||
484 | bail_out("could not setup mc2 task params"); | ||
485 | init_litmus(); | ||
486 | |||
487 | start = wctime(); | ||
488 | ret = task_mode(LITMUS_RT_TASK); | ||
489 | if (ret != 0) | ||
490 | bail_out("could not become RT task"); | ||
491 | |||
492 | if (protocol >= 0) { | ||
493 | /* open reference to semaphore */ | ||
494 | lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster); | ||
495 | if (lock_od < 0) { | ||
496 | perror("litmus_open_lock"); | ||
497 | usage("Could not open lock."); | ||
498 | } | ||
499 | } | ||
500 | |||
501 | |||
502 | if (wait) { | ||
503 | ret = wait_for_ts_release(); | ||
504 | if (ret != 0) | ||
505 | bail_out("wait_for_ts_release()"); | ||
506 | start = wctime(); | ||
507 | } | ||
508 | |||
509 | if (file) { | ||
510 | /* use times read from the CSV file */ | ||
511 | for (cur_job = 0; cur_job < num_jobs; ++cur_job) { | ||
512 | /* convert job's length to seconds */ | ||
513 | job(exec_times[cur_job] * 0.001 * scale, | ||
514 | start + duration, | ||
515 | lock_od, cs_length * 0.001); | ||
516 | } | ||
517 | } else { | ||
518 | do { | ||
519 | if (verbose) { | ||
520 | get_job_no(&job_no); | ||
521 | printf("rtspin/%d:%u @ %.4fms\n", gettid(), | ||
522 | job_no, (wctime() - start) * 1000); | ||
523 | } | ||
524 | /* convert to seconds and scale */ | ||
525 | } while (job(wcet_ms * 0.001 * scale, start + duration, | ||
526 | lock_od, cs_length * 0.001)); | ||
527 | } | ||
528 | |||
529 | ret = task_mode(BACKGROUND_TASK); | ||
530 | if (ret != 0) | ||
531 | bail_out("could not become regular task (huh?)"); | ||
532 | |||
533 | if (file) | ||
534 | free(exec_times); | ||
535 | |||
536 | reservation_destroy(gettid(), config.cpu); | ||
537 | if (mc2_param.crit == CRIT_LEVEL_A) { | ||
538 | free(config.table_driven_params.intervals); | ||
539 | } | ||
540 | return 0; | ||
541 | } | ||
diff --git a/include/litmus.h b/include/litmus.h index 3bd6b92..b90a83d 100644 --- a/include/litmus.h +++ b/include/litmus.h | |||
@@ -40,6 +40,8 @@ extern "C" { | |||
40 | 40 | ||
41 | #include "migration.h" | 41 | #include "migration.h" |
42 | 42 | ||
43 | #include "litmus/mc2_common.h" | ||
44 | |||
43 | /** | 45 | /** |
44 | * @private | 46 | * @private |
45 | * Number of semaphore protocol object types | 47 | * Number of semaphore protocol object types |
@@ -420,6 +422,7 @@ int reservation_create(int rtype, void *config); | |||
420 | 422 | ||
421 | int reservation_destroy(unsigned int reservation_id, int cpu); | 423 | int reservation_destroy(unsigned int reservation_id, int cpu); |
422 | 424 | ||
425 | int set_mc2_task_param(pid_t pid, struct mc2_task* param); | ||
423 | 426 | ||
424 | #ifdef __cplusplus | 427 | #ifdef __cplusplus |
425 | } | 428 | } |
Binary files differ | |||
diff --git a/src/syscalls.c b/src/syscalls.c index fbb8604..b07d135 100644 --- a/src/syscalls.c +++ b/src/syscalls.c | |||
@@ -96,3 +96,8 @@ int reservation_destroy(unsigned int reservation_id, int cpu) | |||
96 | { | 96 | { |
97 | return syscall(__NR_reservation_destroy, reservation_id, cpu); | 97 | return syscall(__NR_reservation_destroy, reservation_id, cpu); |
98 | } | 98 | } |
99 | |||
100 | int set_mc2_task_param(pid_t pid, struct mc2_task *param) | ||
101 | { | ||
102 | return syscall(__NR_set_mc2_task_param, pid, param); | ||
103 | } \ No newline at end of file | ||