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);
3043 +}
3044 +
3045 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
3046 +{
3047 +	if (wctime() > program_end)
3048 +		return 0;
3049 +	else {
3050 +		main_job();
3051 +		sleep_next_period();
3052 +		return 1;
3053 +	}
3054 +}
3055 +
3056 +#define OPTSTR "p:c:wves:q:X:L:Q:vh:m:i:b:"
3057 +int main(int argc, char** argv)
3058 +{
3059 +	int ret;
3060 +	lt_t wcet;
3061 +	lt_t period;
3062 +	lt_t hyperperiod;
3063 +	lt_t budget;
3064 +	double wcet_us, period_us, hyperperiod_us, budget_us;
3065 +	unsigned int priority = LITMUS_NO_PRIORITY;
3066 +	int migrate = 0;
3067 +	int cluster = 0;
3068 +	int opt;
3069 +	int wait = 0;
3070 +	int want_enforcement = 0;
3071 +	double duration = 0, start = 0;
3072 +	double scale = 1.0;
3073 +	task_class_t class = RT_CLASS_HARD;
3074 +	struct rt_task param;
3075 +	struct mc2_task mc2_param;
3076 +	struct reservation_config config;
3077 +	int res_type = PERIODIC_POLLING;
3078 +
3079 +	int verbose = 0;
3080 +	unsigned int job_no;
3081 +
3082 +	/* locking */
3083 +	int lock_od = -1;
3084 +	int resource_id = 0;
3085 +	const char *lock_namespace = "./rtspin-locks";
3086 +	int protocol = -1;
3087 +	double cs_length = 1; /* millisecond */
3088 +
3089 +	progname = argv[0];
3090 +
3091 +	/* default for reservation */
3092 +	config.id = 0;
3093 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
3094 +	config.cpu = -1;
3095 +	
3096 +	mc2_param.crit = CRIT_LEVEL_C;
3097 +	
3098 +	hyperperiod_us = 1000000;
3099 +	budget_us = 10000;
3100 +
3101 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
3102 +		switch (opt) {
3103 +		case 'w':
3104 +			wait = 1;
3105 +			break;
3106 +		case 'p':
3107 +			cluster = atoi(optarg);
3108 +			migrate = 1;
3109 +			config.cpu = cluster;
3110 +			break;
3111 +		case 'q':
3112 +			priority = atoi(optarg);
3113 +			if (!litmus_is_valid_fixed_prio(priority))
3114 +				usage("Invalid priority.");
3115 +			break;
3116 +		case 'c':
3117 +			class = str2class(optarg);
3118 +			if (class == -1)
3119 +				usage("Unknown task class.");
3120 +			break;
3121 +		case 'e':
3122 +			want_enforcement = 1;
3123 +			break;
3124 +		case 's':
3125 +			scale = atof(optarg);
3126 +			break;
3127 +		case 'X':
3128 +			protocol = lock_protocol_for_name(optarg);
3129 +			if (protocol < 0)
3130 +				usage("Unknown locking protocol specified.");
3131 +			break;
3132 +		case 'L':
3133 +			cs_length = atof(optarg);
3134 +			if (cs_length <= 0)
3135 +				usage("Invalid critical section length.");
3136 +			break;
3137 +		case 'Q':
3138 +			resource_id = atoi(optarg);
3139 +			if (resource_id <= 0 && strcmp(optarg, "0"))
3140 +				usage("Invalid resource ID.");
3141 +			break;
3142 +		case 'v':
3143 +			verbose = 1;
3144 +			break;
3145 +		case 'm':
3146 +			mc2_param.crit = atoi(optarg);
3147 +			if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
3148 +				usage("Invalid criticality level.");
3149 +			}
3150 +			res_type = PERIODIC_POLLING;
3151 +			break;
3152 +		case 'h':
3153 +			hyperperiod_us = atof(optarg);
3154 +			break;
3155 +		case 'b':
3156 +			budget_us = atof(optarg);
3157 +			break;
3158 +		case 'i':
3159 +			config.priority = atoi(optarg);
3160 +			break;
3161 +		case ':':
3162 +			usage("Argument missing.");
3163 +			break;
3164 +		case '?':
3165 +		default:
3166 +			usage("Bad argument.");
3167 +			break;
3168 +		}
3169 +	}
3170 +
3171 +	if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
3172 +		usage("Bad criticailty level or priority");
3173 +
3174 +	if (argc - optind < 3)
3175 +		usage("Arguments missing.");
3176 +
3177 +	wcet_us   = atof(argv[optind + 0]);
3178 +	period_us = atof(argv[optind + 1]);
3179 +
3180 +	wcet   = us2ns(wcet_us);
3181 +	period = us2ns(period_us);
3182 +	budget = us2ns(budget_us);
3183 +	hyperperiod = us2ns(hyperperiod_us);
3184 +	
3185 +	if (wcet <= 0)
3186 +		usage("The worst-case execution time must be a "
3187 +				"positive number.");
3188 +	if (period <= 0)
3189 +		usage("The period must be a positive number.");
3190 +	if (wcet > period) {
3191 +		usage("The worst-case execution time must not "
3192 +				"exceed the period.");
3193 +	}
3194 +
3195 +	duration  = atof(argv[optind + 2]);
3196 +
3197 +	if (migrate) {
3198 +		ret = be_migrate_to_domain(cluster);
3199 +		if (ret < 0)
3200 +			bail_out("could not migrate to target partition or cluster.");
3201 +	}
3202 +
3203 +	/* reservation config */
3204 +	config.id = gettid();
3205 +	
3206 +	if (hyperperiod%period != 0 ) {
3207 +		;//bail_out("hyperperiod must be multiple of period");
3208 +	}
3209 +	
3210 +	config.polling_params.budget = budget;
3211 +	config.polling_params.period = period;
3212 +	config.polling_params.offset = 0;
3213 +	config.polling_params.relative_deadline = 0;
3214 +	if (config.polling_params.budget > config.polling_params.period) {
3215 +		usage("The budget must not exceed the period.");
3216 +	}
3217 +	
3218 +	/* create a reservation */
3219 +	ret = reservation_create(res_type, &config);
3220 +	if (ret < 0) {
3221 +		bail_out("failed to create reservation.");
3222 +	}
3223 +	
3224 +	init_rt_task_param(&param);
3225 +	param.exec_cost = wcet;
3226 +	param.period = period;
3227 +	param.priority = priority;
3228 +	param.cls = class;
3229 +	param.release_policy = TASK_PERIODIC;
3230 +	param.budget_policy = (want_enforcement) ?
3231 +			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
3232 +	if (migrate) {
3233 +		param.cpu = gettid();
3234 +	}
3235 +	ret = set_rt_task_param(gettid(), &param);
3236 +	
3237 +	if (ret < 0)
3238 +		bail_out("could not setup rt task params");
3239 +	
3240 +	mc2_param.res_id = gettid();
3241 +	ret = set_mc2_task_param(gettid(), &mc2_param);
3242 +//printf("SET_MC2_TASK\n");
3243 +	if (ret < 0)
3244 +		bail_out("could not setup mc2 task params");
3245 +
3246 +	init_litmus();
3247 +//printf("CALL\n");
3248 +	set_page_color(config.cpu);
3249 +//printf("CALL\n");
3250 +
3251 +//printf("INIT_LITMUS\n");
3252 +	start = wctime();
3253 +	ret = task_mode(LITMUS_RT_TASK);
3254 +//printf("TASK_MODE\n");
3255 +	if (ret != 0)
3256 +		bail_out("could not become RT task");
3257 +
3258 +	if (protocol >= 0) {
3259 +		lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
3260 +		if (lock_od < 0) {
3261 +			perror("litmus_open_lock");
3262 +			usage("Could not open lock.");
3263 +		}
3264 +	}
3265 +
3266 +
3267 +	if (wait) {
3268 +//printf("BEFORE WAIT\n");
3269 +		ret = wait_for_ts_release();
3270 +		if (ret != 0)
3271 +			bail_out("wait_for_ts_release()");
3272 +		start = wctime();
3273 +	}
3274 +
3275 +	do {
3276 +		if (verbose) {
3277 +			get_job_no(&job_no);
3278 +			printf("rtspin/%d:%u @ %.4fms\n", gettid(),
3279 +				job_no, (wctime() - start) * 1000);
3280 +		}
3281 +	} while (job(wcet_us * 0.000001 * scale, start + duration,
3282 +		   lock_od, cs_length * 0.000001));
3283 +
3284 +	ret = task_mode(BACKGROUND_TASK);
3285 +	if (ret != 0)
3286 +		bail_out("could not become regular task (huh?)");
3287 +
3288 +	reservation_destroy(gettid(), config.cpu);
3289 +printf("%s/%d finished.\n",progname, gettid());	
3290 +	return 0;
3291 +}
3292 diff --git bin/rtspin.c bin/rtspin.c
3293 index ea7f192..fd57c45 100644
3294 --- bin/rtspin.c
3295 +++ bin/rtspin.c
3296 @@ -6,7 +6,7 @@
3297  #include <time.h>
3298  #include <string.h>
3299  #include <assert.h>
3300 -
3301 +#include <limits.h>
3302  
3303  #include "litmus.h"
3304  #include "common.h"
3305 @@ -191,7 +191,7 @@ int main(int argc, char** argv)
3306  	lt_t wcet;
3307  	lt_t period;
3308  	double wcet_ms, period_ms;
3309 -	unsigned int priority = LITMUS_LOWEST_PRIORITY;
3310 +	unsigned int priority = LITMUS_NO_PRIORITY;
3311  	int migrate = 0;
3312  	int cluster = 0;
3313  	int reservation = -1;
3314 diff --git include/cache_common.h include/cache_common.h
3315 new file mode 100644
3316 index 0000000..2957dd3
3317 --- /dev/null
3318 +++ include/cache_common.h
3319 @@ -0,0 +1,213 @@
3320 +#ifndef __CACHE_COMMON_H__
3321 +#define __CACHE_COMMON_H__
3322 +
3323 +#include <stdio.h>
3324 +#include <stdlib.h>
3325 +#include <time.h>
3326 +#include <string.h>
3327 +#include <assert.h>
3328 +
3329 +#include <signal.h>
3330 +#include <sys/mman.h>
3331 +#include <sys/types.h>
3332 +#include <sys/stat.h>
3333 +#include <fcntl.h>
3334 +#include <unistd.h>
3335 +
3336 +#include <sys/io.h>
3337 +#include <sys/utsname.h>
3338 +
3339 +#include <sched.h>
3340 +#include <sys/time.h>
3341 +#include <sys/resource.h>
3342 +
3343 +#include "litmus.h"
3344 +#include "asm/cycles.h"
3345 +
3346 +#if defined(__i386__) || defined(__x86_64__)
3347 +#include "asm/irq.h"
3348 +#endif
3349 +
3350 +
3351 +#define UNCACHE_DEV "/dev/litmus/uncache"
3352 +
3353 +static void die(char *error)
3354 +{
3355 +    fprintf(stderr, "Error: %s (errno: %m)\n",
3356 +        error);
3357 +    exit(1);
3358 +}
3359 +
3360 +static int migrate_to(int cpu)
3361 +{
3362 +    int ret;
3363 +
3364 +    static __thread cpu_set_t* cpu_set = NULL;
3365 +    static __thread size_t cpu_set_sz;
3366 +    static __thread int num_cpus;
3367 +    if(!cpu_set)
3368 +    {
3369 +        num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
3370 +        cpu_set = CPU_ALLOC(num_cpus);
3371 +        cpu_set_sz = CPU_ALLOC_SIZE(num_cpus);
3372 +    }
3373 +
3374 +    CPU_ZERO_S(cpu_set_sz, cpu_set);
3375 +    CPU_SET_S(cpu, cpu_set_sz, cpu_set);
3376 +    ret = sched_setaffinity(0 /* self */, cpu_set_sz, cpu_set);
3377 +    return ret;
3378 +}
3379 +
3380 +static int check_migrations(int num_cpus)
3381 +{
3382 +    int cpu, err;
3383 +
3384 +    for (cpu = 0; cpu < num_cpus; cpu++) {
3385 +        err = migrate_to(cpu);
3386 +        if (err != 0) {
3387 +            fprintf(stderr, "Migration to CPU %d failed: %m.\n",
3388 +                cpu + 1);
3389 +            return 1;
3390 +        }
3391 +    }
3392 +    return 0;
3393 +}
3394 +
3395 +static int become_posix_realtime_task(int prio)
3396 +{
3397 +    struct sched_param param;
3398 +    memset(&param, 0, sizeof(param));
3399 +    param.sched_priority = prio;
3400 +    return sched_setscheduler(0 /* self */, SCHED_FIFO, &param);
3401 +}
3402 +
3403 +static int renice(int nice_val)
3404 +{
3405 +        return setpriority(PRIO_PROCESS, 0 /* self */, nice_val);
3406 +}
3407 +
3408 +static int lock_memory(void)
3409 +{
3410 +    return mlockall(MCL_CURRENT | MCL_FUTURE);
3411 +}
3412 +
3413 +/* define CACHELINE_SIZE if not provided by compiler args */
3414 +#ifndef CACHELINE_SIZE
3415 +#if defined(__i386__) || defined(__x86_64__)
3416 +/* recent intel cpus */
3417 +#define CACHELINE_SIZE 64
3418 +#elif defined(__arm__)
3419 +/* at least with Cortex-A9 cpus ("8 words") */
3420 +#define CACHELINE_SIZE 32
3421 +#else
3422 +#error "Could not determine cacheline size!"
3423 +#endif
3424 +#endif
3425 +
3426 +//#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
3427 +//typedef struct cacheline
3428 +//{
3429 +//        int line[INTS_IN_CACHELINE];
3430 +//} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
3431 +
3432 +static cacheline_t* alloc_arena(size_t size, int use_huge_pages, int use_uncache_pages)
3433 +{
3434 +    int flags = MAP_PRIVATE | MAP_POPULATE;
3435 +    cacheline_t* arena = NULL;
3436 +    int fd;
3437 +
3438 +    if(use_huge_pages)
3439 +        flags |= MAP_HUGETLB;
3440 +
3441 +	if(use_uncache_pages) {
3442 +			fd = open(UNCACHE_DEV, O_RDWR);
3443 +			if (fd == -1)
3444 +					die("Failed to open uncache device. Are you running the LITMUS^RT kernel?");
3445 +	}
3446 +	else {
3447 +			fd = -1;
3448 +			flags |= MAP_ANONYMOUS;
3449 +	}
3450 +
3451 +    arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0);
3452 +	
3453 +    if(use_uncache_pages)
3454 +		close(fd);
3455 +
3456 +    assert(arena);
3457 +
3458 +        return arena;
3459 +}
3460 +
3461 +static void dealloc_arena(cacheline_t* arena, size_t size)
3462 +{
3463 +		int ret = munmap((void*)arena, size);
3464 +        if(ret != 0)
3465 +                die("munmap() error");
3466 +}
3467 +
3468 +static int randrange(int min, int max)
3469 +{
3470 +        /* generate a random number on the range [min, max) w/o skew */
3471 +        int limit = max - min;
3472 +        int devisor = RAND_MAX/limit;
3473 +        int retval;
3474 +
3475 +        do {
3476 +                retval = rand() / devisor;
3477 +        } while(retval == limit);
3478 +        retval += min;
3479 +
3480 +        return retval;
3481 +}
3482 +
3483 +static void init_arena(cacheline_t* arena, size_t size)
3484 +{
3485 +    int i;
3486 +        size_t num_arena_elem = size / sizeof(cacheline_t);
3487 +
3488 +        /* Generate a cycle among the cache lines using Sattolo's algorithm.
3489 +           Every int in the cache line points to the same cache line.
3490 +           Note: Sequential walk doesn't care about these values. */
3491 +        for (i = 0; i < num_arena_elem; i++) {
3492 +                int j;
3493 +                for(j = 0; j < INTS_IN_CACHELINE; ++j)
3494 +                        arena[i].line[j] = i;
3495 +        }
3496 +        while(1 < i--) {
3497 +                int j = randrange(0, i);
3498 +                cacheline_t temp = arena[j];
3499 +                arena[j] = arena[i];
3500 +                arena[i] = temp;
3501 +        }
3502 +}
3503 +
3504 +static void sleep_us(int microseconds)
3505 +{
3506 +    struct timespec delay;
3507 +
3508 +    delay.tv_sec = 0;
3509 +    delay.tv_nsec = microseconds * 1000;
3510 +    if (nanosleep(&delay, NULL) != 0)
3511 +        die("sleep failed");
3512 +}
3513 +
3514 +static int completed(int nSamples, int* history, int nCategories)
3515 +{
3516 +        int i;
3517 +        for(i = 0; i < nCategories; ++i)
3518 +                if(history[i] < nSamples)
3519 +                        return 0;
3520 +        return 1;
3521 +}
3522 +
3523 +inline unsigned long get_cyclecount (void)
3524 +{
3525 +	unsigned long value;
3526 +	// Read CCNT Register
3527 +	asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
3528 +	return value;
3529 +}
3530 +
3531 +
3532 +#endif
3533 diff --git include/color_shm.h include/color_shm.h
3534 new file mode 100644
3535 index 0000000..449ec9d
3536 --- /dev/null
3537 +++ include/color_shm.h
3538 @@ -0,0 +1,20 @@
3539 +#include <sys/types.h>
3540 +#include <sys/ioctl.h>
3541 +#include <fcntl.h>
3542 +
3543 +#define SHM_MAJOR		(240)
3544 +
3545 +struct color_ioctl_cmd {
3546 +	unsigned int color;
3547 +	unsigned int bank;
3548 +};
3549 +
3550 +struct color_ioctl_offset {
3551 +	unsigned long offset;
3552 +	int lock;
3553 +};
3554 +
3555 +#define SET_COLOR_SHM_CMD		_IOW(SHM_MAJOR, 0x1, struct color_ioctl_cmd)
3556 +#define SET_COLOR_SHM_OFFSET	_IOW(SHM_MAJOR, 0x2, struct color_ioctl_offset)
3557 +
3558 +void* color_mmap(size_t size, struct color_ioctl_cmd cmd, struct color_ioctl_offset offset);
3559 diff --git include/litmus.h include/litmus.h
3560 index b9dbdb5..b70917e 100644
3561 --- include/litmus.h
3562 +++ include/litmus.h
3563 @@ -40,12 +40,22 @@ extern "C" {
3564  
3565  #include "migration.h"
3566  
3567 +#include "litmus/mc2_common.h"
3568 +
3569  /**
3570   * @private
3571   * The numeric ID of the LITMUS^RT scheduling class.
3572   */
3573  #define SCHED_LITMUS 7
3574  
3575 +#define CACHELINE_SIZE 32
3576 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
3577 +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
3578 +typedef struct cacheline
3579 +{
3580 +        int line[INTS_IN_CACHELINE];
3581 +} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
3582 +
3583  /**
3584   * Initialise a real-time task param struct
3585   * @param param Pointer to the struct to initialise
3586 @@ -146,6 +156,12 @@ int sporadic_clustered(lt_t e_ns, lt_t p_ns, int cluster);
3587  /** Convert microseconds to nanoseconds
3588    * @param us Time units in microseconds */
3589  #define us2ns(us) ((us)*1000LL)
3590 +#define ns2s(ns)  ((ns)/1000000000LL)
3591 +#define ns2ms(ns) ((ns)/1000000LL)
3592 +#define ns2us(ns) ((ns)/1000LL)
3593 +#define us2ms(us) ((us)/1000LL)
3594 +#define us2s(us)  ((us)/1000000LL)
3595 +#define ms2s(ms)  ((ms)/1000LL)
3596  
3597  /**
3598   * Locking protocols for allocated shared objects
3599 @@ -286,6 +302,12 @@ void exit_np(void);
3600   */
3601  int  requested_to_preempt(void);
3602  
3603 +/* pgm support */
3604 +void enter_pgm_wait(void);
3605 +void exit_pgm_wait(void);
3606 +void enter_pgm_send(void);
3607 +void exit_pgm_send(void);
3608 +
3609  /***** Task System support *****/
3610  /**
3611   * Wait until task master releases all real-time tasks
3612 @@ -416,6 +438,20 @@ int null_call(cycles_t *timestamp);
3613   */
3614  struct control_page* get_ctrl_page(void);
3615  
3616 +int reservation_create(int rtype, void *config);
3617 +
3618 +int reservation_destroy(unsigned int reservation_id, int cpu);
3619 +
3620 +int set_mc2_task_param(pid_t pid, struct mc2_task* param);
3621 +
3622 +int set_page_color(int cpu);
3623 +
3624 +int test_call(unsigned int param);
3625 +
3626 +int run_bench(int type, int size, cacheline_t *src, cacheline_t *dst, lt_t __user *ts);
3627 +
3628 +int lock_buffer(void* vaddr, size_t size, unsigned int lock_way, unsigned int unlock_way);
3629 +
3630  #ifdef __cplusplus
3631  }
3632  #endif
3633 diff --git src/color_shm.c src/color_shm.c
3634 new file mode 100644
3635 index 0000000..15332aa
3636 --- /dev/null
3637 +++ src/color_shm.c
3638 @@ -0,0 +1,42 @@
3639 +#include <sys/mman.h>
3640 +#include <stdio.h>
3641 +#include <unistd.h>
3642 +
3643 +#include "color_shm.h"
3644 +
3645 +void* color_mmap(size_t size, struct color_ioctl_cmd cmd, struct color_ioctl_offset offset)
3646 +{
3647 +	int ret, fd;
3648 +	void *mem;
3649 +	
3650 +	fd = open("/dev/litmus/color_shm", O_RDWR);
3651 +	if (fd < 0) {
3652 +		printf("Device open error.\n");
3653 +		return NULL;
3654 +	}
3655 +
3656 +	ret = ioctl(fd, SET_COLOR_SHM_CMD, &cmd);
3657 +	if (ret < 0) {
3658 +		printf("ioctl failed.\n");
3659 +		return NULL;
3660 +	}
3661 +	
3662 +	ret = ioctl(fd, SET_COLOR_SHM_OFFSET, &offset);
3663 +	if (ret < 0) {
3664 +		printf("ioctl failed.\n");
3665 +		return NULL;
3666 +	}
3667 +	
3668 +	size += offset.offset;
3669 +	mem = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
3670 +	if (mem == MAP_FAILED) {
3671 +		printf("mmap failed.\n");
3672 +		return MAP_FAILED;
3673 +	}
3674 +	close(fd);
3675 +	
3676 +	mem += offset.offset;
3677 +	
3678 +	return mem;
3679 +}
3680 +
3681 diff --git src/kernel_iface.c src/kernel_iface.c
3682 index ca874ff..273ecb2 100644
3683 --- src/kernel_iface.c
3684 +++ src/kernel_iface.c
3685 @@ -2,7 +2,7 @@
3686  #include <sys/fcntl.h> /* for O_RDWR */
3687  #include <sys/unistd.h>
3688  #include <sched.h> /* for sched_yield() */
3689 -
3690 +#include <assert.h>
3691  
3692  #include <stdio.h>
3693  
3694 @@ -98,6 +98,8 @@ int init_kernel_iface(void)
3695  		     != LITMUS_CP_OFFSET_TS_SC_START);
3696  	BUILD_BUG_ON(offsetof(struct control_page, irq_syscall_start)
3697  		     != LITMUS_CP_OFFSET_IRQ_SC_START);
3698 +	BUILD_BUG_ON(offsetof(struct control_page, mode_poll_task)
3699 +		     != LITMUS_CP_OFFSET_MODE_POLL_TASK);
3700  
3701  	err = map_file(LITMUS_CTRL_DEVICE, &mapped_at, CTRL_PAGES * page_size);
3702  
3703 @@ -110,7 +112,7 @@ int init_kernel_iface(void)
3704  		fprintf(stderr, "%s: cannot open LITMUS^RT control page (%m)\n",
3705  			__FUNCTION__);
3706  	}
3707 -
3708 +	ctrl_page->mode_poll_task = 0;
3709  	return err;
3710  }
3711  
3712 @@ -140,6 +142,63 @@ int requested_to_preempt(void)
3713  	return (likely(ctrl_page != NULL) && ctrl_page->sched.np.preempt);
3714  }
3715  
3716 +#ifdef CONFIG_PGMRT_SUPPORT
3717 +void enter_pgm_wait(void) 		
3718 +{ 		
3719 +        if (likely(ctrl_page != NULL) || init_kernel_iface() == 0) { 		
3720 +                assert(!ctrl_page->pgm_waiting); 		
3721 +                ctrl_page->pgm_waiting = 1; 		
3722 +                __sync_synchronize(); 		
3723 +        } 		
3724 +        else { 		
3725 +                fprintf(stderr, "enter_pgm_wait: control page not mapped!\n"); 		
3726 +        } 		
3727 +} 		
3728 +		
3729 +void exit_pgm_wait(void) 		
3730 +{ 		
3731 +        if (likely(ctrl_page != NULL)) { 		
3732 +                assert(ctrl_page->pgm_waiting); 		
3733 +                ctrl_page->pgm_waiting = 0; 		
3734 +                __sync_synchronize(); 		
3735 +        } 		
3736 +        else { 		
3737 +                fprintf(stderr, "exit_pgm_wait: control page not mapped!\n"); 		
3738 +        } 		
3739 +} 		
3740 +		
3741 +void enter_pgm_send(void) 		
3742 +{ 		
3743 +        if (likely(ctrl_page != NULL) || init_kernel_iface() == 0) { 		
3744 +                assert(!ctrl_page->pgm_sending); 		
3745 +                ctrl_page->pgm_sending = 1; /* we will become boosted if 		
3746 +                                               anyone tries to preempt us. */ 		
3747 +                __sync_synchronize(); 		
3748 +        } 		
3749 +        else { 		
3750 +                fprintf(stderr, "enter_pgm_send: control page not mapped!\n"); 		
3751 +        } 		
3752 +} 		
3753 +		
3754 +void exit_pgm_send(void) 		
3755 +{ 		
3756 +        if (likely(ctrl_page != NULL)) { 		
3757 +                assert(ctrl_page->pgm_sending); 		
3758 +		
3759 +                ctrl_page->pgm_satisfied = 1; 		
3760 +                __sync_synchronize(); 		
3761 +		
3762 +                /* re-eval priority. Should clear pgm_sending and pgm_satisfied. */ 		
3763 +                sched_yield(); 		
3764 +		
3765 +                /* double check that Litmus is doing its job */ 		
3766 +                assert(!ctrl_page->pgm_sending && !ctrl_page->pgm_satisfied); 		
3767 +        } 		
3768 +        else { 		
3769 +                fprintf(stderr, "exit_pgm_send: control page not mapped!\n"); 		
3770 +        } 		
3771 +}
3772 +#endif
3773  /* init and return a ptr to the control page for
3774   * preemption and migration overhead analysis
3775   *
3776 diff --git src/syscalls.c src/syscalls.c
3777 index c68f15b..6ec0cd9 100644
3778 --- src/syscalls.c
3779 +++ src/syscalls.c
3780 @@ -86,3 +86,34 @@ int null_call(cycles_t *timestamp)
3781  {
3782  	return syscall(__NR_null_call, timestamp);
3783  }
3784 +
3785 +int reservation_create(int rtype, void *config)
3786 +{
3787 +	return syscall(__NR_reservation_create, rtype, config);
3788 +}
3789 +
3790 +int reservation_destroy(unsigned int reservation_id, int cpu)
3791 +{
3792 +	return syscall(__NR_reservation_destroy, reservation_id, cpu);
3793 +}
3794 +
3795 +int set_mc2_task_param(pid_t pid, struct mc2_task *param)
3796 +{
3797 +	return syscall(__NR_set_mc2_task_param, pid, param);
3798 +}
3799 +
3800 +int set_page_color(int cpu)
3801 +{
3802 +	return syscall(__NR_set_page_color, cpu);
3803 +}
3804 +
3805 +int run_bench(int type, int wss, cacheline_t *src, cacheline_t *dst, lt_t *ts)
3806 +{
3807 +	return syscall(__NR_run_test, type, wss, src, dst, ts);
3808 +}
3809 +
3810 +int lock_buffer(void* vaddr, size_t size, unsigned int lock_way, unsigned int unlock_way)
3811 +{
3812 +	return syscall(__NR_lock_buffer, vaddr, size, lock_way, unlock_way);
3813 +}
3814 +
3815 

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2015-06-04 21:22:59, 244.8 KB) [[attachment:MC2-liblitmus-imx6-rtss15.patch]]
  • [get | view] (2016-05-12 14:35:37, 51.9 KB) [[attachment:MC2-liblitmus-rtss16.patch]]
  • [get | view] (2016-05-12 14:36:06, 190.4 KB) [[attachment:MC2-litmus-rt-rtss16.patch]]
  • [get | view] (2015-07-19 10:27:52, 1119.9 KB) [[attachment:MC2-litmut-rt-imx6-rtss15.patch]]
  • [get | view] (2014-05-27 20:46:19, 58.3 KB) [[attachment:MC2_liblitmus_ipdps15.patch]]
  • [get | view] (2014-05-27 20:45:43, 1044.3 KB) [[attachment:MC2_litmusrt_ipdps15.patch]]
  • [get | view] (2017-04-07 21:48:09, 6099.5 KB) [[attachment:buff_sharing.tar]]
  • [get | view] (2015-01-08 14:20:07, 61.0 KB) [[attachment:feather-trace-patch-against-sched-deadline-v8.patch]]
  • [get | view] (2014-04-01 23:10:10, 38.9 KB) [[attachment:gedf-mp-rtas14.patch]]
  • [get | view] (2012-03-02 20:13:59, 1.9 KB) [[attachment:gpu-klmirqd-liblitmus-rt-ecrts12.patch]]
  • [get | view] (2012-03-02 20:14:25, 389.8 KB) [[attachment:gpu-klmirqd-litmus-rt-ecrts12.patch]]
  • [get | view] (2012-05-26 21:41:34, 418.0 KB) [[attachment:gpusync-rtss12.patch]]
  • [get | view] (2012-05-26 21:42:20, 8.6 KB) [[attachment:gpusync_liblitmus-rtss12.patch]]
  • [get | view] (2013-05-21 15:32:08, 208.6 KB) [[attachment:gpusync_rtss13_liblitmus.patch]]
  • [get | view] (2013-05-21 15:31:32, 779.5 KB) [[attachment:gpusync_rtss13_litmus.patch]]
  • [get | view] (2012-05-26 21:42:41, 71.4 KB) [[attachment:klt_tracker_v1.0.litmus.tgz]]
  • [get | view] (2016-10-13 21:14:05, 19.6 KB) [[attachment:liblitmus-rtas17.patch]]
  • [get | view] (2017-05-01 20:46:22, 90.0 KB) [[attachment:liblitmus-rtns17.patch]]
  • [get | view] (2018-12-11 01:38:53, 49.1 KB) [[attachment:liblitmus-semi-part-with-edfos.patch]]
  • [get | view] (2017-10-09 19:16:09, 304.0 KB) [[attachment:litmus-rt-os-isolation.patch]]
  • [get | view] (2016-10-13 21:13:27, 207.6 KB) [[attachment:litmus-rt-rtas17.patch]]
  • [get | view] (2017-05-01 20:46:40, 207.6 KB) [[attachment:litmus-rt-rtns17.patch]]
  • [get | view] (2018-12-11 01:39:04, 100.5 KB) [[attachment:litmus-rt-semi-part-with-edfos.patch]]
  • [get | view] (2018-06-26 04:31:48, 7.0 KB) [[attachment:mc2_liblitmus_2015.1-rtns18.patch]]
  • [get | view] (2018-06-26 04:31:33, 292.7 KB) [[attachment:mc2_litmus-rt_2015.1-rtns18.patch]]
  • [get | view] (2017-05-01 20:45:10, 2596.9 KB) [[attachment:mcp_study.zip]]
  • [get | view] (2013-07-13 14:11:53, 58.0 KB) [[attachment:omip-ecrts13.patch]]
  • [get | view] (2014-02-19 21:48:33, 17.2 KB) [[attachment:pgmrt-liblitmus-ecrts14.patch]]
  • [get | view] (2014-02-19 21:47:57, 87.8 KB) [[attachment:pgmrt-litmusrt-ecrts14.patch]]
  • [get | view] (2015-01-08 14:22:32, 61.0 KB) [[attachment:sched-deadline-v8-feather-trace-rtas14.patch]]
  • [get | view] (2018-06-26 04:32:13, 2545.1 KB) [[attachment:sched_study_rtns2018.tar.gz]]
  • [get | view] (2017-04-07 21:53:39, 5969.5 KB) [[attachment:seminal.tar]]
  • [get | view] (2017-04-07 21:51:13, 6064.0 KB) [[attachment:shared_libraries.tar]]
  • [get | view] (2013-07-13 13:58:25, 42.7 KB) [[attachment:tracing-and-dflp-rtas13.patch]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.