Attachment 'liblitmus-rtns17.patch'

Download

   1 diff --git .gitignore .gitignore
   2 index a52500b..ec913c5 100644
   3 --- .gitignore
   4 +++ .gitignore
   5 @@ -3,10 +3,13 @@
   6  *.a
   7  
   8  
   9 +# editor backup files
  10 +*~
  11  
  12  # generated files
  13  tests/test_catalog.inc
  14  *.d
  15 +*.d.*
  16  docs/
  17  
  18  # executables
  19 @@ -23,6 +26,13 @@ showst
  20  rtspin
  21  cycles
  22  measure_syscall
  23 +uncache
  24 +resctrl
  25 +mc2pollute
  26 +mc2spin
  27 +mc2syn
  28 +memthrash
  29 +mttest
  30  
  31  # build system files
  32  .config
  33 @@ -32,3 +42,5 @@ test_catalog.inc
  34  # files copied in from the kernel tree
  35  include/litmus
  36  arch/*/include/asm
  37 +arch/x86/include/generated
  38 +arch/x86/include/uapi
  39 diff --git Makefile Makefile
  40 index 4742fd2..3e6ee15 100644
  41 --- Makefile
  42 +++ Makefile
  43 @@ -19,7 +19,7 @@ LITMUS_KERNEL ?= ../litmus-rt
  44  # Internal configuration.
  45  
  46  # compiler flags
  47 -flags-debug    = -O2 -Wall -Werror -g -Wdeclaration-after-statement
  48 +flags-debug    = -O0 -Wall -g -Wdeclaration-after-statement
  49  flags-api      = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE
  50  
  51  # architecture-specific flags
  52 @@ -73,11 +73,14 @@ AR  := ${CROSS_COMPILE}${AR}
  53  
  54  all     = lib ${rt-apps}
  55  rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
  56 -	  base_mt_task uncache runtests
  57 +	base_mt_task uncache runtests resctrl mc2mem \
  58 +	mc2spin mtdag mode_request rt_mode_poll
  59 +
  60 +#mc2thrash mc2thrash1 mc2thrash2 mc2thrash3
  61  
  62  .PHONY: all lib clean dump-config TAGS tags cscope help doc
  63  
  64 -all: ${all} inc/config.makefile
  65 +all: ${all} inc/config.makefile post-build
  66  
  67  # Write a distilled version of the flags for clients of the library. Ideally,
  68  # this should depend on liblitmus.a, but that requires LIBLITMUS to be a
  69 @@ -126,6 +129,7 @@ clean:
  70  	rm -f inc/config.makefile
  71  	rm -f tags TAGS cscope.files cscope.out
  72  	rm -r -f docs
  73 +	rm -f mc2mem*
  74  
  75  # Emacs Tags
  76  TAGS:
  77 @@ -143,6 +147,8 @@ cscope:
  78  	@find . -type f -and  -iname '*.[ch]' | xargs printf "%s\n" > cscope.files
  79  	@cscope -b
  80  
  81 +post-build:
  82 +	
  83  # ##############################################################################
  84  # Kernel headers.
  85  # The kernel does not like being #included directly, so let's
  86 @@ -168,7 +174,8 @@ litmus-headers = \
  87  	include/litmus/rt_param.h \
  88  	include/litmus/fpmath.h \
  89  	include/litmus/unistd_32.h \
  90 -	include/litmus/unistd_64.h
  91 +	include/litmus/unistd_64.h \
  92 +	include/litmus/mc2_common.h
  93  
  94  unistd-headers = \
  95    $(foreach file,${unistd-${ARCH}},arch/${include-${ARCH}}/include/$(file))
  96 @@ -234,6 +241,22 @@ obj-release_ts = release_ts.o
  97  obj-measure_syscall = null_call.o
  98  lib-measure_syscall = -lm
  99  
 100 +obj-resctrl = resctrl.o
 101 +
 102 +obj-mc2spin = mc2spin.o common.o
 103 +lib-mc2spin = -lrt -static
 104 +
 105 +obj-mc2mem = mc2mem.o common.o
 106 +lib-mc2mem = -lrt -static
 107 +
 108 +obj-mtdag = mtdag.o common.o
 109 +ldf-mtdag = -lrt -pthread -static
 110 +
 111 +obj-mode_request = mode_request.o common.o
 112 +lib-mode_request = -lrt -static
 113 +
 114 +obj-rt_mode_poll = rt_mode_poll.o common.o
 115 +lib-rt_mode_poll = -lrt -static
 116  # ##############################################################################
 117  # Build everything that depends on liblitmus.
 118  
 119 diff --git bin/base_mt_task.c bin/base_mt_task.c
 120 index aec79a4..1665203 100644
 121 --- bin/base_mt_task.c
 122 +++ bin/base_mt_task.c
 123 @@ -29,11 +29,13 @@
 124  /* Let's create 10 threads in the example, 
 125   * for a total utilization of 1.
 126   */
 127 -#define NUM_THREADS      10 
 128 +#define NUM_THREADS      3 
 129  
 130  /* The information passed to each thread. Could be anything. */
 131  struct thread_context {
 132  	int id;
 133 +	int cpu;
 134 +	int job_no;
 135  };
 136  
 137  /* The real-time thread program. Doesn't have to be the same for
 138 @@ -45,7 +47,7 @@ void* rt_thread(void *tcontext);
 139   * Returns 1 -> task should exit.
 140   *         0 -> task should continue.
 141   */
 142 -int job(void);
 143 +int job(struct thread_context *tcx);
 144  
 145  
 146  /* Catch errors.
 147 @@ -97,6 +99,8 @@ int main(int argc, char** argv)
 148  	 */
 149  	for (i = 0; i < NUM_THREADS; i++) {
 150  		ctx[i].id = i;
 151 +		ctx[i].cpu = 0;
 152 +		ctx[i].job_no = 0;
 153  		pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i));
 154  	}
 155  
 156 @@ -125,6 +129,7 @@ void* rt_thread(void *tcontext)
 157  	int do_exit;
 158  	struct thread_context *ctx = (struct thread_context *) tcontext;
 159  	struct rt_task param;
 160 +	int ret;
 161  
 162  	/* Set up task parameters */
 163  	init_rt_task_param(&param);
 164 @@ -157,6 +162,12 @@ void* rt_thread(void *tcontext)
 165  	 * where CPU ranges from 0 to "Number of CPUs" - 1 before calling
 166  	 * set_rt_task_param().
 167  	 */
 168 +	param.cpu = ctx->cpu;
 169 +	ret = be_migrate_to_cpu(ctx->cpu);
 170 +	if (ret < 0) {
 171 +		printf("RT Thread %d fails to migrate to CPU%d\n", ctx->id, ctx->cpu);
 172 +		return NULL;
 173 +	}
 174  	CALL( set_rt_task_param(gettid(), &param) );
 175  
 176  	/*****
 177 @@ -176,7 +187,7 @@ void* rt_thread(void *tcontext)
 178  		/* Wait until the next job is released. */
 179  		sleep_next_period();
 180  		/* Invoke job. */
 181 -		do_exit = job();		
 182 +		do_exit = job(ctx);		
 183  	} while (!do_exit);
 184  
 185  
 186 @@ -192,10 +203,13 @@ void* rt_thread(void *tcontext)
 187  
 188  
 189  
 190 -int job(void) 
 191 +int job(struct thread_context *tcx) 
 192  {
 193  	/* Do real-time calculation. */
 194 -
 195 +	printf("Job executinig\n");
 196 +	tcx->job_no++;
 197 +	if (tcx->job_no == 5)
 198 +		return 1;
 199  	/* Don't exit. */
 200  	return 0;
 201  }
 202 diff --git bin/mc2mem.c bin/mc2mem.c
 203 new file mode 100644
 204 index 0000000..1087381
 205 --- /dev/null
 206 +++ bin/mc2mem.c
 207 @@ -0,0 +1,326 @@
 208 +#include <sys/time.h>
 209 +#include <sys/mman.h>
 210 +
 211 +#include <stdio.h>
 212 +#include <stdlib.h>
 213 +#include <unistd.h>
 214 +#include <time.h>
 215 +#include <string.h>
 216 +#include <assert.h>
 217 +#include <limits.h>
 218 +#include <fcntl.h>
 219 +#include <math.h>
 220 +
 221 +#include "litmus.h"
 222 +#include "common.h"
 223 +#include "cache_common.h"
 224 +
 225 +#define PAGE_SIZE (4096)
 226 +#define CACHELINE_SIZE 32
 227 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
 228 +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
 229 +#define INTS_IN_1KB	(1024 / sizeof(int))
 230 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
 231 +
 232 +static int loops = 100;
 233 +static cacheline_t* arena = NULL;
 234 +static int verbose = 0;
 235 +
 236 +struct timeval t1,t2;
 237 +
 238 +
 239 +#define UNCACHE_DEV "/dev/litmus/uncache"
 240 +
 241 +/* Random walk around the arena in cacheline-sized chunks.
 242 +   Cacheline-sized chucks ensures the same utilization of each
 243 +   hit line as sequential read. (Otherwise, our utilization
 244 +   would only be 1/INTS_IN_CACHELINE.) */
 245 +static int random_walk(cacheline_t *mem, int wss, int write_cycle)
 246 +{
 247 +	/* a random cycle among the cache lines was set up by init_arena(). */
 248 +	int sum, i, next;
 249 +
 250 +	int numlines = wss * CACHELINES_IN_1KB;
 251 +
 252 +	sum = 0;
 253 +
 254 +	/* contents of arena is structured s.t. offsets are all
 255 +	   w.r.t. to start of arena, so compute the initial offset */
 256 +	next = mem - arena;
 257 +
 258 +	if (write_cycle == 0) {
 259 +		for (i = 0; i < numlines; i++) {
 260 +			/* every element in the cacheline has the same value */
 261 +			next = arena[next].line[0];
 262 +			sum += next;
 263 +		}
 264 +	}
 265 +	
 266 +	else {
 267 +		int w, which_line;
 268 +		for (i = 0, w = 0; i < numlines; i++) {
 269 +			which_line = next;
 270 +			next = arena[next].line[0];
 271 +			if((w % write_cycle) != (write_cycle - 1)) {
 272 +				sum += next;
 273 +			}
 274 +			else {
 275 +				((volatile cacheline_t*)arena)[which_line].line[0] = next;
 276 +			}
 277 +		}
 278 +	}
 279 +	return sum;
 280 +}
 281 +
 282 +static cacheline_t* random_start(int wss)
 283 +{
 284 +	return arena + randrange(0, ((wss * 1024)/sizeof(cacheline_t)));
 285 +}
 286 +
 287 +static volatile int dont_optimize_me = 0;
 288 +
 289 +static void usage(char *error) {
 290 +	fprintf(stderr, "Error: %s\n", error);
 291 +	fprintf(stderr,
 292 +		"Usage:\n"
 293 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
 294 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
 295 +		"	rt_spin -l\n"
 296 +		"\n"
 297 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
 298 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-m CRITICALITY LEVEL]\n"
 299 +		"              [-k WSS] [-l LOOPS] [-b BUDGET]\n"
 300 +		"\n"
 301 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n");
 302 +	exit(EXIT_FAILURE);
 303 +}
 304 +
 305 +static int loop_once(int wss)
 306 +{
 307 +	cacheline_t *mem;
 308 +	int temp;
 309 +	
 310 +	mem = random_start(wss);
 311 +	temp = random_walk(mem, wss, 1);
 312 +    
 313 +	//mem = sequential_start(wss);
 314 +	//temp = sequential_walk(mem, wss, 0);
 315 +	dont_optimize_me = temp;
 316 +	
 317 +	return dont_optimize_me;
 318 +}
 319 +
 320 +static int job(int wss, double exec_time, double program_end)
 321 +{
 322 +	if (wctime() > program_end)
 323 +		return 0;
 324 +	else {
 325 +		register unsigned int iter = 0;
 326 +		register cycles_t t;
 327 +		t = get_cycles();
 328 +		while(iter++ < loops) {
 329 +			loop_once(wss);
 330 +		}
 331 +		t = get_cycles() - t;
 332 +		if (verbose)
 333 +			printf("%ld cycles\n", t);
 334 +  		sleep_next_period(); 
 335 +    	return 1;
 336 +	}
 337 +}
 338 +
 339 +#define OPTSTR "p:wl:m:i:b:k:vs:"
 340 +int main(int argc, char** argv)
 341 +{
 342 +	int ret, i;
 343 +	lt_t wcet, period, budget;
 344 +	double wcet_ms, period_ms, budget_ms;
 345 +	unsigned int priority = LITMUS_NO_PRIORITY;
 346 +	int migrate = 0;
 347 +	int cluster = 0;
 348 +	int opt;
 349 +	int wait = 0;
 350 +	double duration = 0, start = 0;
 351 +	struct rt_task param;
 352 +	struct mc2_task mc2_param;
 353 +	struct reservation_config config;
 354 +	int res_type = PERIODIC_POLLING;
 355 +	size_t arena_sz;
 356 +	int wss = 1;
 357 +	uint32_t mode_mask;
 358 +
 359 +	/* default for reservation */
 360 +	config.id = 0;
 361 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
 362 +	config.cpu = -1;
 363 +	
 364 +	mc2_param.crit = CRIT_LEVEL_C;
 365 +	
 366 +	budget_ms = 1000;
 367 +	
 368 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
 369 +		switch (opt) {
 370 +		case 'w':
 371 +			wait = 1;
 372 +			break;
 373 +		case 'p':
 374 +			cluster = atoi(optarg);
 375 +			migrate = 1;
 376 +			config.cpu = cluster;
 377 +			break;
 378 +		case 'l':
 379 +			loops = atoi(optarg);
 380 +			break;
 381 +		case 's':
 382 +			wss = atoi(optarg);
 383 +			break;
 384 +		case 'k':
 385 +			mode_mask = atoi(optarg);
 386 +			break;
 387 +		case 'm':
 388 +			mc2_param.crit = atoi(optarg);
 389 +			if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
 390 +				res_type = PERIODIC_POLLING;
 391 +			}
 392 +			else
 393 +				usage("Invalid criticality level.");
 394 +			break;
 395 +		case 'b':
 396 +			budget_ms = atof(optarg);
 397 +			break;
 398 +		case 'i':
 399 +			config.priority = atoi(optarg);
 400 +			break;
 401 +		case 'v':
 402 +			verbose = 1;
 403 +			break;
 404 +		case ':':
 405 +			usage("Argument missing.");
 406 +			break;
 407 +		case '?':
 408 +		default:
 409 +			usage("Bad argument.");
 410 +			break;
 411 +		}
 412 +	}
 413 +	srand(getpid());
 414 +
 415 +	/*
 416 +	 * We need three parameters
 417 +	 */
 418 +	if (argc - optind < 3)
 419 +		usage("Arguments missing.");
 420 +
 421 +	wcet_ms   = atof(argv[optind + 0]);
 422 +	period_ms = atof(argv[optind + 1]);
 423 +
 424 +	wcet   = ms2ns(wcet_ms);
 425 +	period = ms2ns(period_ms);
 426 +	budget = ms2ns(budget_ms);
 427 +	if (wcet <= 0)
 428 +		usage("The worst-case execution time must be a "
 429 +				"positive number.");
 430 +	if (period <= 0)
 431 +		usage("The period must be a positive number.");
 432 +	if (wcet > period) {
 433 +		usage("The worst-case execution time must not "
 434 +				"exceed the period.");
 435 +	}
 436 +	if (wss == 0) {
 437 +		usage("You need to specify a WSS (-k option).");
 438 +	}
 439 +
 440 +	duration  = atof(argv[optind + 2]);
 441 +	
 442 +	if (migrate) {
 443 +		ret = be_migrate_to_domain(cluster);
 444 +		if (ret < 0)
 445 +			bail_out("could not migrate to target partition or cluster.");
 446 +	}
 447 +
 448 +	/* reservation config */
 449 +	config.id = gettid();
 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 +	
 455 +	if (config.polling_params.budget > config.polling_params.period) {
 456 +		usage("The budget must not exceed the period.");
 457 +	}
 458 +	
 459 +	/* create a reservation */
 460 +	for(i = 0; i < 32; i++){
 461 +		if ( !( (1 << i) & mode_mask) )
 462 +			continue;
 463 +		config.mode = i;
 464 +		ret = reservation_create(res_type, &config);
 465 +		if (ret < 0) {
 466 +			bail_out("failed to create reservation.");
 467 +		}
 468 +	}
 469 +	
 470 +	init_rt_task_param(&param);
 471 +	param.exec_cost = wcet;
 472 +	param.period = period;
 473 +	param.priority = priority;
 474 +	param.cls = RT_CLASS_HARD;
 475 +	param.release_policy = TASK_PERIODIC;
 476 +	param.budget_policy = NO_ENFORCEMENT;
 477 +	if (migrate) {
 478 +		param.cpu = gettid();
 479 +		//param.cpu = config.cpu;
 480 +	}
 481 +	ret = set_rt_task_param(gettid(), &param);
 482 +	if (ret < 0)
 483 +		bail_out("could not setup rt task params");
 484 +	
 485 +	mc2_param.res_id = gettid();
 486 +	mc2_param.mode_mask = mode_mask;
 487 +	ret = set_mc2_task_param(gettid(), &mc2_param);
 488 +	if (ret < 0)
 489 +		bail_out("could not setup mc2 task params");
 490 +	
 491 +	arena_sz = wss*1024;
 492 +	arena = alloc_arena(arena_sz, 0, 0);
 493 +	init_arena(arena, arena_sz);
 494 +	
 495 +	mlockall(MCL_CURRENT | MCL_FUTURE);
 496 +	
 497 +	ret = init_litmus();
 498 +	if (ret != 0)
 499 +		bail_out("init_litmus() failed\n");
 500 +
 501 +	start = wctime();
 502 +	ret = task_mode(LITMUS_RT_TASK);
 503 +	if (ret != 0)
 504 +		bail_out("could not become RT task");
 505 +
 506 +	if (mc2_param.crit == CRIT_LEVEL_C)
 507 +		set_page_color(-1);
 508 +	else
 509 +		set_page_color(config.cpu);
 510 +
 511 +	mlockall(MCL_CURRENT | MCL_FUTURE);
 512 +	
 513 +	if (wait) {
 514 +		ret = wait_for_ts_release();
 515 +		if (ret != 0)
 516 +			bail_out("wait_for_ts_release()");
 517 +		start = wctime();
 518 +	}
 519 +
 520 +	while (job(wss, wcet_ms * 0.001, start + duration)) {};
 521 +
 522 +//set_page_color(config.cpu);
 523 +	//test_call(0);
 524 +	ret = task_mode(BACKGROUND_TASK);
 525 +	if (ret != 0)
 526 +		bail_out("could not become regular task (huh?)");
 527 +
 528 +	reservation_destroy(gettid(), config.cpu);
 529 +	dealloc_arena(arena, arena_sz);
 530 +	printf("%s finished.\n", argv[0]);
 531 +	//test_call(1);
 532 +	return 0;
 533 +}
 534 diff --git bin/mc2spin.c bin/mc2spin.c
 535 new file mode 100644
 536 index 0000000..dfb5c80
 537 --- /dev/null
 538 +++ bin/mc2spin.c
 539 @@ -0,0 +1,545 @@
 540 +#include <sys/time.h>
 541 +#include <sys/mman.h>
 542 +
 543 +#include <stdio.h>
 544 +#include <stdlib.h>
 545 +#include <unistd.h>
 546 +#include <time.h>
 547 +#include <string.h>
 548 +#include <assert.h>
 549 +#include <limits.h>
 550 +
 551 +
 552 +#include "litmus.h"
 553 +#include "common.h"
 554 +
 555 +#define PAGE_SIZE 4096
 556 +
 557 +static void usage(char *error) {
 558 +	fprintf(stderr, "Error: %s\n", error);
 559 +	fprintf(stderr,
 560 +		"Usage:\n"
 561 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
 562 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
 563 +		"	rt_spin -l\n"
 564 +		"\n"
 565 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
 566 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
 567 +		"              [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
 568 +		"              [-i [start,end]:[start,end]...]\n"
 569 +		"\n"
 570 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n"
 571 +		"CRITICAL SECTION LENGTH is in milliseconds.\n");
 572 +	exit(EXIT_FAILURE);
 573 +}
 574 +
 575 +/*
 576 + * returns the character that made processing stop, newline or EOF
 577 + */
 578 +static int skip_to_next_line(FILE *fstream)
 579 +{
 580 +	int ch;
 581 +	for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
 582 +	return ch;
 583 +}
 584 +
 585 +static void skip_comments(FILE *fstream)
 586 +{
 587 +	int ch;
 588 +	for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
 589 +		skip_to_next_line(fstream);
 590 +	ungetc(ch, fstream);
 591 +}
 592 +
 593 +static void get_exec_times(const char *file, const int column,
 594 +			   int *num_jobs,    double **exec_times)
 595 +{
 596 +	FILE *fstream;
 597 +	int  cur_job, cur_col, ch;
 598 +	*num_jobs = 0;
 599 +
 600 +	fstream = fopen(file, "r");
 601 +	if (!fstream)
 602 +		bail_out("could not open execution time file");
 603 +
 604 +	/* figure out the number of jobs */
 605 +	do {
 606 +		skip_comments(fstream);
 607 +		ch = skip_to_next_line(fstream);
 608 +		if (ch != EOF)
 609 +			++(*num_jobs);
 610 +	} while (ch != EOF);
 611 +
 612 +	if (-1 == fseek(fstream, 0L, SEEK_SET))
 613 +		bail_out("rewinding file failed");
 614 +
 615 +	/* allocate space for exec times */
 616 +	*exec_times = calloc(*num_jobs, sizeof(*exec_times));
 617 +	if (!*exec_times)
 618 +		bail_out("couldn't allocate memory");
 619 +
 620 +	for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
 621 +
 622 +		skip_comments(fstream);
 623 +
 624 +		for (cur_col = 1; cur_col < column; ++cur_col) {
 625 +			/* discard input until we get to the column we want */
 626 +			int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
 627 +		}
 628 +
 629 +		/* get the desired exec. time */
 630 +		if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
 631 +			fprintf(stderr, "invalid execution time near line %d\n",
 632 +					cur_job);
 633 +			exit(EXIT_FAILURE);
 634 +		}
 635 +
 636 +		skip_to_next_line(fstream);
 637 +	}
 638 +
 639 +	assert(cur_job == *num_jobs);
 640 +	fclose(fstream);
 641 +}
 642 +
 643 +#define NUMS 16
 644 +static int num[NUMS];
 645 +static char* progname;
 646 +
 647 +static int loop_once(void)
 648 +{
 649 +	int i, j = 0;
 650 +	for (i = 0; i < NUMS; i++)
 651 +		j += num[i];
 652 +	return j;
 653 +}
 654 +
 655 +static int loop_for(double exec_time, double emergency_exit)
 656 +{
 657 +	double last_loop = 0, loop_start;
 658 +	int tmp = 0;
 659 +
 660 +	double start = cputime();
 661 +	double now = cputime();
 662 +
 663 +	while (now + last_loop < start + exec_time) {
 664 +		loop_start = now;
 665 +		tmp += loop_once();
 666 +		now = cputime();
 667 +		last_loop = now - loop_start;
 668 +		if (emergency_exit && wctime() > emergency_exit) {
 669 +			/* Oops --- this should only be possible if the execution time tracking
 670 +			 * is broken in the LITMUS^RT kernel. */
 671 +			fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
 672 +			fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
 673 +			break;
 674 +		}
 675 +	}
 676 +
 677 +	return tmp;
 678 +}
 679 +
 680 +
 681 +static void debug_delay_loop(int count)
 682 +{
 683 +	double start, end, delay;
 684 +
 685 +	while (count--) {
 686 +		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
 687 +			start = wctime();
 688 +			loop_for(delay, 0);
 689 +			end = wctime();
 690 +			printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
 691 +			       delay,
 692 +			       end - start,
 693 +			       end - start - delay,
 694 +			       100 * (end - start - delay) / delay);
 695 +		}
 696 +	}
 697 +}
 698 +
 699 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
 700 +{
 701 +	double chunk1, chunk2;
 702 +
 703 +	if (wctime() > program_end)
 704 +		return 0;
 705 +	else {
 706 +		if (lock_od >= 0) {
 707 +			/* simulate critical section somewhere in the middle */
 708 +			chunk1 = drand48() * (exec_time - cs_length);
 709 +			chunk2 = exec_time - cs_length - chunk1;
 710 +
 711 +			/* non-critical section */
 712 +			loop_for(chunk1, program_end + 1);
 713 +
 714 +			/* critical section */
 715 +			litmus_lock(lock_od);
 716 +			loop_for(cs_length, program_end + 1);
 717 +			litmus_unlock(lock_od);
 718 +
 719 +			/* non-critical section */
 720 +			loop_for(chunk2, program_end + 2);
 721 +		} else {
 722 +			loop_for(exec_time, program_end + 1);
 723 +		}
 724 +		sleep_next_period();
 725 +		return 1;
 726 +	}
 727 +}
 728 +
 729 +struct lt_interval* parse_td_intervals(int num, char* optarg, unsigned int *num_intervals)
 730 +{
 731 +	int i, matched;
 732 +	struct lt_interval *slots = malloc(sizeof(slots[0]) * num);
 733 +	char** arg = (char**)malloc(sizeof(char*) * num);
 734 +	char *token, *saveptr;
 735 +	double start, end;
 736 +	
 737 +	for (i = 0; i < num; i++) {
 738 +		arg[i] = (char*)malloc(sizeof(char)*100);
 739 +	}
 740 +	
 741 +	i = 0;
 742 +	token = strtok_r(optarg, ":", &saveptr);
 743 +	while(token != NULL) {
 744 +		sprintf(arg[i++], "%s", token);
 745 +		token = strtok_r(NULL, ":", &saveptr);
 746 +	}
 747 +	
 748 +	*num_intervals = 0;
 749 +	
 750 +	for (i=0; i<num; i++) {
 751 +		matched = sscanf(arg[i], "[%lf,%lf]", &start, &end);
 752 +		if (matched != 2) {
 753 +			fprintf(stderr, "could not parse '%s' as interval\n", arg[i]);
 754 +			exit(5);
 755 +		}
 756 +		if (start < 0) {
 757 +			fprintf(stderr, "interval %s: must not start before zero\n", arg[i]);
 758 +			exit(5);
 759 +		}
 760 +		if (end <= start) {
 761 +			fprintf(stderr, "interval %s: end before start\n", arg[i]);
 762 +			exit(5);
 763 +		}
 764 +
 765 +		slots[i].start = ms2ns(start);
 766 +		slots[i].end   = ms2ns(end);
 767 +
 768 +		if (i > 0 && slots[i - 1].end >= slots[i].start) {
 769 +			fprintf(stderr, "interval %s: overlaps with previous interval\n", arg[i]);
 770 +			exit(5);
 771 +		}
 772 +
 773 +		(*num_intervals)++;
 774 +	}
 775 +	
 776 +	for (i=0; i<num; i++) {
 777 +		free(arg[i]);
 778 +	}
 779 +	free(arg);
 780 +	return slots;
 781 +}
 782 +
 783 +#define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:vh:m:i:b:k:"
 784 +int main(int argc, char** argv)
 785 +{
 786 +	int ret;
 787 +	lt_t wcet;
 788 +	lt_t period;
 789 +	lt_t hyperperiod;
 790 +	lt_t budget;
 791 +	double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
 792 +	unsigned int priority = LITMUS_NO_PRIORITY;
 793 +	int migrate = 0;
 794 +	int cluster = 0;
 795 +	int opt;
 796 +	int wait = 0;
 797 +	int test_loop = 0;
 798 +	int column = 1;
 799 +	const char *file = NULL;
 800 +	int want_enforcement = 0;
 801 +	double duration = 0, start = 0;
 802 +	double *exec_times = NULL;
 803 +	double scale = 1.0;
 804 +	task_class_t class = RT_CLASS_HARD;
 805 +	int cur_job = 0, num_jobs = 0;
 806 +	struct rt_task param;
 807 +	struct mc2_task mc2_param;
 808 +	struct reservation_config config;
 809 +	int res_type = PERIODIC_POLLING;
 810 +	int i;
 811 +	uint32_t mode_mask;
 812 +
 813 +	int verbose = 0;
 814 +	unsigned int job_no;
 815 +
 816 +	/* locking */
 817 +	int lock_od = -1;
 818 +	int resource_id = 0;
 819 +	const char *lock_namespace = "./rtspin-locks";
 820 +	int protocol = -1;
 821 +	double cs_length = 1; /* millisecond */
 822 +
 823 +	progname = argv[0];
 824 +
 825 +	/* default for reservation */
 826 +	config.id = 0;
 827 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
 828 +	config.cpu = -1;
 829 +	
 830 +	mc2_param.crit = CRIT_LEVEL_C;
 831 +	
 832 +	hyperperiod_ms = 1000;
 833 +	budget_ms = 10;
 834 +	
 835 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
 836 +		switch (opt) {
 837 +		case 'w':
 838 +			wait = 1;
 839 +			break;
 840 +		case 'p':
 841 +			cluster = atoi(optarg);
 842 +			migrate = 1;
 843 +			config.cpu = cluster;
 844 +			break;
 845 +		case 'q':
 846 +			priority = atoi(optarg);
 847 +			if (!litmus_is_valid_fixed_prio(priority))
 848 +				usage("Invalid priority.");
 849 +			break;
 850 +		case 'c':
 851 +			class = str2class(optarg);
 852 +			if (class == -1)
 853 +				usage("Unknown task class.");
 854 +			break;
 855 +		case 'e':
 856 +			want_enforcement = 1;
 857 +			break;
 858 +		case 'l':
 859 +			test_loop = 1;
 860 +			break;
 861 +		case 'o':
 862 +			column = atoi(optarg);
 863 +			break;
 864 +		case 'f':
 865 +			file = optarg;
 866 +			break;
 867 +		case 's':
 868 +			scale = atof(optarg);
 869 +			break;
 870 +		case 'X':
 871 +			protocol = lock_protocol_for_name(optarg);
 872 +			if (protocol < 0)
 873 +				usage("Unknown locking protocol specified.");
 874 +			break;
 875 +		case 'L':
 876 +			cs_length = atof(optarg);
 877 +			if (cs_length <= 0)
 878 +				usage("Invalid critical section length.");
 879 +			break;
 880 +		case 'Q':
 881 +			resource_id = atoi(optarg);
 882 +			if (resource_id <= 0 && strcmp(optarg, "0"))
 883 +				usage("Invalid resource ID.");
 884 +			break;
 885 +		case 'v':
 886 +			verbose = 1;
 887 +			break;
 888 +		case 'm':
 889 +			mc2_param.crit = atoi(optarg);
 890 +			if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
 891 +				usage("Invalid criticality level.");
 892 +			}
 893 +			res_type = PERIODIC_POLLING;
 894 +			break;
 895 +		case 'h':
 896 +			hyperperiod_ms = atof(optarg);
 897 +			break;
 898 +		case 'b':
 899 +			budget_ms = atof(optarg);
 900 +			break;
 901 +		case 'i':
 902 +			config.priority = atoi(optarg);
 903 +			break;
 904 +		case 'k':
 905 +			mode_mask = atoi(optarg);
 906 +			break;
 907 +		case ':':
 908 +			usage("Argument missing.");
 909 +			break;
 910 +		case '?':
 911 +		default:
 912 +			usage("Bad argument.");
 913 +			break;
 914 +		}
 915 +	}
 916 +
 917 +	if (test_loop) {
 918 +		debug_delay_loop(1);
 919 +		return 0;
 920 +	}
 921 +
 922 +	if (mc2_param.crit == CRIT_LEVEL_A && config.priority == LITMUS_NO_PRIORITY)
 923 +		usage("Bad criticailty level or priority");
 924 +	if (mc2_param.crit == CRIT_LEVEL_B) {
 925 +		config.priority = LITMUS_NO_PRIORITY;
 926 +	}
 927 +	
 928 +	if (mc2_param.crit == CRIT_LEVEL_C) {
 929 +		config.priority = LITMUS_NO_PRIORITY;
 930 +		config.cpu = -1;
 931 +	}
 932 +
 933 +	srand(getpid());
 934 +
 935 +	if (file) {
 936 +		get_exec_times(file, column, &num_jobs, &exec_times);
 937 +
 938 +		if (argc - optind < 2)
 939 +			usage("Arguments missing.");
 940 +
 941 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
 942 +			/* convert the execution time to seconds */
 943 +			duration += exec_times[cur_job] * 0.001;
 944 +		}
 945 +	} else {
 946 +		/*
 947 +		 * if we're not reading from the CSV file, then we need
 948 +		 * three parameters
 949 +		 */
 950 +		if (argc - optind < 3)
 951 +			usage("Arguments missing.");
 952 +	}
 953 +
 954 +	wcet_ms   = atof(argv[optind + 0]);
 955 +	period_ms = atof(argv[optind + 1]);
 956 +
 957 +	wcet   = ms2ns(wcet_ms);
 958 +	period = ms2ns(period_ms);
 959 +	budget = ms2ns(budget_ms);
 960 +	hyperperiod = ms2ns(hyperperiod_ms);
 961 +	
 962 +	if (wcet <= 0)
 963 +		usage("The worst-case execution time must be a "
 964 +				"positive number.");
 965 +	if (period <= 0)
 966 +		usage("The period must be a positive number.");
 967 +	if (!file && wcet > period) {
 968 +		usage("The worst-case execution time must not "
 969 +				"exceed the period.");
 970 +	}
 971 +
 972 +	if (!file)
 973 +		duration  = atof(argv[optind + 2]);
 974 +	else if (file && num_jobs > 1)
 975 +		duration += period_ms * 0.001 * (num_jobs - 1);
 976 +
 977 +	if (migrate) {
 978 +		ret = be_migrate_to_domain(cluster);
 979 +		if (ret < 0)
 980 +			bail_out("could not migrate to target partition or cluster.");
 981 +	}
 982 +
 983 +	/* reservation config */
 984 +	config.id = gettid();
 985 +	
 986 +	if (hyperperiod%period != 0 ) {
 987 +		;//bail_out("hyperperiod must be multiple of period");
 988 +	}
 989 +	
 990 +	config.polling_params.budget = budget;
 991 +	config.polling_params.period = period;
 992 +	config.polling_params.offset = 0;
 993 +	config.polling_params.relative_deadline = 0;
 994 +	if (config.polling_params.budget > config.polling_params.period) {
 995 +		usage("The budget must not exceed the period.");
 996 +	}
 997 +	/* create a reservation */
 998 +	for(i = 0; i < 32; i++){
 999 +		if ( !( (1 << i) & mode_mask) )
1000 +			continue;
1001 +		config.mode = i;
1002 +		ret = reservation_create(res_type, &config);
1003 +		if (ret < 0) {
1004 +			bail_out("failed to create reservation.");
1005 +		}
1006 +	}
1007 +	
1008 +	init_rt_task_param(&param);
1009 +	param.exec_cost = wcet;
1010 +	param.period = period;
1011 +	param.priority = priority;
1012 +	param.cls = class;
1013 +	param.release_policy = TASK_PERIODIC;
1014 +	param.budget_policy = (want_enforcement) ?
1015 +			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
1016 +	if (migrate) {
1017 +		param.cpu = gettid();
1018 +	}
1019 +	ret = set_rt_task_param(gettid(), &param);
1020 +//printf("SET_RT_TASK\n");
1021 +	if (ret < 0)
1022 +		bail_out("could not setup rt task params");
1023 +	
1024 +	mc2_param.res_id = gettid();
1025 +	mc2_param.mode_mask = mode_mask;
1026 +	ret = set_mc2_task_param(gettid(), &mc2_param);
1027 +//printf("SET_MC2_TASK\n");
1028 +	if (ret < 0)
1029 +		bail_out("could not setup mc2 task params");
1030 +
1031 +	init_litmus();
1032 +
1033 +//printf("INIT_LITMUS\n");
1034 +	start = wctime();
1035 +	ret = task_mode(LITMUS_RT_TASK);
1036 +//printf("TASK_MODE\n");
1037 +	set_page_color(config.cpu);
1038 +	if (ret != 0)
1039 +		bail_out("could not become RT task");
1040 +
1041 +	if (protocol >= 0) {
1042 +		lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
1043 +		if (lock_od < 0) {
1044 +			perror("litmus_open_lock");
1045 +			usage("Could not open lock.");
1046 +		}
1047 +	}
1048 +
1049 +
1050 +	if (wait) {
1051 +//printf("BEFORE WAIT\n");
1052 +		ret = wait_for_ts_release();
1053 +		if (ret != 0)
1054 +			bail_out("wait_for_ts_release()");
1055 +		start = wctime();
1056 +	}
1057 +
1058 +	if (file) {
1059 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
1060 +			job(exec_times[cur_job] * 0.001 * scale,
1061 +			    start + duration,
1062 +			    lock_od, cs_length * 0.001);
1063 +		}
1064 +	} else {
1065 +		do {
1066 +			if (verbose) {
1067 +				get_job_no(&job_no);
1068 +				printf("rtspin/%d:%u @ %.4fms\n", gettid(),
1069 +					job_no, (wctime() - start) * 1000);
1070 +			}
1071 +		} while (job(wcet_ms * 0.001 * scale, start + duration,
1072 +			   lock_od, cs_length * 0.001));
1073 +	}
1074 +	ret = task_mode(BACKGROUND_TASK);
1075 +	if (ret != 0)
1076 +		bail_out("could not become regular task (huh?)");
1077 +
1078 +	if (file)
1079 +		free(exec_times);
1080 +
1081 +	reservation_destroy(gettid(), config.cpu);
1082 +	
1083 +	return 0;
1084 +}
1085 diff --git bin/mode_request.c bin/mode_request.c
1086 new file mode 100644
1087 index 0000000..010add1
1088 --- /dev/null
1089 +++ bin/mode_request.c
1090 @@ -0,0 +1,49 @@
1091 +#include <stdio.h>
1092 +#include <stdlib.h>
1093 +#include <errno.h>
1094 +#include <sys/syscall.h>
1095 +#include <unistd.h>
1096 +#include <signal.h>
1097 +
1098 +#include "litmus.h"
1099 +
1100 +#define __NR_request_mode 408
1101 +
1102 +static int keep_running;
1103 +
1104 +void sig_handler(int signum) {
1105 +	int ret;
1106 +
1107 +	usleep(100000);
1108 +	ret = syscall(__NR_request_mode, 0);
1109 +	usleep(1000000);
1110 +	keep_running = 0;
1111 +	
1112 +}
1113 +
1114 +int main(int argc, char* argv[]) {
1115 +	int ret, req_mode = 0;
1116 +	int interval_ms;
1117 +	int max_mode = 9;
1118 +	
1119 +	signal(SIGINT, sig_handler);
1120 +	
1121 +	if (argc == 2) {
1122 +		max_mode = atoi(argv[1]);
1123 +		printf("%d\n", max_mode);
1124 +	}
1125 +	
1126 +	keep_running = 1;
1127 +	usleep(500000); // ms 
1128 +	while (keep_running) {
1129 +		req_mode = (req_mode%max_mode)+1;
1130 +		
1131 +		if (keep_running)
1132 +			ret = syscall(__NR_request_mode, req_mode);
1133 +		interval_ms = rand() % 1000 - 500;  // ms
1134 +		usleep(1000*(1000 + interval_ms));
1135 +	}
1136 +	
1137 +	
1138 +	return ret;
1139 +} 
1140 diff --git bin/mode_skeleton.c bin/mode_skeleton.c
1141 new file mode 100644
1142 index 0000000..cae5851
1143 --- /dev/null
1144 +++ bin/mode_skeleton.c
1145 @@ -0,0 +1,256 @@
1146 +#include <sys/time.h>
1147 +#include <sys/mman.h>
1148 +
1149 +#include <stdio.h>
1150 +#include <stdlib.h>
1151 +#include <unistd.h>
1152 +#include <time.h>
1153 +#include <string.h>
1154 +#include <assert.h>
1155 +#include <limits.h>
1156 +
1157 +
1158 +#include "litmus.h"
1159 +#include "common.h"
1160 +
1161 +extern int main_job(void);
1162 +
1163 +static char* progname;
1164 +int loops = 10;
1165 +//struct timeval t1, t2;
1166 +
1167 +static void usage(char *error) {
1168 +	fprintf(stderr, "Error: %s\n", error);
1169 +	fprintf(stderr,
1170 +		"Usage:\n"
1171 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
1172 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
1173 +		"	rt_spin -l\n"
1174 +		"\n"
1175 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
1176 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
1177 +		"\n"
1178 +		"WCET and PERIOD are microseconds, DURATION is seconds.\n");
1179 +	exit(EXIT_FAILURE);
1180 +}
1181 +
1182 +inline unsigned long get_cyclecount (void)
1183 +{
1184 +	unsigned long value;
1185 +	// Read CCNT Register
1186 +	asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
1187 +	return value;
1188 +}
1189 +
1190 +static int job(double exec_time, double program_end)
1191 +{
1192 +	if (wctime() > program_end)
1193 +		return 0;
1194 +	else {
1195 +		register int iter = 0;
1196 +		//register unsigned long t;
1197 +		//t = get_cyclecount();
1198 +		//gettimeofday(&t1, NULL);
1199 +		while (iter++ < loops) {
1200 +			main_job();
1201 +		}
1202 +		//t = get_cyclecount() - t;
1203 +		//printf("%ld cycles\n", t);
1204 +		//gettimeofday(&t2, NULL);
1205 +		//printf("%ld us\n", ((t2.tv_sec * 1000000 + t2.tv_usec) - (t1.tv_sec * 1000000 + t1.tv_usec)));
1206 +		sleep_next_period();
1207 +		return 1;
1208 +	}
1209 +}
1210 +
1211 +#define OPTSTR "p:wves:l:m:i:b:k:"
1212 +int main(int argc, char** argv)
1213 +{
1214 +	int ret;
1215 +	lt_t wcet;
1216 +	lt_t period;
1217 +	lt_t budget;
1218 +	double wcet_us, period_us, budget_us;
1219 +	unsigned int priority = LITMUS_NO_PRIORITY;
1220 +	int migrate = 0;
1221 +	int cluster = 0;
1222 +	int opt;
1223 +	int wait = 0;
1224 +	int want_enforcement = 0;
1225 +	double duration = 0, start = 0;
1226 +	double scale = 1.0;
1227 +	task_class_t class = RT_CLASS_HARD;
1228 +	struct rt_task param;
1229 +	struct mc2_task mc2_param;
1230 +	struct reservation_config config;
1231 +	int res_type = PERIODIC_POLLING;
1232 +	uint32_t mode_mask = (1 << 0);
1233 +	int i;
1234 +	unsigned int job_no;
1235 +
1236 +
1237 +	progname = argv[0];
1238 +
1239 +	/* default for reservation */
1240 +	config.id = 0;
1241 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
1242 +	config.cpu = -1;
1243 +	
1244 +	mc2_param.crit = CRIT_LEVEL_C;
1245 +	
1246 +	budget_us = 10000;
1247 +
1248 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1249 +		switch (opt) {
1250 +		case 'w':
1251 +			wait = 1;
1252 +			break;
1253 +		case 'p':
1254 +			cluster = atoi(optarg);
1255 +			migrate = 1;
1256 +			config.cpu = cluster;
1257 +			break;
1258 +		case 'e':
1259 +			want_enforcement = 1;
1260 +			break;
1261 +		case 's':
1262 +			scale = atof(optarg);
1263 +			break;
1264 +		case 'l':
1265 +			loops = atoi(optarg);
1266 +			break;
1267 +		case 'm':
1268 +			mc2_param.crit = atoi(optarg);
1269 +			if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
1270 +				usage("Invalid criticality level.");
1271 +			}
1272 +			res_type = PERIODIC_POLLING;
1273 +			break;
1274 +		case 'b':
1275 +			budget_us = atof(optarg);
1276 +			break;
1277 +		case 'i':
1278 +			config.priority = atoi(optarg);
1279 +			break;
1280 +		case 'k':
1281 +			mode_mask = atoi(optarg);
1282 +		case ':':
1283 +			usage("Argument missing.");
1284 +			break;
1285 +		case '?':
1286 +		default:
1287 +			usage("Bad argument.");
1288 +			break;
1289 +		}
1290 +	}
1291 +
1292 +	if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
1293 +		usage("Bad criticailty level or priority");
1294 +
1295 +	if (argc - optind < 3)
1296 +		usage("Arguments missing.");
1297 +
1298 +	wcet_us   = atof(argv[optind + 0]);
1299 +	period_us = atof(argv[optind + 1]);
1300 +
1301 +	wcet   = us2ns(wcet_us);
1302 +	period = us2ns(period_us);
1303 +	budget = us2ns(budget_us);
1304 +	
1305 +	if (wcet <= 0)
1306 +		usage("The worst-case execution time must be a "
1307 +				"positive number.");
1308 +	if (period <= 0)
1309 +		usage("The period must be a positive number.");
1310 +	if (wcet > period) {
1311 +		usage("The worst-case execution time must not "
1312 +				"exceed the period.");
1313 +	}
1314 +
1315 +	duration  = atof(argv[optind + 2]);
1316 +
1317 +	if (migrate) {
1318 +		ret = be_migrate_to_domain(cluster);
1319 +		if (ret < 0)
1320 +			bail_out("could not migrate to target partition or cluster.");
1321 +	}
1322 +
1323 +	/* reservation config */
1324 +	config.id = gettid();
1325 +	
1326 +	config.polling_params.budget = budget;
1327 +	config.polling_params.period = period;
1328 +	config.polling_params.offset = 0;
1329 +	config.polling_params.relative_deadline = 0;
1330 +	if (config.polling_params.budget > config.polling_params.period) {
1331 +		usage("The budget must not exceed the period.");
1332 +	}
1333 +	
1334 +	/* create reservations */
1335 +	for(i = 0; i < 32; i++){
1336 +		if ( !((1 << i) & mode_mask ) )
1337 +			continue;
1338 +		config.mode = i;
1339 +		ret = reservation_create(res_type, &config);
1340 +		if (ret < 0) {
1341 +			bail_out("failed to create reservation.");
1342 +		}
1343 +	}
1344 +	
1345 +	init_rt_task_param(&param);
1346 +	param.exec_cost = wcet;
1347 +	param.period = period;
1348 +	param.priority = priority;
1349 +	param.cls = class;
1350 +	param.release_policy = TASK_PERIODIC;
1351 +	param.budget_policy = (want_enforcement) ?
1352 +			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
1353 +	if (migrate) {
1354 +		param.cpu = gettid();
1355 +	}
1356 +	ret = set_rt_task_param(gettid(), &param);
1357 +	
1358 +	if (ret < 0)
1359 +		bail_out("could not setup rt task params");
1360 +	
1361 +	mc2_param.res_id = gettid();
1362 +	mc2_param.mode_mask = mode_mask;
1363 +	ret = set_mc2_task_param(gettid(), &mc2_param);
1364 +//printf("SET_MC2_TASK\n");
1365 +	if (ret < 0)
1366 +		bail_out("could not setup mc2 task params");
1367 +
1368 +	init_litmus();
1369 +//printf("CALL\n");
1370 +	if (mc2_param.crit == CRIT_LEVEL_C)
1371 +		set_page_color(8);
1372 +	else if (mc2_param.crit < CRIT_LEVEL_C)
1373 +		set_page_color(config.cpu*2 + mc2_param.crit);
1374 +//printf("CALL\n");
1375 +
1376 +//printf("INIT_LITMUS\n");
1377 +	start = wctime();
1378 +	ret = task_mode(LITMUS_RT_TASK);
1379 +//printf("TASK_MODE\n");
1380 +	if (ret != 0)
1381 +		bail_out("could not become RT task");
1382 +
1383 +
1384 +	if (wait) {
1385 +//printf("BEFORE WAIT\n");
1386 +		ret = wait_for_ts_release();
1387 +		if (ret != 0)
1388 +			bail_out("wait_for_ts_release()");
1389 +		start = wctime();
1390 +	}
1391 +
1392 +	while (job(wcet_us * 0.000001 * scale, start + duration)) {};
1393 +
1394 +	ret = task_mode(BACKGROUND_TASK);
1395 +	if (ret != 0)
1396 +		bail_out("could not become regular task (huh?)");
1397 +
1398 +	reservation_destroy(gettid(), config.cpu);
1399 +	printf("%s/%d finished.\n",progname, gettid());	
1400 +	return 0;
1401 +}
1402 diff --git bin/mtdag.c bin/mtdag.c
1403 new file mode 100644
1404 index 0000000..adf6d8d
1405 --- /dev/null
1406 +++ bin/mtdag.c
1407 @@ -0,0 +1,291 @@
1408 +/* based_mt_task.c -- A basic multi-threaded real-time task skeleton. 
1409 + *
1410 + * This (by itself useless) task demos how to setup a multi-threaded LITMUS^RT
1411 + * real-time task. Familiarity with the single threaded example (base_task.c)
1412 + * is assumed.
1413 + *
1414 + * Currently, liblitmus still lacks automated support for real-time
1415 + * tasks, but internaly it is thread-safe, and thus can be used together
1416 + * with pthreads.
1417 + */
1418 +
1419 +#include <stdio.h>
1420 +#include <stdlib.h>
1421 +#include <string.h>
1422 +#include <limits.h>
1423 +#include <sys/mman.h>
1424 +#include <sys/stat.h>
1425 +#include <fcntl.h>
1426 +#include <unistd.h>
1427 +/* Include gettid() */
1428 +#include <sys/types.h>
1429 +
1430 +/* Include threading support. */
1431 +#include <pthread.h>
1432 +
1433 +/* Include the LITMUS^RT API.*/
1434 +#include "litmus.h"
1435 +#include "color_shm.h"
1436 +#include "asm/cycles.h"
1437 +
1438 +#define PERIOD            100
1439 +#define RELATIVE_DEADLINE 100
1440 +#define EXEC_COST         10
1441 +
1442 +/* Let's create 10 threads in the example, 
1443 + * for a total utilization of 1.
1444 + */
1445 +#define NUM_THREADS      2 
1446 +
1447 +/* The information passed to each thread. Could be anything. */
1448 +struct thread_context {
1449 +	int id;
1450 +	int cpu;
1451 +	int job_no;
1452 +	char* shm1;
1453 +	char* shm2;
1454 +	char* shm3;
1455 +};
1456 +
1457 +/* The real-time thread program. Doesn't have to be the same for
1458 + * all threads. Here, we only have one that will invoke job().
1459 + */
1460 +void* rt_thread(void *tcontext);
1461 +
1462 +/* Declare the periodically invoked job. 
1463 + * Returns 1 -> task should exit.
1464 + *         0 -> task should continue.
1465 + */
1466 +int job(struct thread_context *tcx);
1467 +
1468 +
1469 +/* Catch errors.
1470 + */
1471 +#define CALL( exp ) do { \
1472 +		int ret; \
1473 +		ret = exp; \
1474 +		if (ret != 0) \
1475 +			fprintf(stderr, "%s failed: %m\n", #exp);\
1476 +		else \
1477 +			fprintf(stderr, "%s ok.\n", #exp); \
1478 +	} while (0)
1479 +
1480 +
1481 +/* Basic setup is the same as in the single-threaded example. However, 
1482 + * we do some thread initiliazation first before invoking the job.
1483 + */
1484 +int main(int argc, char** argv)
1485 +{
1486 +	int i;
1487 +	struct thread_context ctx[NUM_THREADS];
1488 +	pthread_t             task[NUM_THREADS];
1489 +	char *shm1;
1490 +	char *shm2;
1491 +	char *shm3;
1492 +	struct color_ioctl_cmd shm_info;
1493 +	struct color_ioctl_offset shm_offset;
1494 +	/* The task is in background mode upon startup. */		
1495 +
1496 +
1497 +	/*****
1498 +	 * 1) Command line paramter parsing would be done here.
1499 +	 */
1500 +
1501 +
1502 +       
1503 +	/*****
1504 +	 * 2) Work environment (e.g., global data structures, file data, etc.) would
1505 +	 *    be setup here.
1506 +	 */
1507 +
1508 +	shm_info.color = 0x00000001;
1509 +	shm_info.bank = 0x00000020;
1510 +	shm_offset.offset = 0;
1511 +	shm_offset.lock = 1;
1512 +	
1513 +	shm1 = (char*)color_mmap(1024, shm_info, shm_offset);
1514 +	if (!shm1) {
1515 +		printf("color mmap failed.\n");
1516 +		exit(-1);
1517 +	}
1518 +	else {
1519 +		printf("Mapped vaddr = %p\n", shm1);
1520 +	}
1521 +
1522 +	shm_info.color = 0x00000003;
1523 +	shm_offset.offset = 1024;
1524 +	shm2 = (char*)color_mmap(4096, shm_info, shm_offset);
1525 +	if (!shm2) {
1526 +                printf("color mmap failed.\n");
1527 +                exit(-1);
1528 +        }
1529 +        else {
1530 +                printf("Mapped vaddr = %p\n", shm2);
1531 +	}
1532 +
1533 +	mlockall(MCL_CURRENT | MCL_FUTURE);
1534 +	/*****
1535 +	 * 3) Initialize LITMUS^RT.
1536 +	 *    Task parameters will be specified per thread.
1537 +	 */
1538 +	init_litmus();
1539 +
1540 +
1541 +	/***** 
1542 +	 * 4) Launch threads.
1543 +	 */
1544 +	for (i = 0; i < NUM_THREADS; i++) {
1545 +		ctx[i].id = i;
1546 +		ctx[i].cpu = 0;
1547 +		ctx[i].job_no = 0;
1548 +		ctx[i].shm1 = shm1;
1549 +		ctx[i].shm3 = shm2;
1550 +		ctx[i].shm2 = shm3;
1551 +		pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i));
1552 +	}
1553 +
1554 +	
1555 +	/*****
1556 +	 * 5) Wait for RT threads to terminate.
1557 +	 */
1558 +	for (i = 0; i < NUM_THREADS; i++)
1559 +		pthread_join(task[i], NULL);
1560 +	
1561 +
1562 +	/***** 
1563 +	 * 6) Clean up, maybe print results and stats, and exit.
1564 +	 */
1565 +	return 0;
1566 +}
1567 +
1568 +
1569 +
1570 +/* A real-time thread is very similar to the main function of a single-threaded
1571 + * real-time app. Notice, that init_rt_thread() is called to initialized per-thread
1572 + * data structures of the LITMUS^RT user space libary.
1573 + */
1574 +void* rt_thread(void *tcontext)
1575 +{
1576 +	int do_exit;
1577 +	struct thread_context *ctx = (struct thread_context *) tcontext;
1578 +	struct rt_task param;
1579 +	int ret;
1580 +	struct mc2_task mc2_param;
1581 +	struct reservation_config res_config;
1582 +
1583 +	/* Set up task parameters */
1584 +	init_rt_task_param(&param);
1585 +	param.exec_cost = ms2ns(EXEC_COST);
1586 +	param.period = ms2ns(PERIOD);
1587 +	param.relative_deadline = ms2ns(RELATIVE_DEADLINE*(ctx->id+1));
1588 +
1589 +	/* What to do in the case of budget overruns? */
1590 +	param.budget_policy = NO_ENFORCEMENT;
1591 +
1592 +	/* The task class parameter is ignored by most plugins. */
1593 +	param.cls = RT_CLASS_SOFT;
1594 +
1595 +	/* The priority parameter is only used by fixed-priority plugins. */
1596 +	param.priority = LITMUS_LOWEST_PRIORITY;
1597 +
1598 +	/* Make presence visible. */
1599 +	printf("RT Thread %d active.\n", ctx->id);
1600 +
1601 +	/* reservation config */
1602 +	res_config.id = gettid();
1603 +	res_config.polling_params.budget = ms2ns(EXEC_COST+1);
1604 +	res_config.polling_params.period = param.period;
1605 +	res_config.polling_params.offset = 0;
1606 +	res_config.polling_params.relative_deadline = 0;
1607 +	res_config.priority = LITMUS_MAX_PRIORITY;
1608 +	res_config.cpu = ctx->cpu;
1609 +	mc2_param.crit = CRIT_LEVEL_A;
1610 +	mc2_param.res_id = gettid();
1611 +	/*****
1612 +	 * 1) Initialize real-time settings.
1613 +	 */
1614 +	CALL( init_rt_thread() );
1615 +
1616 +	ret = reservation_create(PERIODIC_POLLING, &res_config);
1617 +	if (ret < 0) {
1618 +		printf("reservation failed.\n");
1619 +		return NULL;
1620 +	}
1621 +	
1622 +	/* To specify a partition, do
1623 +	 *
1624 +	 * param.cpu = CPU;
1625 +	 * be_migrate_to(CPU);
1626 +	 *
1627 +	 * where CPU ranges from 0 to "Number of CPUs" - 1 before calling
1628 +	 * set_rt_task_param().
1629 +	 */
1630 +	param.cpu = ctx->cpu;
1631 +	ret = be_migrate_to_cpu(ctx->cpu);
1632 +	if (ret < 0) {
1633 +		printf("RT Thread %d fails to migrate to CPU%d\n", ctx->id, ctx->cpu);
1634 +		return NULL;
1635 +	}
1636 +	CALL( set_rt_task_param(gettid(), &param) );
1637 +
1638 +	CALL( set_mc2_task_param(gettid(), &mc2_param) );
1639 +	/*****
1640 +	 * 2) Transition to real-time mode.
1641 +	 */
1642 +	CALL( task_mode(LITMUS_RT_TASK) );
1643 +
1644 +	/* The task is now executing as a real-time task if the call didn't fail. 
1645 +	 */
1646 +
1647 +
1648 +
1649 +	/*****
1650 +	 * 3) Invoke real-time jobs.
1651 +	 */
1652 +	do {
1653 +		/* Wait until the next job is released. */
1654 +		sleep_next_period();
1655 +		/* Invoke job. */
1656 +		do_exit = job(ctx);		
1657 +	} while (!do_exit);
1658 +
1659 +
1660 +	
1661 +	/*****
1662 +	 * 4) Transition to background mode.
1663 +	 */
1664 +	CALL( task_mode(BACKGROUND_TASK) );
1665 +	reservation_destroy(gettid(), res_config.cpu);
1666 +
1667 +	return NULL;
1668 +}
1669 +
1670 +
1671 +
1672 +int job(struct thread_context *tcx) 
1673 +{
1674 +	int i;
1675 +	char* buf1 = tcx->shm1;
1676 +	char* buf2 = tcx->shm2;
1677 +	char* buf3 = tcx->shm3;
1678 +	char tmp = 0;
1679 +	/* Do real-time calculation. */
1680 +	printf("Task %d Job %d executinig\n", tcx->id, tcx->job_no);
1681 +
1682 +	if (tcx->id == 0) {
1683 +		printf("READ\n");
1684 +		for (i=0; i<600; i++) {
1685 +			char t = buf1[i];
1686 +			printf("%x ", t);
1687 +		}
1688 +		printf("\n");
1689 +
1690 +		;
1691 +	}
1692 +	//test_call(0);
1693 +	tcx->job_no++;
1694 +	if (tcx->job_no == 10)
1695 +		return 1;
1696 +	/* Don't exit. */
1697 +	return 0;
1698 +}
1699 diff --git bin/resctrl.c bin/resctrl.c
1700 new file mode 100644
1701 index 0000000..63b5054
1702 --- /dev/null
1703 +++ bin/resctrl.c
1704 @@ -0,0 +1,242 @@
1705 +#include <stdio.h>
1706 +#include <stdlib.h>
1707 +#include <string.h>
1708 +#include <unistd.h>
1709 +#include <limits.h>
1710 +#include <signal.h>
1711 +
1712 +#include <sched.h>
1713 +
1714 +#include "litmus.h"
1715 +#include "common.h"
1716 +
1717 +const char *usage_msg =
1718 +	"Usage: resctrl OPTIONS [INTERVAL-START,INTERVAL-END]*\n"
1719 +	"    -n ID             create new reservation with id ID\n"
1720 +	"    -a PID            attach already-running process PID to reservation\n"
1721 +	"    -r ID             specify which reservation to attach to (not needed with -n)\n"
1722 +	"    -t TYPE           type of reservation (polling-periodic, polling-sporadic, table-driven)\n"
1723 +	"    -c CPU            physical partition or cluster to assign to\n"
1724 +	"    -b BUDGET         polling reservation budget (in ms, default: 10ms)\n"
1725 +	"    -p PERIOD         polling reservation period (in ms, default: 100ms)\n"
1726 +	"    -d DEADLINE       relative deadline, implicit by default (in ms)\n"
1727 +	"    -o OFFSET         offset (also known as phase), zero by default (in ms)\n"
1728 +	"    -q PRIORITY       priority to use (EDF by default, highest priority = 1)\n"
1729 +	"    -m MAJOR-CYCLE    major cycle length (in ms, for table-driven reservations) \n"
1730 +	"\n";
1731 +
1732 +void usage(char *error) {
1733 +	fprintf(stderr, "%s\n%s", error, usage_msg);
1734 +	exit(1);
1735 +}
1736 +
1737 +
1738 +static void attach_task(int attach_pid, struct reservation_config *config)
1739 +{
1740 +	int ret;
1741 +	struct rt_task param;
1742 +	struct sched_param linux_param;
1743 +
1744 +	ret = be_migrate_thread_to_cpu(attach_pid, config->cpu);
1745 +	if (ret < 0) {
1746 +		fprintf(stderr, "failed to migrate task %d to CPU %d\n",
1747 +			attach_pid, config->cpu);
1748 +		exit(4);
1749 +	}
1750 +
1751 +	init_rt_task_param(&param);
1752 +	/* dummy values */
1753 +	param.exec_cost = ms2ns(100);
1754 +	param.period    = ms2ns(100);
1755 +	/* specify reservation as "virtual" CPU */
1756 +	param.cpu       = config->id;
1757 +
1758 +	ret = set_rt_task_param(attach_pid, &param);
1759 +	if (ret < 0) {
1760 +		fprintf(stderr, "failed to set RT task parameters for task %d (%m)\n",
1761 +			attach_pid);
1762 +		exit(2);
1763 +	}
1764 +
1765 +	linux_param.sched_priority = 0;
1766 +	ret = sched_setscheduler(attach_pid, SCHED_LITMUS, &linux_param);
1767 +	if (ret < 0) {
1768 +		fprintf(stderr, "failed to transition task %d to LITMUS^RT class (%m)\n",
1769 +			attach_pid);
1770 +		exit(3);
1771 +	}
1772 +}
1773 +
1774 +static struct lt_interval* parse_td_intervals(int argc, char** argv,
1775 +	unsigned int *num_intervals, lt_t major_cycle)
1776 +{
1777 +	int i, matched;
1778 +	struct lt_interval *slots = malloc(sizeof(slots[0]) * argc);
1779 +	double start, end;
1780 +
1781 +	*num_intervals = 0;
1782 +	for (i = 0; i < argc; i++) {
1783 +		matched = sscanf(argv[i], "[%lf,%lf]", &start, &end);
1784 +		if (matched != 2) {
1785 +			fprintf(stderr, "could not parse '%s' as interval\n", argv[i]);
1786 +			exit(5);
1787 +		}
1788 +		if (start < 0) {
1789 +			fprintf(stderr, "interval %s: must not start before zero\n", argv[i]);
1790 +			exit(5);
1791 +		}
1792 +		if (end <= start) {
1793 +			fprintf(stderr, "interval %s: end before start\n", argv[i]);
1794 +			exit(5);
1795 +		}
1796 +
1797 +		slots[i].start = ms2ns(start);
1798 +		slots[i].end   = ms2ns(end);
1799 +
1800 +		if (i > 0 && slots[i - 1].end >= slots[i].start) {
1801 +			fprintf(stderr, "interval %s: overlaps with previous interval\n", argv[i]);
1802 +			exit(5);
1803 +		}
1804 +
1805 +		if (slots[i].end >= major_cycle) {
1806 +			fprintf(stderr, "interval %s: exceeds major cycle length\n", argv[i]);
1807 +			exit(5);
1808 +		}
1809 +
1810 +		(*num_intervals)++;
1811 +	}
1812 +
1813 +	return slots;
1814 +}
1815 +
1816 +#define OPTSTR "n:a:r:t:c:b:p:d:o:q:m:h"
1817 +
1818 +int main(int argc, char** argv)
1819 +{
1820 +	int ret, opt;
1821 +	double budget_ms, period_ms, offset_ms, deadline_ms, major_cycle_ms;
1822 +	int create_new = 0;
1823 +	int attach_pid = 0;
1824 +	int res_type = SPORADIC_POLLING;
1825 +
1826 +	struct reservation_config config;
1827 +
1828 +	/* Reasonable defaults */
1829 +	offset_ms      =    0;
1830 +	deadline_ms    =    0;
1831 +	budget_ms      =   10;
1832 +	period_ms      =  100;
1833 +	major_cycle_ms = 1000;
1834 +
1835 +	config.id = 0;
1836 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
1837 +	config.cpu = 0;
1838 +
1839 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1840 +		switch (opt) {
1841 +		case 'b':
1842 +			budget_ms = atof(optarg);
1843 +			break;
1844 +		case 'p':
1845 +			period_ms = atof(optarg);
1846 +			break;
1847 +		case 'd':
1848 +			deadline_ms = atof(optarg);
1849 +			if (deadline_ms <= 0) {
1850 +				usage("The relative deadline must be a positive"
1851 +					" number.");
1852 +			}
1853 +			break;
1854 +		case 'o':
1855 +			offset_ms = atof(optarg);
1856 +			break;
1857 +		case 'm':
1858 +			major_cycle_ms = atof(optarg);
1859 +			break;
1860 +
1861 +		case 'q':
1862 +			config.priority = atoi(optarg);
1863 +			if (!config.priority)
1864 +				usage("-q: invalid priority");
1865 +			break;
1866 +		case 'c':
1867 +			config.cpu = atoi(optarg);
1868 +			break;
1869 +
1870 +		case 'n':
1871 +			create_new = 1;
1872 +			config.id  = atoi(optarg);
1873 +			break;
1874 +		case 'a':
1875 +			attach_pid = atoi(optarg);
1876 +			if (!attach_pid)
1877 +				usage("-a: invalid PID");
1878 +			break;
1879 +
1880 +		case 'r':
1881 +			config.id  = atoi(optarg);
1882 +			break;
1883 +
1884 +		case 't':
1885 +			if (strcmp(optarg, "polling-periodic") == 0) {
1886 +				res_type = PERIODIC_POLLING;
1887 +			} else if (strcmp(optarg, "polling-sporadic") == 0) {
1888 +				res_type = SPORADIC_POLLING;
1889 +			}  else if (strcmp(optarg, "table-driven") == 0) {
1890 +				res_type = TABLE_DRIVEN;
1891 +				/* Default for table-driven reservations to
1892 +				 * maximum priority. EDF has not meaning for
1893 +				 * table-driven reservations. */
1894 +				if (config.priority == LITMUS_NO_PRIORITY)
1895 +					config.priority = LITMUS_HIGHEST_PRIORITY;
1896 +			} else {
1897 +				usage("Unknown reservation type.");
1898 +			}
1899 +			break;
1900 +
1901 +		case 'h':
1902 +			usage("");
1903 +			break;
1904 +		case ':':
1905 +			usage("Argument missing.");
1906 +			break;
1907 +		case '?':
1908 +		default:
1909 +			usage("Bad argument.");
1910 +			break;
1911 +		}
1912 +	}
1913 +
1914 +	if (res_type != TABLE_DRIVEN) {
1915 +		config.polling_params.budget = ms2ns(budget_ms);
1916 +		config.polling_params.period = ms2ns(period_ms);
1917 +		config.polling_params.offset = ms2ns(offset_ms);
1918 +		config.polling_params.relative_deadline = ms2ns(deadline_ms);
1919 +		if (config.polling_params.budget > config.polling_params.period) {
1920 +			usage("The budget must not exceed the period.");
1921 +		}
1922 +	} else {
1923 +		config.table_driven_params.major_cycle_length = ms2ns(major_cycle_ms);
1924 +		argc -= optind;
1925 +		argv += optind;
1926 +		config.table_driven_params.intervals = parse_td_intervals(
1927 +			argc, argv, &config.table_driven_params.num_intervals,
1928 +			config.table_driven_params.major_cycle_length);
1929 +		if (!config.table_driven_params.num_intervals)
1930 +			usage("Table-driven reservations require at least one interval to be specified.");
1931 +	}
1932 +
1933 +	if (create_new) {
1934 +		ret = reservation_create(res_type, &config);
1935 +		if (ret < 0) {
1936 +			fprintf(stderr, "failed to create reservation %u (%m)\n",
1937 +				config.id);
1938 +			exit(1);
1939 +		}
1940 +	}
1941 +
1942 +	if (attach_pid)
1943 +		attach_task(attach_pid, &config);
1944 +
1945 +	return 0;
1946 +}
1947 diff --git bin/rt_compress.c bin/rt_compress.c
1948 new file mode 100644
1949 index 0000000..9647854
1950 --- /dev/null
1951 +++ bin/rt_compress.c
1952 @@ -0,0 +1,283 @@
1953 +#include <sys/time.h>
1954 +#include <sys/mman.h>
1955 +
1956 +#include <stdio.h>
1957 +#include <stdlib.h>
1958 +#include <unistd.h>
1959 +#include <time.h>
1960 +#include <string.h>
1961 +#include <assert.h>
1962 +#include <limits.h>
1963 +
1964 +
1965 +#include "litmus.h"
1966 +#include "common.h"
1967 +
1968 +extern int main_job(void);
1969 +static char* progname;
1970 +
1971 +static void usage(char *error) {
1972 +	fprintf(stderr, "Error: %s\n", error);
1973 +	fprintf(stderr,
1974 +		"Usage:\n"
1975 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
1976 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
1977 +		"	rt_spin -l\n"
1978 +		"\n"
1979 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
1980 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
1981 +		"              [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
1982 +		"\n"
1983 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n"
1984 +		"CRITICAL SECTION LENGTH is in milliseconds.\n");
1985 +	exit(EXIT_FAILURE);
1986 +}
1987 +
1988 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
1989 +{
1990 +	if (wctime() > program_end)
1991 +		return 0;
1992 +	else {
1993 +		main_job();
1994 +		sleep_next_period();
1995 +		return 1;
1996 +	}
1997 +}
1998 +
1999 +#define OPTSTR "p:c:wves:q:X:L:Q:vh:m:i:b:"
2000 +int main(int argc, char** argv)
2001 +{
2002 +	int ret;
2003 +	lt_t wcet;
2004 +	lt_t period;
2005 +	lt_t hyperperiod;
2006 +	lt_t budget;
2007 +	double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
2008 +	unsigned int priority = LITMUS_NO_PRIORITY;
2009 +	int migrate = 0;
2010 +	int cluster = 0;
2011 +	int opt;
2012 +	int wait = 0;
2013 +	int want_enforcement = 0;
2014 +	double duration = 0, start = 0;
2015 +	double scale = 1.0;
2016 +	task_class_t class = RT_CLASS_HARD;
2017 +	struct rt_task param;
2018 +	struct mc2_task mc2_param;
2019 +	struct reservation_config config;
2020 +	int res_type = PERIODIC_POLLING;
2021 +
2022 +	int verbose = 0;
2023 +	unsigned int job_no;
2024 +
2025 +	/* locking */
2026 +	int lock_od = -1;
2027 +	int resource_id = 0;
2028 +	const char *lock_namespace = "./rtspin-locks";
2029 +	int protocol = -1;
2030 +	double cs_length = 1; /* millisecond */
2031 +
2032 +	progname = argv[0];
2033 +
2034 +	/* default for reservation */
2035 +	config.id = 0;
2036 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
2037 +	config.cpu = -1;
2038 +	
2039 +	mc2_param.crit = CRIT_LEVEL_C;
2040 +	
2041 +	hyperperiod_ms = 1000;
2042 +	budget_ms = 10;
2043 +	
2044 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
2045 +		switch (opt) {
2046 +		case 'w':
2047 +			wait = 1;
2048 +			break;
2049 +		case 'p':
2050 +			cluster = atoi(optarg);
2051 +			migrate = 1;
2052 +			config.cpu = cluster;
2053 +			break;
2054 +		case 'q':
2055 +			priority = atoi(optarg);
2056 +			if (!litmus_is_valid_fixed_prio(priority))
2057 +				usage("Invalid priority.");
2058 +			break;
2059 +		case 'c':
2060 +			class = str2class(optarg);
2061 +			if (class == -1)
2062 +				usage("Unknown task class.");
2063 +			break;
2064 +		case 'e':
2065 +			want_enforcement = 1;
2066 +			break;
2067 +		case 's':
2068 +			scale = atof(optarg);
2069 +			break;
2070 +		case 'X':
2071 +			protocol = lock_protocol_for_name(optarg);
2072 +			if (protocol < 0)
2073 +				usage("Unknown locking protocol specified.");
2074 +			break;
2075 +		case 'L':
2076 +			cs_length = atof(optarg);
2077 +			if (cs_length <= 0)
2078 +				usage("Invalid critical section length.");
2079 +			break;
2080 +		case 'Q':
2081 +			resource_id = atoi(optarg);
2082 +			if (resource_id <= 0 && strcmp(optarg, "0"))
2083 +				usage("Invalid resource ID.");
2084 +			break;
2085 +		case 'v':
2086 +			verbose = 1;
2087 +			break;
2088 +		case 'm':
2089 +			mc2_param.crit = atoi(optarg);
2090 +			if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
2091 +				usage("Invalid criticality level.");
2092 +			}
2093 +			res_type = PERIODIC_POLLING;
2094 +			break;
2095 +		case 'h':
2096 +			hyperperiod_ms = atof(optarg);
2097 +			break;
2098 +		case 'b':
2099 +			budget_ms = atof(optarg);
2100 +			break;
2101 +		case 'i':
2102 +			config.priority = atoi(optarg);
2103 +			break;
2104 +		case ':':
2105 +			usage("Argument missing.");
2106 +			break;
2107 +		case '?':
2108 +		default:
2109 +			usage("Bad argument.");
2110 +			break;
2111 +		}
2112 +	}
2113 +
2114 +	if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
2115 +		usage("Bad criticailty level or priority");
2116 +
2117 +	if (argc - optind < 3)
2118 +		usage("Arguments missing.");
2119 +
2120 +	wcet_ms   = atof(argv[optind + 0]);
2121 +	period_ms = atof(argv[optind + 1]);
2122 +
2123 +	wcet   = ms2ns(wcet_ms);
2124 +	period = ms2ns(period_ms);
2125 +	budget = ms2ns(budget_ms);
2126 +	hyperperiod = ms2ns(hyperperiod_ms);
2127 +	
2128 +	if (wcet <= 0)
2129 +		usage("The worst-case execution time must be a "
2130 +				"positive number.");
2131 +	if (period <= 0)
2132 +		usage("The period must be a positive number.");
2133 +	if (wcet > period) {
2134 +		usage("The worst-case execution time must not "
2135 +				"exceed the period.");
2136 +	}
2137 +
2138 +	duration  = atof(argv[optind + 2]);
2139 +
2140 +	if (migrate) {
2141 +		ret = be_migrate_to_domain(cluster);
2142 +		if (ret < 0)
2143 +			bail_out("could not migrate to target partition or cluster.");
2144 +	}
2145 +
2146 +	/* reservation config */
2147 +	config.id = gettid();
2148 +	
2149 +	if (hyperperiod%period != 0 ) {
2150 +		;//bail_out("hyperperiod must be multiple of period");
2151 +	}
2152 +	
2153 +	config.polling_params.budget = budget;
2154 +	config.polling_params.period = period;
2155 +	config.polling_params.offset = 0;
2156 +	config.polling_params.relative_deadline = 0;
2157 +	if (config.polling_params.budget > config.polling_params.period) {
2158 +		usage("The budget must not exceed the period.");
2159 +	}
2160 +	
2161 +	/* create a reservation */
2162 +	ret = reservation_create(res_type, &config);
2163 +	if (ret < 0) {
2164 +		bail_out("failed to create reservation.");
2165 +	}
2166 +	
2167 +	init_rt_task_param(&param);
2168 +	param.exec_cost = wcet;
2169 +	param.period = period;
2170 +	param.priority = priority;
2171 +	param.cls = class;
2172 +	param.release_policy = TASK_PERIODIC;
2173 +	param.budget_policy = (want_enforcement) ?
2174 +			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
2175 +	if (migrate) {
2176 +		param.cpu = gettid();
2177 +	}
2178 +	ret = set_rt_task_param(gettid(), &param);
2179 +	
2180 +	if (ret < 0)
2181 +		bail_out("could not setup rt task params");
2182 +	
2183 +	mc2_param.res_id = gettid();
2184 +	ret = set_mc2_task_param(gettid(), &mc2_param);
2185 +//printf("SET_MC2_TASK\n");
2186 +	if (ret < 0)
2187 +		bail_out("could not setup mc2 task params");
2188 +
2189 +	init_litmus();
2190 +//printf("CALL\n");
2191 +	//set_page_color(config.cpu);
2192 +//printf("CALL\n");
2193 +
2194 +//printf("INIT_LITMUS\n");
2195 +	start = wctime();
2196 +	ret = task_mode(LITMUS_RT_TASK);
2197 +//printf("TASK_MODE\n");
2198 +	if (ret != 0)
2199 +		bail_out("could not become RT task");
2200 +
2201 +	if (protocol >= 0) {
2202 +		lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
2203 +		if (lock_od < 0) {
2204 +			perror("litmus_open_lock");
2205 +			usage("Could not open lock.");
2206 +		}
2207 +	}
2208 +
2209 +
2210 +	if (wait) {
2211 +//printf("BEFORE WAIT\n");
2212 +		ret = wait_for_ts_release();
2213 +		if (ret != 0)
2214 +			bail_out("wait_for_ts_release()");
2215 +		start = wctime();
2216 +	}
2217 +
2218 +	do {
2219 +		if (verbose) {
2220 +			get_job_no(&job_no);
2221 +			printf("rtspin/%d:%u @ %.4fms\n", gettid(),
2222 +				job_no, (wctime() - start) * 1000);
2223 +		}
2224 +	} while (job(wcet_ms * 0.001 * scale, start + duration,
2225 +		   lock_od, cs_length * 0.001));
2226 +
2227 +printf("BEFORE BACK_TASK\n");
2228 +	ret = task_mode(BACKGROUND_TASK);
2229 +	if (ret != 0)
2230 +		bail_out("could not become regular task (huh?)");
2231 +
2232 +	reservation_destroy(gettid(), config.cpu);
2233 +	
2234 +	return 0;
2235 +}
2236 diff --git bin/rt_mode_poll.c bin/rt_mode_poll.c
2237 new file mode 100644
2238 index 0000000..d05521c
2239 --- /dev/null
2240 +++ bin/rt_mode_poll.c
2241 @@ -0,0 +1,221 @@
2242 +#include <sys/time.h>
2243 +#include <sys/mman.h>
2244 +
2245 +#include <stdio.h>
2246 +#include <stdlib.h>
2247 +#include <unistd.h>
2248 +#include <time.h>
2249 +#include <string.h>
2250 +#include <assert.h>
2251 +#include <limits.h>
2252 +
2253 +
2254 +#include "litmus.h"
2255 +#include "common.h"
2256 +
2257 +#define __NR_request_mode 408
2258 +#define __NR_enact_mode 409
2259 +
2260 +int main_job(void){
2261 +	return syscall(__NR_enact_mode);
2262 +}
2263 +
2264 +static char* progname;
2265 +
2266 +static void usage(char *error) {
2267 +	fprintf(stderr, "Error: %s\n", error);
2268 +	fprintf(stderr,
2269 +		"Usage:\n"
2270 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
2271 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
2272 +		"	rt_spin -l\n"
2273 +		"\n"
2274 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
2275 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
2276 +		"\n"
2277 +		"WCET and PERIOD are microseconds, DURATION is seconds.\n");
2278 +	exit(EXIT_FAILURE);
2279 +}
2280 +
2281 +static int job(double program_end)
2282 +{
2283 +	if (wctime() > program_end)
2284 +		return 0;
2285 +	else {
2286 +		main_job();
2287 +		sleep_next_period();
2288 +		return 1;
2289 +	}
2290 +}
2291 +
2292 +#define OPTSTR "p:wvel:b:k:"
2293 +int main(int argc, char** argv)
2294 +{
2295 +	int ret;
2296 +	lt_t wcet;
2297 +	lt_t period;
2298 +	lt_t budget;
2299 +	double wcet_ms, period_ms, budget_ms;
2300 +	unsigned int priority = 0; //guarantee highest priority to this task
2301 +	int migrate = 0;
2302 +	int cluster = 0;
2303 +	int opt;
2304 +	int wait = 0;
2305 +	int want_enforcement = 0;
2306 +	task_class_t class = RT_CLASS_HARD;
2307 +	struct rt_task param;
2308 +	struct mc2_task mc2_param;
2309 +	struct reservation_config config;
2310 +	int res_type = PERIODIC_POLLING;
2311 +	uint32_t mode_mask = (1 << 0);
2312 +	int i;
2313 +	double duration = 0, start = 0;
2314 +	struct control_page* ctl_page = NULL;
2315 +
2316 +	progname = argv[0];
2317 +
2318 +	/* default for reservation */
2319 +	config.id = 0;
2320 +	config.priority = 1;
2321 +	config.cpu = -1;
2322 +	
2323 +	mc2_param.crit = CRIT_LEVEL_A;
2324 +	
2325 +	budget_ms = 10;
2326 +
2327 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
2328 +		switch (opt) {
2329 +		case 'w':
2330 +			wait = 1;
2331 +			break;
2332 +		case 'p':
2333 +			cluster = atoi(optarg);
2334 +			migrate = 1;
2335 +			config.cpu = cluster;
2336 +			break;
2337 +		case 'e':
2338 +			want_enforcement = 1;
2339 +			break;
2340 +		case 'b':
2341 +			budget_ms = atof(optarg);
2342 +			break;
2343 +		case 'k':
2344 +			mode_mask = atoi(optarg);
2345 +			break;
2346 +		case ':':
2347 +			usage("Argument missing.");
2348 +			break;
2349 +		case '?':
2350 +		default:
2351 +			usage("Bad argument.");
2352 +			break;
2353 +		}
2354 +	}
2355 +
2356 +	if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
2357 +		usage("Bad criticailty level or priority");
2358 +
2359 +	if (argc - optind < 2)
2360 +		usage("Arguments missing.");
2361 +
2362 +	wcet_ms   = atof(argv[optind + 0]);
2363 +	period_ms = atof(argv[optind + 1]);
2364 +
2365 +	wcet   = ms2ns(wcet_ms);
2366 +	period = ms2ns(period_ms);
2367 +	budget = ms2ns(budget_ms);
2368 +	
2369 +	if (wcet <= 0)
2370 +		usage("The worst-case execution time must be a "
2371 +				"positive number.");
2372 +	if (period <= 0)
2373 +		usage("The period must be a positive number.");
2374 +	if (wcet > period) {
2375 +		usage("The worst-case execution time must not "
2376 +				"exceed the period.");
2377 +	}
2378 +
2379 +	duration  = atof(argv[optind + 2]);
2380 +	
2381 +	if (migrate) {
2382 +		ret = be_migrate_to_domain(cluster);
2383 +		if (ret < 0)
2384 +			bail_out("could not migrate to target partition or cluster.");
2385 +	}
2386 +	else{
2387 +		bail_out("rt_mode_poll must be migrated.");
2388 +	}
2389 +
2390 +	/* reservation config */
2391 +	config.id = gettid();
2392 +	
2393 +	config.polling_params.budget = budget;
2394 +	config.polling_params.period = period;
2395 +	config.polling_params.offset = 0;
2396 +	config.polling_params.relative_deadline = 0;
2397 +	if (config.polling_params.budget > config.polling_params.period) {
2398 +		usage("The budget must not exceed the period.");
2399 +	}
2400 +
2401 +	/* create reservation's */
2402 +	for( i = 0; i < 32; i++){
2403 +		if ( !( (1 << i) & mode_mask ) )
2404 +			continue;
2405 +		config.mode = i;
2406 +		ret = reservation_create(res_type, &config);
2407 +		if (ret < 0) {
2408 +			bail_out("failed to create reservation.");
2409 +		}
2410 +	}
2411 +	
2412 +	init_rt_task_param(&param);
2413 +	param.exec_cost = wcet;
2414 +	param.period = period;
2415 +	param.priority = priority;
2416 +	param.cls = class;
2417 +	param.release_policy = TASK_PERIODIC;
2418 +	param.budget_policy = (want_enforcement) ?
2419 +			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
2420 +	if (migrate) {
2421 +		param.cpu = gettid();
2422 +	}
2423 +	ret = set_rt_task_param(gettid(), &param);
2424 +	
2425 +	if (ret < 0)
2426 +		bail_out("could not setup rt task params");
2427 +	
2428 +	mc2_param.res_id = gettid();
2429 +	mc2_param.mode_mask = mode_mask;
2430 +	ret = set_mc2_task_param(gettid(), &mc2_param);
2431 +	if (ret < 0)
2432 +		bail_out("could not setup mc2 task params");
2433 +
2434 +	init_litmus();
2435 +	ctl_page = get_ctrl_page();
2436 +	if (!ctl_page)
2437 +		bail_out("could not get ctrl_page");
2438 +	ctl_page->mode_poll_task = 1;
2439 +	
2440 +	start = wctime();
2441 +	ret = task_mode(LITMUS_RT_TASK);
2442 +	if (ret != 0)
2443 +		bail_out("could not become RT task");
2444 +
2445 +	set_page_color(config.cpu);
2446 +
2447 +	if (wait) {
2448 +		ret = wait_for_ts_release();
2449 +		if (ret != 0)
2450 +			bail_out("wait_for_ts_release()");
2451 +		start = wctime();
2452 +	}
2453 +
2454 +	while (job(start + duration)) {};
2455 +
2456 +	ret = task_mode(BACKGROUND_TASK);
2457 +	if (ret != 0)
2458 +		bail_out("could not become regular task (huh?)");
2459 +
2460 +	reservation_destroy(gettid(), config.cpu);
2461 +	return 0;
2462 +}
2463 diff --git bin/rt_skeleton.c bin/rt_skeleton.c
2464 new file mode 100644
2465 index 0000000..16e189a
2466 --- /dev/null
2467 +++ bin/rt_skeleton.c
2468 @@ -0,0 +1,247 @@
2469 +#include <sys/time.h>
2470 +#include <sys/mman.h>
2471 +
2472 +#include <stdio.h>
2473 +#include <stdlib.h>
2474 +#include <unistd.h>
2475 +#include <time.h>
2476 +#include <string.h>
2477 +#include <assert.h>
2478 +#include <limits.h>
2479 +
2480 +
2481 +#include "litmus.h"
2482 +#include "common.h"
2483 +
2484 +extern int main_job(void);
2485 +
2486 +static char* progname;
2487 +int loops = 10;
2488 +//struct timeval t1, t2;
2489 +
2490 +static void usage(char *error) {
2491 +	fprintf(stderr, "Error: %s\n", error);
2492 +	fprintf(stderr,
2493 +		"Usage:\n"
2494 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
2495 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
2496 +		"	rt_spin -l\n"
2497 +		"\n"
2498 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
2499 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
2500 +		"\n"
2501 +		"WCET and PERIOD are microseconds, DURATION is seconds.\n");
2502 +	exit(EXIT_FAILURE);
2503 +}
2504 +
2505 +inline unsigned long get_cyclecount (void)
2506 +{
2507 +	unsigned long value;
2508 +	// Read CCNT Register
2509 +	asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
2510 +	return value;
2511 +}
2512 +
2513 +static int job(double exec_time, double program_end)
2514 +{
2515 +	if (wctime() > program_end)
2516 +		return 0;
2517 +	else {
2518 +		register int iter = 0;
2519 +		//register unsigned long t;
2520 +		//t = get_cyclecount();
2521 +		//gettimeofday(&t1, NULL);
2522 +		while (iter++ < loops) {
2523 +			main_job();
2524 +		}
2525 +		//t = get_cyclecount() - t;
2526 +		//printf("%ld cycles\n", t);
2527 +		//gettimeofday(&t2, NULL);
2528 +		//printf("%ld us\n", ((t2.tv_sec * 1000000 + t2.tv_usec) - (t1.tv_sec * 1000000 + t1.tv_usec)));
2529 +		sleep_next_period();
2530 +		return 1;
2531 +	}
2532 +}
2533 +
2534 +#define OPTSTR "p:wves:l:m:i:b:"
2535 +int main(int argc, char** argv)
2536 +{
2537 +	int ret;
2538 +	lt_t wcet;
2539 +	lt_t period;
2540 +	lt_t budget;
2541 +	double wcet_us, period_us, budget_us;
2542 +	unsigned int priority = LITMUS_NO_PRIORITY;
2543 +	int migrate = 0;
2544 +	int cluster = 0;
2545 +	int opt;
2546 +	int wait = 0;
2547 +	int want_enforcement = 0;
2548 +	double duration = 0, start = 0;
2549 +	double scale = 1.0;
2550 +	task_class_t class = RT_CLASS_HARD;
2551 +	struct rt_task param;
2552 +	struct mc2_task mc2_param;
2553 +	struct reservation_config config;
2554 +	int res_type = PERIODIC_POLLING;
2555 +
2556 +	unsigned int job_no;
2557 +
2558 +
2559 +	progname = argv[0];
2560 +
2561 +	/* default for reservation */
2562 +	config.id = 0;
2563 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
2564 +	config.cpu = -1;
2565 +	
2566 +	mc2_param.crit = CRIT_LEVEL_C;
2567 +	
2568 +	budget_us = 10000;
2569 +
2570 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
2571 +		switch (opt) {
2572 +		case 'w':
2573 +			wait = 1;
2574 +			break;
2575 +		case 'p':
2576 +			cluster = atoi(optarg);
2577 +			migrate = 1;
2578 +			config.cpu = cluster;
2579 +			break;
2580 +		case 'e':
2581 +			want_enforcement = 1;
2582 +			break;
2583 +		case 's':
2584 +			scale = atof(optarg);
2585 +			break;
2586 +		case 'l':
2587 +			loops = atoi(optarg);
2588 +			break;
2589 +		case 'm':
2590 +			mc2_param.crit = atoi(optarg);
2591 +			if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
2592 +				usage("Invalid criticality level.");
2593 +			}
2594 +			res_type = PERIODIC_POLLING;
2595 +			break;
2596 +		case 'b':
2597 +			budget_us = atof(optarg);
2598 +			break;
2599 +		case 'i':
2600 +			config.priority = atoi(optarg);
2601 +			break;
2602 +		case ':':
2603 +			usage("Argument missing.");
2604 +			break;
2605 +		case '?':
2606 +		default:
2607 +			usage("Bad argument.");
2608 +			break;
2609 +		}
2610 +	}
2611 +
2612 +	if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
2613 +		usage("Bad criticailty level or priority");
2614 +
2615 +	if (argc - optind < 3)
2616 +		usage("Arguments missing.");
2617 +
2618 +	wcet_us   = atof(argv[optind + 0]);
2619 +	period_us = atof(argv[optind + 1]);
2620 +
2621 +	wcet   = us2ns(wcet_us);
2622 +	period = us2ns(period_us);
2623 +	budget = us2ns(budget_us);
2624 +	
2625 +	if (wcet <= 0)
2626 +		usage("The worst-case execution time must be a "
2627 +				"positive number.");
2628 +	if (period <= 0)
2629 +		usage("The period must be a positive number.");
2630 +	if (wcet > period) {
2631 +		usage("The worst-case execution time must not "
2632 +				"exceed the period.");
2633 +	}
2634 +
2635 +	duration  = atof(argv[optind + 2]);
2636 +
2637 +	if (migrate) {
2638 +		ret = be_migrate_to_domain(cluster);
2639 +		if (ret < 0)
2640 +			bail_out("could not migrate to target partition or cluster.");
2641 +	}
2642 +
2643 +	/* reservation config */
2644 +	config.id = gettid();
2645 +	
2646 +	config.polling_params.budget = budget;
2647 +	config.polling_params.period = period;
2648 +	config.polling_params.offset = 0;
2649 +	config.polling_params.relative_deadline = 0;
2650 +	if (config.polling_params.budget > config.polling_params.period) {
2651 +		usage("The budget must not exceed the period.");
2652 +	}
2653 +	
2654 +	/* create a reservation */
2655 +	ret = reservation_create(res_type, &config);
2656 +	if (ret < 0) {
2657 +		bail_out("failed to create reservation.");
2658 +	}
2659 +	
2660 +	init_rt_task_param(&param);
2661 +	param.exec_cost = wcet;
2662 +	param.period = period;
2663 +	param.priority = priority;
2664 +	param.cls = class;
2665 +	param.release_policy = TASK_PERIODIC;
2666 +	param.budget_policy = (want_enforcement) ?
2667 +			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
2668 +	if (migrate) {
2669 +		param.cpu = gettid();
2670 +	}
2671 +	ret = set_rt_task_param(gettid(), &param);
2672 +	
2673 +	if (ret < 0)
2674 +		bail_out("could not setup rt task params");
2675 +	
2676 +	mc2_param.res_id = gettid();
2677 +	ret = set_mc2_task_param(gettid(), &mc2_param);
2678 +//printf("SET_MC2_TASK\n");
2679 +	if (ret < 0)
2680 +		bail_out("could not setup mc2 task params");
2681 +
2682 +	init_litmus();
2683 +//printf("CALL\n");
2684 +	if (mc2_param.crit == CRIT_LEVEL_C)
2685 +		set_page_color(8);
2686 +	else if (mc2_param.crit < CRIT_LEVEL_C)
2687 +		set_page_color(config.cpu*2 + mc2_param.crit);
2688 +//printf("CALL\n");
2689 +
2690 +//printf("INIT_LITMUS\n");
2691 +	start = wctime();
2692 +	ret = task_mode(LITMUS_RT_TASK);
2693 +//printf("TASK_MODE\n");
2694 +	if (ret != 0)
2695 +		bail_out("could not become RT task");
2696 +
2697 +
2698 +	if (wait) {
2699 +//printf("BEFORE WAIT\n");
2700 +		ret = wait_for_ts_release();
2701 +		if (ret != 0)
2702 +			bail_out("wait_for_ts_release()");
2703 +		start = wctime();
2704 +	}
2705 +
2706 +	while (job(wcet_us * 0.000001 * scale, start + duration)) {};
2707 +
2708 +	ret = task_mode(BACKGROUND_TASK);
2709 +	if (ret != 0)
2710 +		bail_out("could not become regular task (huh?)");
2711 +
2712 +	reservation_destroy(gettid(), config.cpu);
2713 +	printf("%s/%d finished.\n",progname, gettid());	
2714 +	return 0;
2715 +}
2716 diff --git bin/rt_skeleton_ms.c bin/rt_skeleton_ms.c
2717 new file mode 100644
2718 index 0000000..d545635
2719 --- /dev/null
2720 +++ bin/rt_skeleton_ms.c
2721 @@ -0,0 +1,282 @@
2722 +#include <sys/time.h>
2723 +#include <sys/mman.h>
2724 +
2725 +#include <stdio.h>
2726 +#include <stdlib.h>
2727 +#include <unistd.h>
2728 +#include <time.h>
2729 +#include <string.h>
2730 +#include <assert.h>
2731 +#include <limits.h>
2732 +
2733 +
2734 +#include "litmus.h"
2735 +#include "common.h"
2736 +
2737 +extern int main_job(void);
2738 +static char* progname;
2739 +
2740 +static void usage(char *error) {
2741 +	fprintf(stderr, "Error: %s\n", error);
2742 +	fprintf(stderr,
2743 +		"Usage:\n"
2744 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
2745 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
2746 +		"	rt_spin -l\n"
2747 +		"\n"
2748 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
2749 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
2750 +		"              [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
2751 +		"\n"
2752 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n"
2753 +		"CRITICAL SECTION LENGTH is in milliseconds.\n");
2754 +	exit(EXIT_FAILURE);
2755 +}
2756 +
2757 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
2758 +{
2759 +	if (wctime() > program_end)
2760 +		return 0;
2761 +	else {
2762 +		main_job();
2763 +		sleep_next_period();
2764 +		return 1;
2765 +	}
2766 +}
2767 +
2768 +#define OPTSTR "p:c:wves:q:X:L:Q:vh:m:i:b:"
2769 +int main(int argc, char** argv)
2770 +{
2771 +	int ret;
2772 +	lt_t wcet;
2773 +	lt_t period;
2774 +	lt_t hyperperiod;
2775 +	lt_t budget;
2776 +	double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
2777 +	unsigned int priority = LITMUS_NO_PRIORITY;
2778 +	int migrate = 0;
2779 +	int cluster = 0;
2780 +	int opt;
2781 +	int wait = 0;
2782 +	int want_enforcement = 0;
2783 +	double duration = 0, start = 0;
2784 +	double scale = 1.0;
2785 +	task_class_t class = RT_CLASS_HARD;
2786 +	struct rt_task param;
2787 +	struct mc2_task mc2_param;
2788 +	struct reservation_config config;
2789 +	int res_type = PERIODIC_POLLING;
2790 +
2791 +	int verbose = 0;
2792 +	unsigned int job_no;
2793 +
2794 +	/* locking */
2795 +	int lock_od = -1;
2796 +	int resource_id = 0;
2797 +	const char *lock_namespace = "./rtspin-locks";
2798 +	int protocol = -1;
2799 +	double cs_length = 1; /* millisecond */
2800 +
2801 +	progname = argv[0];
2802 +
2803 +	/* default for reservation */
2804 +	config.id = 0;
2805 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
2806 +	config.cpu = -1;
2807 +	
2808 +	mc2_param.crit = CRIT_LEVEL_C;
2809 +	
2810 +	hyperperiod_ms = 1000;
2811 +	budget_ms = 10;
2812 +
2813 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
2814 +		switch (opt) {
2815 +		case 'w':
2816 +			wait = 1;
2817 +			break;
2818 +		case 'p':
2819 +			cluster = atoi(optarg);
2820 +			migrate = 1;
2821 +			config.cpu = cluster;
2822 +			break;
2823 +		case 'q':
2824 +			priority = atoi(optarg);
2825 +			if (!litmus_is_valid_fixed_prio(priority))
2826 +				usage("Invalid priority.");
2827 +			break;
2828 +		case 'c':
2829 +			class = str2class(optarg);
2830 +			if (class == -1)
2831 +				usage("Unknown task class.");
2832 +			break;
2833 +		case 'e':
2834 +			want_enforcement = 1;
2835 +			break;
2836 +		case 's':
2837 +			scale = atof(optarg);
2838 +			break;
2839 +		case 'X':
2840 +			protocol = lock_protocol_for_name(optarg);
2841 +			if (protocol < 0)
2842 +				usage("Unknown locking protocol specified.");
2843 +			break;
2844 +		case 'L':
2845 +			cs_length = atof(optarg);
2846 +			if (cs_length <= 0)
2847 +				usage("Invalid critical section length.");
2848 +			break;
2849 +		case 'Q':
2850 +			resource_id = atoi(optarg);
2851 +			if (resource_id <= 0 && strcmp(optarg, "0"))
2852 +				usage("Invalid resource ID.");
2853 +			break;
2854 +		case 'v':
2855 +			verbose = 1;
2856 +			break;
2857 +		case 'm':
2858 +			mc2_param.crit = atoi(optarg);
2859 +			if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
2860 +				usage("Invalid criticality level.");
2861 +			}
2862 +			res_type = PERIODIC_POLLING;
2863 +			break;
2864 +		case 'h':
2865 +			hyperperiod_ms = atof(optarg);
2866 +			break;
2867 +		case 'b':
2868 +			budget_ms = atof(optarg);
2869 +			break;
2870 +		case 'i':
2871 +			config.priority = atoi(optarg);
2872 +			break;
2873 +		case ':':
2874 +			usage("Argument missing.");
2875 +			break;
2876 +		case '?':
2877 +		default:
2878 +			usage("Bad argument.");
2879 +			break;
2880 +		}
2881 +	}
2882 +
2883 +	if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
2884 +		usage("Bad criticailty level or priority");
2885 +
2886 +	if (argc - optind < 3)
2887 +		usage("Arguments missing.");
2888 +
2889 +	wcet_ms   = atof(argv[optind + 0]);
2890 +	period_ms = atof(argv[optind + 1]);
2891 +
2892 +	wcet   = ms2ns(wcet_ms);
2893 +	period = ms2ns(period_ms);
2894 +	budget = ms2ns(budget_ms);
2895 +	hyperperiod = ms2ns(hyperperiod_ms);
2896 +	
2897 +	if (wcet <= 0)
2898 +		usage("The worst-case execution time must be a "
2899 +				"positive number.");
2900 +	if (period <= 0)
2901 +		usage("The period must be a positive number.");
2902 +	if (wcet > period) {
2903 +		usage("The worst-case execution time must not "
2904 +				"exceed the period.");
2905 +	}
2906 +
2907 +	duration  = atof(argv[optind + 2]);
2908 +
2909 +	if (migrate) {
2910 +		ret = be_migrate_to_domain(cluster);
2911 +		if (ret < 0)
2912 +			bail_out("could not migrate to target partition or cluster.");
2913 +	}
2914 +
2915 +	/* reservation config */
2916 +	config.id = gettid();
2917 +	
2918 +	if (hyperperiod%period != 0 ) {
2919 +		;//bail_out("hyperperiod must be multiple of period");
2920 +	}
2921 +	
2922 +	config.polling_params.budget = budget;
2923 +	config.polling_params.period = period;
2924 +	config.polling_params.offset = 0;
2925 +	config.polling_params.relative_deadline = 0;
2926 +	if (config.polling_params.budget > config.polling_params.period) {
2927 +		usage("The budget must not exceed the period.");
2928 +	}
2929 +	
2930 +	/* create a reservation */
2931 +	ret = reservation_create(res_type, &config);
2932 +	if (ret < 0) {
2933 +		bail_out("failed to create reservation.");
2934 +	}
2935 +	
2936 +	init_rt_task_param(&param);
2937 +	param.exec_cost = wcet;
2938 +	param.period = period;
2939 +	param.priority = priority;
2940 +	param.cls = class;
2941 +	param.release_policy = TASK_PERIODIC;
2942 +	param.budget_policy = (want_enforcement) ?
2943 +			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
2944 +	if (migrate) {
2945 +		param.cpu = gettid();
2946 +	}
2947 +	ret = set_rt_task_param(gettid(), &param);
2948 +	
2949 +	if (ret < 0)
2950 +		bail_out("could not setup rt task params");
2951 +	
2952 +	mc2_param.res_id = gettid();
2953 +	ret = set_mc2_task_param(gettid(), &mc2_param);
2954 +//printf("SET_MC2_TASK\n");
2955 +	if (ret < 0)
2956 +		bail_out("could not setup mc2 task params");
2957 +
2958 +	init_litmus();
2959 +//printf("CALL\n");
2960 +	set_page_color(config.cpu);
2961 +//printf("CALL\n");
2962 +
2963 +//printf("INIT_LITMUS\n");
2964 +	start = wctime();
2965 +	ret = task_mode(LITMUS_RT_TASK);
2966 +//printf("TASK_MODE\n");
2967 +	if (ret != 0)
2968 +		bail_out("could not become RT task");
2969 +
2970 +	if (protocol >= 0) {
2971 +		lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
2972 +		if (lock_od < 0) {
2973 +			perror("litmus_open_lock");
2974 +			usage("Could not open lock.");
2975 +		}
2976 +	}
2977 +
2978 +
2979 +	if (wait) {
2980 +//printf("BEFORE WAIT\n");
2981 +		ret = wait_for_ts_release();
2982 +		if (ret != 0)
2983 +			bail_out("wait_for_ts_release()");
2984 +		start = wctime();
2985 +	}
2986 +
2987 +	do {
2988 +		if (verbose) {
2989 +			get_job_no(&job_no);
2990 +			printf("rtspin/%d:%u @ %.4fms\n", gettid(),
2991 +				job_no, (wctime() - start) * 1000);
2992 +		}
2993 +	} while (job(wcet_ms * 0.001 * scale, start + duration,
2994 +		   lock_od, cs_length * 0.001));
2995 +
2996 +	ret = task_mode(BACKGROUND_TASK);
2997 +	if (ret != 0)
2998 +		bail_out("could not become regular task (huh?)");
2999 +
3000 +	reservation_destroy(gettid(), config.cpu);
3001 +printf("%s/%d finished.\n",progname, gettid());	
3002 +	return 0;
3003 +}
3004 diff --git bin/rt_skeleton_us.c bin/rt_skeleton_us.c
3005 new file mode 100644
3006 index 0000000..ecf3ed8
3007 --- /dev/null
3008 +++ bin/rt_skeleton_us.c
3009 @@ -0,0 +1,282 @@
3010 +#include <sys/time.h>
3011 +#include <sys/mman.h>
3012 +
3013 +#include <stdio.h>
3014 +#include <stdlib.h>
3015 +#include <unistd.h>
3016 +#include <time.h>
3017 +#include <string.h>
3018 +#include <assert.h>
3019 +#include <limits.h>
3020 +
3021 +
3022 +#include "litmus.h"
3023 +#include "common.h"
3024 +
3025 +extern int main_job(void);
3026 +static char* progname;
3027 +
3028 +static void usage(char *error) {
3029 +	fprintf(stderr, "Error: %s\n", error);
3030 +	fprintf(stderr,
3031 +		"Usage:\n"
3032 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
3033 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
3034 +		"	rt_spin -l\n"
3035 +		"\n"
3036 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
3037 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
3038 +		"              [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
3039 +		"\n"
3040 +		"WCET and PERIOD are microseconds, DURATION is seconds.\n"
3041 +		"CRITICAL SECTION LENGTH is in microseconds.\n");
3042 +	exit(EXIT_FAILURE);