aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile26
-rw-r--r--bin/bespin.c400
-rw-r--r--bin/common.c41
-rw-r--r--bin/locktest.c206
-rw-r--r--bin/rtspin.beta.c283
-rw-r--r--bin/rtspin.c17
-rw-r--r--bin/rtspin.ovh.c239
-rw-r--r--include/common.h3
-rw-r--r--include/litmus.h3
-rw-r--r--src/kernel_iface.c7
-rw-r--r--src/litmus.c1
11 files changed, 1214 insertions, 12 deletions
diff --git a/Makefile b/Makefile
index f6b865c..5527862 100644
--- a/Makefile
+++ b/Makefile
@@ -12,14 +12,15 @@ host-arch := $(shell uname -m | \
12ARCH ?= ${host-arch} 12ARCH ?= ${host-arch}
13 13
14# LITMUS_KERNEL -- where to find the litmus kernel? 14# LITMUS_KERNEL -- where to find the litmus kernel?
15LITMUS_KERNEL ?= ../litmus-rt 15LITMUS_KERNEL ?= ../backup-litmus-rt
16 16
17 17
18# ############################################################################## 18# ##############################################################################
19# Internal configuration. 19# Internal configuration.
20 20
21# compiler flags 21# compiler flags
22flags-debug = -Wall -Werror -g -Wdeclaration-after-statement 22# flags-debug = -Wall -Werror -g -Wdeclaration-after-statement
23flags-debug = -Wall -g -Wdeclaration-after-statement
23flags-api = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE 24flags-api = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE
24 25
25# architecture-specific flags 26# architecture-specific flags
@@ -71,7 +72,7 @@ AR := ${CROSS_COMPILE}${AR}
71 72
72all = lib ${rt-apps} 73all = lib ${rt-apps}
73rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \ 74rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
74 base_mt_task runtests colortest colorbench testcounters 75 base_mt_task runtests colortest colorbench testcounters bespin
75 76
76.PHONY: all lib clean dump-config TAGS tags cscope help 77.PHONY: all lib clean dump-config TAGS tags cscope help
77 78
@@ -154,7 +155,7 @@ arch/${include-${ARCH}}/include/asm/%.h: \
154 cp $< $@ 155 cp $< $@
155 156
156litmus-headers = include/litmus/rt_param.h include/litmus/unistd_32.h \ 157litmus-headers = include/litmus/rt_param.h include/litmus/unistd_32.h \
157 include/litmus/unistd_64.h 158 include/litmus/unistd_64.h include/litmus/color.h
158 159
159unistd-headers = \ 160unistd-headers = \
160 $(foreach file,${unistd-${ARCH}},arch/${include-${ARCH}}/include/asm/$(file)) 161 $(foreach file,${unistd-${ARCH}},arch/${include-${ARCH}}/include/asm/$(file))
@@ -207,12 +208,25 @@ obj-base_mt_task = base_mt_task.o
207ldf-base_mt_task = -pthread 208ldf-base_mt_task = -pthread
208 209
209obj-rt_launch = rt_launch.o common.o 210obj-rt_launch = rt_launch.o common.o
211lib-rt_launch = -lgsl -lgslcblas
210 212
211obj-rtspin = rtspin.o common.o 213obj-rtspin = rtspin.o common.o
212lib-rtspin = -lrt 214lib-rtspin = -lrt -lgsl -lgslcblas
215
216obj-rtspin.ovh = rtspin.ovh.o common.o
217lib-rtspin.ovh = -lrt -lgsl -lgslcblas
218
219obj-rtspin.beta = rtspin.beta.o common.o
220lib-rtspin.beta = -lrt $(shell gsl-config --libs)
221
222obj-bespin = bespin.o common.o
223lib-bespin = -lrt -lgsl -lgslcblas
213 224
214obj-release_ts = release_ts.o 225obj-release_ts = release_ts.o
215 226
227obj-locktest = locktest.o
228lib-locktest = -lrt -pthread
229
216obj-measure_syscall = null_call.o 230obj-measure_syscall = null_call.o
217lib-measure_syscall = -lm 231lib-measure_syscall = -lm
218 232
@@ -220,7 +234,7 @@ obj-colortest = colortest.o color.o
220lib-colortest = -static 234lib-colortest = -static
221 235
222obj-colorbench = colorbench.o color.o perfcounters.o common.o 236obj-colorbench = colorbench.o color.o perfcounters.o common.o
223lib-colorbench = -lpthread -lrt 237lib-colorbench = -lpthread -lrt -lgsl -lgslcblas
224 238
225obj-testcounters = testcounters.o 239obj-testcounters = testcounters.o
226lib-testcounters = 240lib-testcounters =
diff --git a/bin/bespin.c b/bin/bespin.c
new file mode 100644
index 0000000..4495721
--- /dev/null
+++ b/bin/bespin.c
@@ -0,0 +1,400 @@
1#include <sys/time.h>
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <time.h>
7#include <assert.h>
8#include <string.h>
9#include <limits.h>
10
11#include <sched.h>
12#include <sys/time.h>
13#include <sys/resource.h>
14
15#include <gsl/gsl_rng.h>
16#include <gsl/gsl_randist.h>
17
18#include "litmus.h"
19#include "common.h"
20
21#define UINT_WANT 4294967295
22#if UINT_MAX < UINT_WANT
23#error Unsigned int not big enough.
24#endif
25
26/*
27 * Limit the execution times.
28 */
29#define EXEC_MIN (2 * __NS_PER_MS)
30#define EXEC_MAX (100 * __NS_PER_MS)
31
32/*
33 * Limit interarrival times.
34 */
35#define IA_MIN (0 * __NS_PER_MS)
36#define IA_MAX (200 * __NS_PER_MS)
37
38
39static void usage(char *error) {
40 fprintf(stderr, "Error: %s\n", error);
41 fprintf(stderr,
42 "Usage:\n"
43 " bespin [-w] [-o] [-n] [-p partition] "
44 "[-s seed] [-f res-time file] OS_TYPE DURATION\n"
45 "OS_TYPE is litmus or linux\n"
46 "DURATION is milliseconds.\n");
47 exit(EXIT_FAILURE);
48}
49
50#define NUMS 4096
51static int num[NUMS];
52static char* progname;
53
54static int task_colors, avg_ways;
55
56static gsl_rng *exec_rng;
57static gsl_rng *ia_rng;
58static struct timespec sleep_ts = { .tv_sec = 0 };
59
60static void setup_rng(unsigned long seed)
61{
62 exec_rng = gsl_rng_alloc(gsl_rng_taus);
63 ia_rng = gsl_rng_alloc(gsl_rng_taus);
64 if (!exec_rng || !ia_rng)
65 bail_out("Could not initialize RNG");
66 gsl_rng_set(exec_rng, seed);
67 gsl_rng_set(ia_rng, seed + 1);
68}
69
70static lt_t round_double_lt(const double d)
71{
72 /* if needed, add one so round up */
73 if (d - ((lt_t)d) > 0.0)
74 return ((lt_t)(d + 1.0));
75 else
76 return ((lt_t)d);
77}
78
79static lt_t get_exec_time(const lt_t exec_mean)
80{
81 double e = gsl_ran_exponential(exec_rng, exec_mean);
82 e = (e < EXEC_MIN) ? EXEC_MIN : e;
83 e = (e > EXEC_MAX) ? EXEC_MAX : e;
84 return (round_double_lt(e));
85}
86
87static lt_t get_ia_time(const lt_t ia_mean)
88{
89 double ia = gsl_ran_exponential(ia_rng, ia_mean);
90 ia = (ia < IA_MIN) ? IA_MIN : ia;
91 ia = (ia > IA_MAX) ? IA_MAX : ia;
92 return (round_double_lt(ia));
93}
94
95#define LITMUS_STR "litmus"
96#define LINUX_STR "linux"
97static int using_os(const char *const os, const char *const test)
98{
99 /* LITMUS_STR > LINUX_STR */
100 return (0 == strncasecmp(os, test, sizeof(LITMUS_STR)));
101}
102
103static int valid_os(char *os)
104{
105 return (using_os(LITMUS_STR, os) || using_os(LINUX_STR, os));
106}
107
108static inline lt_t ts_to_ns(const struct timespec *ts)
109{
110 return ( (((lt_t)ts->tv_sec) * 1e9) + ts->tv_nsec );
111}
112
113static void mono_time_ts(struct timespec *ts)
114{
115 int ret = clock_gettime(CLOCK_MONOTONIC, ts);
116 if (ret)
117 bail_out("could not get monotonic time");
118}
119
120static lt_t mono_time(void)
121{
122 struct timespec ts;
123 mono_time_ts(&ts);
124 return (ts_to_ns(&ts));
125}
126
127static void add_to_ts(struct timespec *ts, const lt_t t)
128{
129 /* convert the lt_t to seconds and nanoseconds */
130 const lt_t sec = t / 1e9;
131 long nsec = t - sec;
132
133 /* figure out carry for nsec field */
134 const long nsec_sum_large = ts->tv_nsec + nsec;
135 const time_t sec_carry = nsec_sum_large / 1e9;
136
137 ts->tv_sec += sec + sec_carry;
138 ts->tv_nsec = nsec_sum_large - sec_carry * 1e9;
139 assert(ts->tv_nsec < 1e9);
140}
141
142static lt_t etime(void)
143{
144 struct timespec ts;
145 int err;
146 err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
147 if (err)
148 bail_out("could not get thread CPU time");
149 return (ts_to_ns(&ts));
150}
151
152static int loop_once(void)
153{
154 int i, j = 0;
155 for (i = 0; i < NUMS; i++)
156 j += num[i]++;
157 return j;
158}
159
160static int loop_for(lt_t exec_time, lt_t emergency_exit)
161{
162 double last_loop = 0, loop_start;
163 int job_finished = 1;
164 int tmp = 0;
165
166 lt_t start = etime();
167 lt_t now = etime();
168
169 while (now + last_loop < start + exec_time) {
170 loop_start = now;
171 tmp += loop_once();
172 now = etime();
173 last_loop = now - loop_start;
174 if (emergency_exit && mono_time() > emergency_exit)
175 job_finished = 0;
176 }
177
178 return job_finished;
179}
180
181static void do_sleep(const lt_t ia_mean)
182{
183 const lt_t ia = get_ia_time(ia_mean);
184 int err;
185
186 add_to_ts(&sleep_ts, ia);
187 err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
188 &sleep_ts, NULL);
189
190 /*
191 * For some reason, nanosleep returns non-zero even when things are
192 * okay the last time. */
193 if (err)
194 bail_out("could not nanosleep!");
195}
196
197static int job(const lt_t exec_mean, const lt_t ia_mean, FILE *out_f,
198 const lt_t program_end)
199{
200 const lt_t now = mono_time();
201 const lt_t exec = get_exec_time(exec_mean);
202 int job_finished;
203 lt_t end_time;
204
205 if (now > program_end || now + exec > program_end)
206 {
207 /* this job is either after we want to stop, or would be,
208 * so just quit now */
209 return 0;
210 } else {
211 /* add NS per MS as an error margin */
212 job_finished = loop_for(exec, program_end + __NS_PER_MS);
213 end_time = mono_time();
214
215 /* record response time if wanted and the job finished */
216 if (out_f && job_finished)
217 {
218 /* print start time, end time, exec time */
219 fprintf(out_f, "%llu, %llu, %llu\n",
220 ts_to_ns(&sleep_ts), end_time, exec);
221 }
222
223 if (end_time < program_end) {
224 /* we can go to sleep some time */
225 do_sleep(ia_mean);
226 return 1;
227 } else {
228 /* that was the last job */
229 return 0;
230 }
231 }
232}
233
234static void setup_litmus_task(const double phase_ms, const int cpu)
235{
236 const lt_t phase = phase_ms * __NS_PER_MS;
237 int ret;
238
239 /* Best-Effort task has no WCET or period, just use one */
240 ret = sporadic_task_ns(1, 1, phase, cpu, RT_CLASS_BEST_EFFORT,
241 NO_ENFORCEMENT, 0);
242 if (ret < 0)
243 bail_out("could not setup rt task params");
244
245 request_resources(task_colors, avg_ways);
246
247 init_litmus();
248
249 ret = task_mode(LITMUS_RT_TASK);
250 if (ret != 0)
251 bail_out("could not become RT task");
252}
253
254#define OPTSTR "p:wl:r:nos:f:h:"
255
256int main(int argc, char** argv)
257{
258 unsigned long seed = 1;
259 double duration_ms;
260 double exec_mean_ms = 10.0, ia_mean_ms = 100.0, phase_ms = 0.0;
261 lt_t duration, start, exec_mean, ia_mean;
262 char *os_type, *out_fname = NULL;
263 FILE *out_f = NULL;
264 int opt;
265 int ret;
266 int wait = 0;
267 int nice = 0;
268 int fifo = 0;
269 int cpu = 0;
270 int migrate = 0;
271 struct sched_param param;
272
273 progname = argv[0];
274
275 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
276 switch (opt) {
277 case 'w':
278 wait = 1;
279 break;
280 case 'p':
281 cpu = atoi(optarg);
282 migrate = 1;
283 break;
284 case 'n':
285 nice = 1;
286 break;
287 case 'o':
288 fifo = 1;
289 break;
290 case 's':
291 seed = atoi(optarg);
292 break;
293 /* case 'h': */
294 /* phase_ms = atof(optarg); */
295 /* break; */
296 case 'e':
297 exec_mean_ms = atof(optarg);
298 break;
299 case 'i':
300 ia_mean_ms = atof(optarg);
301 break;
302 case 'f':
303 out_fname = optarg;
304 break;
305 case 'h':
306 sscanf(optarg, "%d,%d", &task_colors, &avg_ways);
307 break;
308 case ':':
309 usage("Argument missing.");
310 break;
311 case '?':
312 default:
313 usage("Bad argument.");
314 break;
315 }
316 }
317
318 if (argc - optind != 2)
319 usage("Arguments missing.");
320
321 os_type = argv[optind + 0];
322 duration_ms = atof(argv[optind + 1]);
323
324 if (!valid_os(os_type))
325 bail_out("Invalid OS type");
326
327 if (duration_ms < 0)
328 bail_out("duration < 0 not allowed");
329
330 if (exec_mean_ms < 0)
331 bail_out("execution time mean < 0 not allowed");
332
333 if (ia_mean_ms < 0)
334 bail_out("IA time mean < 0 not allowed");
335
336 if (exec_mean_ms * __NS_PER_MS > UINT_MAX >> 1)
337 bail_out("Exec time too big");
338
339 if (seed < 1)
340 bail_out("seed < 1 not allowed");
341
342 if (phase_ms < 0)
343 bail_out("phase < 0 not allowed");
344
345 if (wait && using_os(LINUX_STR, os_type))
346 bail_out("Linux cannot use the wait flag");
347
348 duration = duration_ms * __NS_PER_MS;
349 exec_mean = exec_mean_ms * __NS_PER_MS;
350 ia_mean = ia_mean_ms * __NS_PER_MS;
351
352 if (out_fname)
353 {
354 out_f = fopen(out_fname, "w");
355 if (!out_f)
356 bail_out("Could not open response-time file");
357 }
358
359 setup_rng(seed);
360
361 if (using_os(LITMUS_STR, os_type)) {
362
363 if (migrate) {
364 ret = be_migrate_to(cpu);
365 if (ret < 0)
366 bail_out("could not migrate to target partition");
367 }
368
369 setup_litmus_task(phase_ms, cpu);
370
371 if (wait) {
372 ret = wait_for_ts_release();
373 if (ret != 0)
374 bail_out("wait_for_ts_release()");
375 }
376 } else if (fifo) {
377 param.sched_priority = sched_get_priority_max(SCHED_FIFO) - 2;
378 ret = sched_setscheduler(0, SCHED_FIFO, &param);
379 if (ret)
380 bail_out("Could not switch to FIFO scheduler");
381 } else if (nice) {
382 ret = setpriority(PRIO_PROCESS, 0, 5);
383 if (ret)
384 bail_out("Could not set task priority");
385 }
386
387 /* initialize the start time */
388 mono_time_ts(&sleep_ts);
389 start = ts_to_ns(&sleep_ts);
390
391 while (job(exec_mean, ia_mean, out_f, start + duration));
392
393 if (using_os(LITMUS_STR, os_type)) {
394 ret = task_mode(BACKGROUND_TASK);
395 if (ret != 0)
396 bail_out("could not become regular task (huh?)");
397 }
398
399 return 0;
400}
diff --git a/bin/common.c b/bin/common.c
index 452b882..2aa9a7c 100644
--- a/bin/common.c
+++ b/bin/common.c
@@ -3,9 +3,50 @@
3#include <errno.h> 3#include <errno.h>
4 4
5#include "common.h" 5#include "common.h"
6#include "litmus.h"
7#include <litmus/color.h>
8
9#include <gsl/gsl_rng.h>
10#include <gsl/gsl_randist.h>
6 11
7void bail_out(const char* msg) 12void bail_out(const char* msg)
8{ 13{
9 perror(msg); 14 perror(msg);
10 exit(-1 * errno); 15 exit(-1 * errno);
11} 16}
17
18void request_resources(int task_colors, int avg_ways)
19{
20 const gsl_rng *way_rng = gsl_rng_alloc(gsl_rng_taus);
21 struct control_page *page = get_ctrl_page();
22 int color, ways, rem = task_colors;
23 float random;
24 char taken[NUM_COLORS];
25
26 memset(page->requests, 0, NUM_COLORS*sizeof(*page->requests));
27
28 gsl_rng_set(way_rng, rand());
29 memset(taken, 0, NUM_COLORS);
30
31 srand(getpid());
32 gsl_rng_set(way_rng, getpid());
33
34 while (rem) {
35 /* select a random unchosen color */
36 do {
37 color = rand() % NUM_COLORS;
38 } while (taken[color]);
39
40 if (rand() % NUM_COLORS <= task_colors) {
41 taken[color] = 1;
42 rem --;
43
44 random = gsl_ran_exponential(way_rng, avg_ways + 1);
45 ways = 1 + (int)random;
46 ways = (ways < 1) ? 1 : ways;
47 ways = (ways > NUM_WAYS) ? NUM_WAYS : ways;
48
49 page->requests[color] = ways;
50 }
51 }
52}
diff --git a/bin/locktest.c b/bin/locktest.c
new file mode 100644
index 0000000..a0f8948
--- /dev/null
+++ b/bin/locktest.c
@@ -0,0 +1,206 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <stdint.h>
4#include <unistd.h>
5#include <assert.h>
6#include <errno.h>
7#include <sys/types.h>
8#include <sys/stat.h>
9#include <fcntl.h>
10
11/* Include gettid() */
12#include <sys/types.h>
13
14/* Include threading support. */
15#include <pthread.h>
16
17/* Include the LITMUS^RT API.*/
18#include "litmus.h"
19
20/* Catch errors.
21 */
22#define CALL( exp ) do { \
23 int ret; \
24 ret = exp; \
25 if (ret != 0) \
26 fprintf(stderr, "%s failed: %m\n", #exp);\
27 else \
28 fprintf(stderr, "%s ok.\n", #exp); \
29 } while (0)
30
31#define TH_CALL( exp ) do { \
32 int ret; \
33 ret = exp; \
34 if (ret != 0) \
35 fprintf(stderr, "[%d] %s failed: %m\n", ctx->id, #exp); \
36 else \
37 fprintf(stderr, "[%d] %s ok.\n", ctx->id, #exp); \
38 } while (0)
39
40#define TH_SAFE_CALL( exp ) do { \
41 int ret; \
42 fprintf(stderr, "[%d] calling %s...\n", ctx->id, #exp); \
43 ret = exp; \
44 if (ret != 0) \
45 fprintf(stderr, "\t...[%d] %s failed: %m\n", ctx->id, #exp); \
46 else \
47 fprintf(stderr, "\t...[%d] %s ok.\n", ctx->id, #exp); \
48 } while (0)
49
50
51/* these are only default values */
52int NUM_THREADS=3;
53int NUM_SEMS=10;
54
55#define MAX_SEMS 1000
56
57#define EXEC_COST 10
58#define PERIOD 100
59
60/* The information passed to each thread. Could be anything. */
61struct thread_context {
62 int id;
63 int fd;
64 int od[MAX_SEMS];
65 int count;
66 unsigned int rand;
67};
68
69void* rt_thread(void* _ctx);
70int nested_job(struct thread_context* ctx, int *count, int *next);
71int job(struct thread_context*);
72
73#define OPTSTR "t:s:"
74
75int main(int argc, char** argv)
76{
77 int i;
78 struct thread_context* ctx;
79 pthread_t* task;
80 int fd;
81
82 int opt;
83 while((opt = getopt(argc, argv, OPTSTR)) != -1) {
84 switch(opt) {
85 case 't':
86 NUM_THREADS = atoi(optarg);
87 break;
88 case 's':
89 NUM_SEMS = atoi(optarg);
90 assert(NUM_SEMS <= MAX_SEMS);
91 break;
92 default:
93 fprintf(stderr, "Unknown option: %c\n", opt);
94 exit(-1);
95 break;
96 }
97 }
98
99 ctx = (struct thread_context*) calloc(NUM_THREADS, sizeof(struct thread_context));
100 task = (pthread_t*) calloc(NUM_THREADS, sizeof(pthread_t));
101
102 srand(0); /* something repeatable for now */
103
104 fd = open("semaphores", O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR);
105
106 CALL( init_litmus() );
107
108 for (i = 0; i < NUM_THREADS; i++) {
109 ctx[i].id = i;
110 ctx[i].fd = fd;
111 ctx[i].rand = rand();
112 CALL( pthread_create(task + i, NULL, rt_thread, ctx + i) );
113 }
114
115
116 for (i = 0; i < NUM_THREADS; i++)
117 pthread_join(task[i], NULL);
118
119
120 return 0;
121}
122
123void* rt_thread(void* _ctx)
124{
125 int i;
126 int do_exit = 0;
127
128 struct thread_context *ctx = (struct thread_context*)_ctx;
129
130 TH_CALL( init_rt_thread() );
131
132 /* Vary period a little bit. */
133 TH_CALL( sporadic_global(EXEC_COST, PERIOD + 10*ctx->id) );
134
135 for (i = 0; i < NUM_SEMS; i++) {
136 ctx->od[i] = open_fmlp_sem(ctx->fd, i);
137 if(ctx->od[i] < 0)
138 perror("open_fmlp_sem");
139 }
140
141 TH_CALL( task_mode(LITMUS_RT_TASK) );
142
143
144 printf("[%d] Waiting for TS release.\n ", ctx->id);
145 wait_for_ts_release();
146 ctx->count = 0;
147
148 do {
149 int which_sem = (int)(NUM_SEMS * (rand_r(&(ctx->rand)) / (RAND_MAX + 1.0)));
150
151 printf("[%d]: trying to get semaphore %d.\n", ctx->id, which_sem);
152 fflush(stdout);
153
154 TH_SAFE_CALL ( litmus_lock(which_sem) );
155
156 printf("[%d] got semaphore %d.\n", ctx->id, which_sem);
157 fflush(stdout);
158
159 do_exit = job(ctx);
160
161 printf("[%d]: freeing semaphore %d.\n", ctx->id, which_sem);
162 fflush(stdout);
163
164 TH_SAFE_CALL ( litmus_unlock(which_sem) );
165
166 if(!do_exit) {
167 sleep_next_period();
168 }
169 } while(!do_exit);
170
171 /*****
172 * 4) Transition to background mode.
173 */
174 TH_CALL( task_mode(BACKGROUND_TASK) );
175
176
177 return NULL;
178}
179
180void dirty_kb(int kb)
181{
182 int32_t one_kb[256];
183 int32_t sum = 0;
184 int32_t i;
185
186 for (i = 0; i < 256; i++)
187 sum += one_kb[i];
188 kb--;
189 /* prevent tail recursion */
190 if (kb)
191 dirty_kb(kb);
192 for (i = 0; i < 256; i++)
193 sum += one_kb[i];
194}
195
196int job(struct thread_context* ctx)
197{
198 /* Do real-time calculation. */
199 dirty_kb(8);
200
201 /* Don't exit. */
202 //return ctx->count++ > 100;
203 //return ctx->count++ > 12000;
204 //return ctx->count++ > 120000;
205 return ctx->count++ > 30000; // controls number of jobs per task
206}
diff --git a/bin/rtspin.beta.c b/bin/rtspin.beta.c
new file mode 100644
index 0000000..556660e
--- /dev/null
+++ b/bin/rtspin.beta.c
@@ -0,0 +1,283 @@
1#include <sys/time.h>
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <time.h>
7#include <assert.h>
8#include <strings.h>
9
10#include <gsl/gsl_rng.h>
11#include <gsl/gsl_randist.h>
12
13#include "litmus.h"
14#include "common.h"
15
16#include <litmus/sched_mc.h>
17
18
19static void usage(char *error) {
20 fprintf(stderr, "Error: %s\n", error);
21 fprintf(stderr,
22 "Usage:\n"
23 " rt_spin [COMMON-OPTS] LVL_C_TIME WCET PERIOD DURATION\n"
24 " rt_spin -l\n"
25 "\n"
26 "COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n"
27 " [-r CRITICALITY = [a|b|c|d]] [-i MC-LVL-A-ID]\n"
28 " [-a ALPHA] [-b BETA] [-d SEED]\n"
29 "\n"
30 "WCET and PERIOD are nanoseconds, DURATION is seconds.\n");
31 exit(EXIT_FAILURE);
32}
33
34#define NUMS 4096
35static int num[NUMS];
36static char* progname;
37
38static gsl_rng *beta_rng;
39static gsl_rng *coin_rng;
40
41static void setup_rng(unsigned long seed)
42{
43 beta_rng = gsl_rng_alloc(gsl_rng_taus);
44 coin_rng = gsl_rng_alloc(gsl_rng_taus);
45 if (!beta_rng || !coin_rng)
46 bail_out("Could not initialize RNG");
47 gsl_rng_set(beta_rng, seed);
48 gsl_rng_set(coin_rng, seed);
49}
50
51static int loop_once(void)
52{
53 int i, j = 0;
54 for (i = 0; i < NUMS; i++)
55 j += num[i]++;
56 return j;
57}
58
59static int loop_for(double exec_time, double emergency_exit)
60{
61 double last_loop = 0, loop_start;
62 int tmp = 0;
63
64 double start = cputime();
65 double now = cputime();
66
67 while (now + last_loop < start + exec_time) {
68 loop_start = now;
69 tmp += loop_once();
70 now = cputime();
71 last_loop = now - loop_start;
72 if (emergency_exit && wctime() > emergency_exit) {
73 /* Oops --- this should only be possible if the execution time tracking
74 * is broken in the LITMUS^RT kernel. */
75 fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
76 fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
77 break;
78 }
79 }
80
81 return tmp;
82}
83
84
85static void debug_delay_loop(void)
86{
87 double start, end, delay;
88
89 while (1) {
90 for (delay = 0.5; delay > 0.01; delay -= 0.01) {
91 start = wctime();
92 loop_for(delay, 0);
93 end = wctime();
94 printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
95 delay,
96 end - start,
97 end - start - delay,
98 100 * (end - start - delay) / delay);
99 }
100 }
101}
102
103static int job(double exec_time, double program_end)
104{
105 if (wctime() > program_end)
106 return 0;
107 else {
108 loop_for(exec_time, program_end + 1);
109 sleep_next_period();
110 return 1;
111 }
112}
113
114enum crit_level str2crit(const char* str)
115{
116 if (0 == strncasecmp("a", str, 1))
117 return CRIT_LEVEL_A;
118 else if (0 == strncasecmp("b", str, 1))
119 return CRIT_LEVEL_B;
120 else if (0 == strncasecmp("c", str, 1))
121 return CRIT_LEVEL_C;
122 /* failure */
123 return NUM_CRIT_LEVELS;
124}
125
126#define OPTSTR "a:b:d:p:c:wlves:r:i:"
127
128#define COIN_PROB 0.5
129
130int main(int argc, char** argv)
131{
132 int ret;
133 lt_t wcet;
134 lt_t period;
135 lt_t lvl_c_time;
136 int migrate = 0;
137 int cpu = 0;
138 int opt;
139 int wait = 0;
140 int test_loop = 0;
141 int want_enforcement = 0;
142 unsigned long seed = 1;
143 double duration = 0, start;
144 double scale = 1.0;
145 double alpha = -1, beta = -1, beta_sample, exec_time;
146 task_class_t class = RT_CLASS_HARD;
147 struct mc_task mc_task = { .crit = NUM_CRIT_LEVELS, .lvl_a_id = -1 };
148
149 progname = argv[0];
150
151 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
152 switch (opt) {
153 case 'a':
154 alpha = atof(optarg);
155 break;
156 case 'b':
157 beta = atof(optarg);
158 break;
159 case 'd':
160 seed = atoi(optarg);
161 break;
162 case 'w':
163 wait = 1;
164 break;
165 case 'p':
166 cpu = atoi(optarg);
167 migrate = 1;
168 break;
169 case 'c':
170 class = str2class(optarg);
171 if (class == -1)
172 usage("Unknown task class.");
173 break;
174 case 'e':
175 want_enforcement = 1;
176 break;
177 case 'l':
178 test_loop = 1;
179 break;
180 case 's':
181 scale = atof(optarg);
182 break;
183 case 'r':
184 mc_task.crit = str2crit(optarg);
185 if (NUM_CRIT_LEVELS == mc_task.crit)
186 usage("Bad crit level.");
187 break;
188 case 'i':
189 mc_task.lvl_a_id = atoi(optarg);
190 break;
191 case ':':
192 usage("Argument missing.");
193 break;
194 case '?':
195 default:
196 usage("Bad argument.");
197 break;
198 }
199 }
200
201 if (test_loop) {
202 debug_delay_loop();
203 return 0;
204 }
205
206 if (argc - optind < 4)
207 usage("Arguments missing.");
208
209 lvl_c_time = atoi(argv[optind + 0]);
210 wcet = atoi(argv[optind + 1]);
211 period = atoi(argv[optind + 2]);
212
213 if (seed < 1)
214 usage("Seed < 1 not allowed.");
215 if (alpha <= 0 || beta <= 0)
216 usage("Need positive alpha and beta.");
217 if (wcet <= 0)
218 usage("The worst-case execution time must be a "
219 "positive number.");
220 if (period <= 0)
221 usage("The period must be a positive number.");
222 if (wcet > period) {
223 usage("The worst-case execution time must not "
224 "exceed the period.");
225 }
226
227 duration = atof(argv[optind + 3]);
228
229 setup_rng(seed);
230
231 if (migrate) {
232 ret = be_migrate_to(cpu);
233 if (ret < 0)
234 bail_out("could not migrate to target partition");
235 }
236
237 ret = sporadic_task_ns(wcet, period, 0, cpu, class,
238 want_enforcement ? PRECISE_ENFORCEMENT
239 : NO_ENFORCEMENT,
240 migrate);
241 if (ret < 0)
242 bail_out("could not setup rt task params");
243
244 if (NUM_CRIT_LEVELS != mc_task.crit) {
245 ret = set_rt_task_mc_param(gettid(), &mc_task);
246 if (ret < 0)
247 bail_out("could not setup rt mixed criticality params");
248 }
249
250 init_litmus();
251
252 ret = task_mode(LITMUS_RT_TASK);
253 if (ret != 0)
254 bail_out("could not become RT task");
255
256 if (wait) {
257 ret = wait_for_ts_release();
258 if (ret != 0)
259 bail_out("wait_for_ts_release()");
260 }
261
262 start = wctime();
263
264 do {
265 double coin_flip = gsl_rng_uniform(coin_rng);
266 if (coin_flip < COIN_PROB) {
267 beta_sample = gsl_ran_beta(beta_rng, alpha, beta);
268 exec_time = lvl_c_time * 20.0 * beta_sample * scale;
269 } else
270 exec_time = lvl_c_time;
271 /* convert to seconds */
272 exec_time = exec_time * 0.000000001;
273 } while(job(exec_time, start + duration));
274
275 ret = task_mode(BACKGROUND_TASK);
276 if (ret != 0)
277 bail_out("could not become regular task (huh?)");
278
279 gsl_rng_free(beta_rng);
280 gsl_rng_free(coin_rng);
281
282 return 0;
283}
diff --git a/bin/rtspin.c b/bin/rtspin.c
index a6a8ac6..a19637c 100644
--- a/bin/rtspin.c
+++ b/bin/rtspin.c
@@ -5,13 +5,12 @@
5#include <unistd.h> 5#include <unistd.h>
6#include <time.h> 6#include <time.h>
7#include <assert.h> 7#include <assert.h>
8 8#include <strings.h>
9#include <string.h>
9 10
10#include "litmus.h" 11#include "litmus.h"
11#include "common.h" 12#include "common.h"
12 13
13
14
15static void usage(char *error) { 14static void usage(char *error) {
16 fprintf(stderr, "Error: %s\n", error); 15 fprintf(stderr, "Error: %s\n", error);
17 fprintf(stderr, 16 fprintf(stderr,
@@ -21,6 +20,7 @@ static void usage(char *error) {
21 " rt_spin -l\n" 20 " rt_spin -l\n"
22 "\n" 21 "\n"
23 "COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n" 22 "COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n"
23 " [-h NUM-COLORS,AVG-WAYS]\n"
24 "\n" 24 "\n"
25 "WCET and PERIOD are milliseconds, DURATION is seconds.\n"); 25 "WCET and PERIOD are milliseconds, DURATION is seconds.\n");
26 exit(EXIT_FAILURE); 26 exit(EXIT_FAILURE);
@@ -161,7 +161,7 @@ static int job(double exec_time, double program_end)
161 } 161 }
162} 162}
163 163
164#define OPTSTR "p:c:wlveo:f:s:" 164#define OPTSTR "p:c:wlveo:f:s:h:"
165 165
166int main(int argc, char** argv) 166int main(int argc, char** argv)
167{ 167{
@@ -181,7 +181,9 @@ int main(int argc, char** argv)
181 double *exec_times = NULL; 181 double *exec_times = NULL;
182 double scale = 1.0; 182 double scale = 1.0;
183 task_class_t class = RT_CLASS_HARD; 183 task_class_t class = RT_CLASS_HARD;
184 int cur_job, num_jobs = 0; 184 int cur_job, num_jobs;
185 int task_colors = 0;
186 int avg_ways = 0;
185 187
186 progname = argv[0]; 188 progname = argv[0];
187 189
@@ -214,6 +216,9 @@ int main(int argc, char** argv)
214 case 's': 216 case 's':
215 scale = atof(optarg); 217 scale = atof(optarg);
216 break; 218 break;
219 case 'h':
220 sscanf(optarg, "%d,%d", &task_colors, &avg_ways);
221 break;
217 case ':': 222 case ':':
218 usage("Argument missing."); 223 usage("Argument missing.");
219 break; 224 break;
@@ -283,6 +288,8 @@ int main(int argc, char** argv)
283 288
284 init_litmus(); 289 init_litmus();
285 290
291 request_resources(task_colors, avg_ways);
292
286 ret = task_mode(LITMUS_RT_TASK); 293 ret = task_mode(LITMUS_RT_TASK);
287 if (ret != 0) 294 if (ret != 0)
288 bail_out("could not become RT task"); 295 bail_out("could not become RT task");
diff --git a/bin/rtspin.ovh.c b/bin/rtspin.ovh.c
new file mode 100644
index 0000000..d130eac
--- /dev/null
+++ b/bin/rtspin.ovh.c
@@ -0,0 +1,239 @@
1#include <sys/time.h>
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <time.h>
7#include <assert.h>
8#include <strings.h>
9
10
11#include "litmus.h"
12#include "common.h"
13
14#include <litmus/sched_mc.h>
15
16
17static void usage(char *error) {
18 fprintf(stderr, "Error: %s\n", error);
19 fprintf(stderr,
20 "Usage:\n"
21 " rt_spin [COMMON-OPTS] EXEC_TIME WCET PERIOD DURATION\n"
22 " rt_spin -l\n"
23 "\n"
24 "COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n"
25 " [-r CRITICALITY = [a|b|c|d]] [-i MC-LVL-A-ID]\n"
26 "\n"
27 "WCET and PERIOD are nanoseconds, DURATION is seconds.\n");
28 exit(EXIT_FAILURE);
29}
30
31#define NUMS 4096
32static int num[NUMS];
33static char* progname;
34
35static int loop_once(void)
36{
37 int i, j = 0;
38 for (i = 0; i < NUMS; i++)
39 j += num[i]++;
40 return j;
41}
42
43static int loop_for(double exec_time, double emergency_exit)
44{
45 double last_loop = 0, loop_start;
46 int tmp = 0;
47
48 double start = cputime();
49 double now = cputime();
50
51 while (now + last_loop < start + exec_time) {
52 loop_start = now;
53 tmp += loop_once();
54 now = cputime();
55 last_loop = now - loop_start;
56 if (emergency_exit && wctime() > emergency_exit) {
57 /* Oops --- this should only be possible if the execution time tracking
58 * is broken in the LITMUS^RT kernel. */
59 fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
60 fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
61 break;
62 }
63 }
64
65 return tmp;
66}
67
68
69static void debug_delay_loop(void)
70{
71 double start, end, delay;
72
73 while (1) {
74 for (delay = 0.5; delay > 0.01; delay -= 0.01) {
75 start = wctime();
76 loop_for(delay, 0);
77 end = wctime();
78 printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
79 delay,
80 end - start,
81 end - start - delay,
82 100 * (end - start - delay) / delay);
83 }
84 }
85}
86
87static int job(double exec_time, double program_end)
88{
89 if (wctime() > program_end)
90 return 0;
91 else {
92 loop_for(exec_time, program_end + 1);
93 sleep_next_period();
94 return 1;
95 }
96}
97
98enum crit_level str2crit(const char* str)
99{
100 if (0 == strncasecmp("a", str, 1))
101 return CRIT_LEVEL_A;
102 else if (0 == strncasecmp("b", str, 1))
103 return CRIT_LEVEL_B;
104 else if (0 == strncasecmp("c", str, 1))
105 return CRIT_LEVEL_C;
106 /* failure */
107 return NUM_CRIT_LEVELS;
108}
109
110#define OPTSTR "p:c:wlves:r:i:"
111
112int main(int argc, char** argv)
113{
114 int ret;
115 lt_t exec_time;
116 lt_t wcet;
117 lt_t period;
118 int migrate = 0;
119 int cpu = 0;
120 int opt;
121 int wait = 0;
122 int test_loop = 0;
123 int want_enforcement = 0;
124 double duration = 0, start;
125 double scale = 1.0;
126 task_class_t class = RT_CLASS_HARD;
127 struct mc_task mc_task = { .crit = NUM_CRIT_LEVELS, .lvl_a_id = -1 };
128
129 progname = argv[0];
130
131 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
132 switch (opt) {
133 case 'w':
134 wait = 1;
135 break;
136 case 'p':
137 cpu = atoi(optarg);
138 migrate = 1;
139 break;
140 case 'c':
141 class = str2class(optarg);
142 if (class == -1)
143 usage("Unknown task class.");
144 break;
145 case 'e':
146 want_enforcement = 1;
147 break;
148 case 'l':
149 test_loop = 1;
150 break;
151 case 's':
152 scale = atof(optarg);
153 break;
154 case 'r':
155 mc_task.crit = str2crit(optarg);
156 if (NUM_CRIT_LEVELS == mc_task.crit)
157 usage("Bad crit level.");
158 break;
159 case 'i':
160 mc_task.lvl_a_id = atoi(optarg);
161 break;
162 case ':':
163 usage("Argument missing.");
164 break;
165 case '?':
166 default:
167 usage("Bad argument.");
168 break;
169 }
170 }
171
172 if (test_loop) {
173 debug_delay_loop();
174 return 0;
175 }
176
177 if (argc - optind < 4)
178 usage("Arguments missing.");
179
180 exec_time = atoi(argv[optind + 0]);
181 wcet = atoi(argv[optind + 1]);
182 period = atoi(argv[optind + 2]);
183
184 if (exec_time <= 0 || exec_time > period)
185 usage("bad execution time");
186 if (wcet <= 0)
187 usage("The worst-case execution time must be a "
188 "positive number.");
189 if (period <= 0)
190 usage("The period must be a positive number.");
191 if (wcet > period) {
192 usage("The worst-case execution time must not "
193 "exceed the period.");
194 }
195
196 duration = atof(argv[optind + 3]);
197
198 if (migrate) {
199 ret = be_migrate_to(cpu);
200 if (ret < 0)
201 bail_out("could not migrate to target partition");
202 }
203
204 ret = sporadic_task_ns(wcet, period, 0, cpu, class,
205 want_enforcement ? PRECISE_ENFORCEMENT
206 : NO_ENFORCEMENT,
207 migrate);
208 if (ret < 0)
209 bail_out("could not setup rt task params");
210
211 if (NUM_CRIT_LEVELS != mc_task.crit) {
212 ret = set_rt_task_mc_param(gettid(), &mc_task);
213 if (ret < 0)
214 bail_out("could not setup rt mixed criticality params");
215 }
216
217 init_litmus();
218
219 ret = task_mode(LITMUS_RT_TASK);
220 if (ret != 0)
221 bail_out("could not become RT task");
222
223 if (wait) {
224 ret = wait_for_ts_release();
225 if (ret != 0)
226 bail_out("wait_for_ts_release()");
227 }
228
229 start = wctime();
230
231 /* conver to seconds and scale */
232 while (job(exec_time * 0.000000001 * scale, start + duration));
233
234 ret = task_mode(BACKGROUND_TASK);
235 if (ret != 0)
236 bail_out("could not become regular task (huh?)");
237
238 return 0;
239}
diff --git a/include/common.h b/include/common.h
index d1234ba..5c7ed68 100644
--- a/include/common.h
+++ b/include/common.h
@@ -1,7 +1,8 @@
1#ifndef COMMON_H 1#ifndef COMMON_H
2#define COMMON_H 2#define COMMON_H
3 3
4
5void bail_out(const char* msg); 4void bail_out(const char* msg);
6 5
6void request_resources(int task_colors, int avg_ways);
7
7#endif 8#endif
diff --git a/include/litmus.h b/include/litmus.h
index 4c85d28..82e2ba2 100644
--- a/include/litmus.h
+++ b/include/litmus.h
@@ -27,6 +27,9 @@ int be_migrate_to(int target_cpu);
27int set_rt_task_param(pid_t pid, struct rt_task* param); 27int set_rt_task_param(pid_t pid, struct rt_task* param);
28int get_rt_task_param(pid_t pid, struct rt_task* param); 28int get_rt_task_param(pid_t pid, struct rt_task* param);
29 29
30struct mc_task;
31int set_rt_task_mc_param(pid_t pid, struct mc_task *param);
32
30/* setup helper */ 33/* setup helper */
31 34
32/* times are given in ms */ 35/* times are given in ms */
diff --git a/src/kernel_iface.c b/src/kernel_iface.c
index 33d56df..bd47d5c 100644
--- a/src/kernel_iface.c
+++ b/src/kernel_iface.c
@@ -75,6 +75,13 @@ void exit_np(void)
75 } 75 }
76} 76}
77 77
78void request_resource(int resource, int replicas)
79{
80 if (likely(ctrl_page != NULL)) {
81 ctrl_page->requests[resource] = replicas;
82 }
83}
84
78int requested_to_preempt(void) 85int requested_to_preempt(void)
79{ 86{
80 return (likely(ctrl_page != NULL) && ctrl_page->sched.np.preempt); 87 return (likely(ctrl_page != NULL) && ctrl_page->sched.np.preempt);
diff --git a/src/litmus.c b/src/litmus.c
index d3cc6bb..d8a6b96 100644
--- a/src/litmus.c
+++ b/src/litmus.c
@@ -72,6 +72,7 @@ int sporadic_task_ns(lt_t e, lt_t p, lt_t phase,
72 ret = be_migrate_to(cpu); 72 ret = be_migrate_to(cpu);
73 check("migrate to cpu"); 73 check("migrate to cpu");
74 } 74 }
75
75 return set_rt_task_param(gettid(), &param); 76 return set_rt_task_param(gettid(), &param);
76} 77}
77 78