Attachment 'MC2-liblitmus-rtss16.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..6e9723d 100644
  41 --- Makefile
  42 +++ Makefile
  43 @@ -19,8 +19,8 @@ LITMUS_KERNEL ?= ../litmus-rt
  44  # Internal configuration.
  45  
  46  # compiler flags
  47 -flags-debug    = -O2 -Wall -Werror -g -Wdeclaration-after-statement
  48 -flags-api      = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE
  49 +flags-debug    = -O0 -Wall -g -Wdeclaration-after-statement
  50 +flags-api      = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE -DCONFIG_PGMRT_SUPPORT
  51  
  52  # architecture-specific flags
  53  flags-i386     = -m32
  54 @@ -73,7 +73,8 @@ AR  := ${CROSS_COMPILE}${AR}
  55  
  56  all     = lib ${rt-apps}
  57  rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
  58 -	  base_mt_task uncache runtests
  59 +	  base_mt_task uncache runtests resctrl mc2spin \
  60 +	  mc2thrash mc2thrash1 mc2thrash2 mc2thrash3 mc2bench
  61  
  62  .PHONY: all lib clean dump-config TAGS tags cscope help doc
  63  
  64 @@ -168,7 +169,8 @@ litmus-headers = \
  65  	include/litmus/rt_param.h \
  66  	include/litmus/fpmath.h \
  67  	include/litmus/unistd_32.h \
  68 -	include/litmus/unistd_64.h
  69 +	include/litmus/unistd_64.h \
  70 +	include/litmus/mc2_common.h
  71  
  72  unistd-headers = \
  73    $(foreach file,${unistd-${ARCH}},arch/${include-${ARCH}}/include/$(file))
  74 @@ -234,6 +236,34 @@ obj-release_ts = release_ts.o
  75  obj-measure_syscall = null_call.o
  76  lib-measure_syscall = -lm
  77  
  78 +obj-resctrl = resctrl.o
  79 +
  80 +obj-mc2spin = mc2spin.o common.o
  81 +lib-mc2spin = -lrt -static
  82 +
  83 +obj-mc2pollute = mc2pollute.o common.o
  84 +lib-mc2pollute = -lrt -static
  85 +
  86 +obj-mc2syn = mc2syn.o common.o
  87 +lib-mc2syn = -lrt -static
  88 +
  89 +obj-memthrash = memthrash.o
  90 +lib-memthrash = -lrt
  91 +
  92 +obj-mc2thrash = mc2thrash.o common.o
  93 +lib-mc2thrash = -lrt -static
  94 +
  95 +obj-mc2thrash1 = mc2thrash.o common.o
  96 +lib-mc2thrash1 = -lrt -static
  97 +
  98 +obj-mc2thrash2 = mc2thrash.o common.o
  99 +lib-mc2thrash2 = -lrt -static
 100 +
 101 +obj-mc2thrash3 = mc2thrash.o common.o
 102 +lib-mc2thrash3 = -lrt -static
 103 +
 104 +obj-mc2bench = mc2bench.o common.o
 105 +lib-mc2bench = -lrt -static
 106  # ##############################################################################
 107  # Build everything that depends on liblitmus.
 108  
 109 diff --git bin/base_mt_task.c bin/base_mt_task.c
 110 index aec79a4..1665203 100644
 111 --- bin/base_mt_task.c
 112 +++ bin/base_mt_task.c
 113 @@ -29,11 +29,13 @@
 114  /* Let's create 10 threads in the example, 
 115   * for a total utilization of 1.
 116   */
 117 -#define NUM_THREADS      10 
 118 +#define NUM_THREADS      3 
 119  
 120  /* The information passed to each thread. Could be anything. */
 121  struct thread_context {
 122  	int id;
 123 +	int cpu;
 124 +	int job_no;
 125  };
 126  
 127  /* The real-time thread program. Doesn't have to be the same for
 128 @@ -45,7 +47,7 @@ void* rt_thread(void *tcontext);
 129   * Returns 1 -> task should exit.
 130   *         0 -> task should continue.
 131   */
 132 -int job(void);
 133 +int job(struct thread_context *tcx);
 134  
 135  
 136  /* Catch errors.
 137 @@ -97,6 +99,8 @@ int main(int argc, char** argv)
 138  	 */
 139  	for (i = 0; i < NUM_THREADS; i++) {
 140  		ctx[i].id = i;
 141 +		ctx[i].cpu = 0;
 142 +		ctx[i].job_no = 0;
 143  		pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i));
 144  	}
 145  
 146 @@ -125,6 +129,7 @@ void* rt_thread(void *tcontext)
 147  	int do_exit;
 148  	struct thread_context *ctx = (struct thread_context *) tcontext;
 149  	struct rt_task param;
 150 +	int ret;
 151  
 152  	/* Set up task parameters */
 153  	init_rt_task_param(&param);
 154 @@ -157,6 +162,12 @@ void* rt_thread(void *tcontext)
 155  	 * where CPU ranges from 0 to "Number of CPUs" - 1 before calling
 156  	 * set_rt_task_param().
 157  	 */
 158 +	param.cpu = ctx->cpu;
 159 +	ret = be_migrate_to_cpu(ctx->cpu);
 160 +	if (ret < 0) {
 161 +		printf("RT Thread %d fails to migrate to CPU%d\n", ctx->id, ctx->cpu);
 162 +		return NULL;
 163 +	}
 164  	CALL( set_rt_task_param(gettid(), &param) );
 165  
 166  	/*****
 167 @@ -176,7 +187,7 @@ void* rt_thread(void *tcontext)
 168  		/* Wait until the next job is released. */
 169  		sleep_next_period();
 170  		/* Invoke job. */
 171 -		do_exit = job();		
 172 +		do_exit = job(ctx);		
 173  	} while (!do_exit);
 174  
 175  
 176 @@ -192,10 +203,13 @@ void* rt_thread(void *tcontext)
 177  
 178  
 179  
 180 -int job(void) 
 181 +int job(struct thread_context *tcx) 
 182  {
 183  	/* Do real-time calculation. */
 184 -
 185 +	printf("Job executinig\n");
 186 +	tcx->job_no++;
 187 +	if (tcx->job_no == 5)
 188 +		return 1;
 189  	/* Don't exit. */
 190  	return 0;
 191  }
 192 diff --git bin/mc2bench.c bin/mc2bench.c
 193 new file mode 100644
 194 index 0000000..ea555b5
 195 --- /dev/null
 196 +++ bin/mc2bench.c
 197 @@ -0,0 +1,363 @@
 198 +#include <sys/time.h>
 199 +#include <sys/mman.h>
 200 +
 201 +#include <stdio.h>
 202 +#include <stdlib.h>
 203 +#include <unistd.h>
 204 +#include <time.h>
 205 +#include <string.h>
 206 +#include <assert.h>
 207 +#include <limits.h>
 208 +#include <fcntl.h>
 209 +
 210 +#include "litmus.h"
 211 +#include "common.h"
 212 +#include "color_shm.h"
 213 +
 214 +#define PAGE_SIZE (4096)
 215 +#define INTS_IN_1KB	(1024 / sizeof(int))
 216 +
 217 +static int loops = 100000;
 218 +static cacheline_t* arena = NULL;
 219 +static cacheline_t* local_buf = NULL;
 220 +
 221 +struct timeval t1,t2;
 222 +
 223 +lt_t exectime[100000];
 224 +
 225 +#define UNCACHE_DEV "/dev/litmus/uncache"
 226 +
 227 +static cacheline_t* alloc_shm(int cs, size_t size, int use_huge_pages, int use_uncache_pages)
 228 +{
 229 +	struct color_ioctl_cmd shm_info;
 230 +	struct color_ioctl_offset shm_offset;
 231 +	cacheline_t* arena = NULL;
 232 +	
 233 +
 234 +	shm_info.color = 0x0000ffff; 
 235 +
 236 +	/* Shared memory bank allocation 
 237 +	 * Change values according to /proc/sys/litmus/C[core#]_L[crit. lv]_bank
 238 +	 */	
 239 +	if (cs == 1 || cs == 2)
 240 +		shm_info.bank  = 0x00000020; // hi crit. bank
 241 +	else if (cs == 3)
 242 +		shm_info.bank  = 0x00000040; // levelC
 243 +	
 244 +	shm_offset.offset = 0;
 245 +	shm_offset.lock = 1;
 246 +
 247 +	arena = color_mmap(size, shm_info, shm_offset);
 248 +	if (arena == MAP_FAILED) {
 249 +		printf("mmap failed.\n");
 250 +		return NULL;
 251 +	}
 252 +
 253 +	mlockall(MCL_CURRENT | MCL_FUTURE);
 254 +	/* finish allocation */
 255 +
 256 +    assert(arena);
 257 +
 258 +    return arena;
 259 +}
 260 +
 261 +static cacheline_t* alloc_local(size_t size, int use_huge_pages, int use_uncache_pages)
 262 +{
 263 +    int flags = MAP_PRIVATE | MAP_POPULATE;
 264 +    cacheline_t* arena = NULL;
 265 +    int fd;
 266 +
 267 +    if(use_huge_pages)
 268 +        flags |= MAP_HUGETLB;
 269 +
 270 +	if(use_uncache_pages) {
 271 +			fd = open(UNCACHE_DEV, O_RDWR|O_SYNC);
 272 +			if (fd == -1)
 273 +					bail_out("Failed to open uncache device. Are you running the LITMUS^RT kernel?");
 274 +	}
 275 +	else {
 276 +			fd = -1;
 277 +			flags |= MAP_ANONYMOUS;
 278 +	}
 279 +
 280 +    arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0);
 281 +	
 282 +    if(use_uncache_pages)
 283 +		close(fd);
 284 +
 285 +    assert(arena);
 286 +
 287 +    return arena;
 288 +}
 289 +
 290 +static void dealloc_arena(cacheline_t* arena, size_t size)
 291 +{
 292 +		int ret = munmap((void*)arena, size);
 293 +        if(ret != 0)
 294 +                bail_out("munmap() error");
 295 +}
 296 +
 297 +static int randrange(int min, int max)
 298 +{
 299 +        /* generate a random number on the range [min, max) w/o skew */
 300 +        int limit = max - min;
 301 +        int devisor = RAND_MAX/limit;
 302 +        int retval;
 303 +
 304 +        do {
 305 +                retval = rand() / devisor;
 306 +        } while(retval == limit);
 307 +        retval += min;
 308 +
 309 +        return retval;
 310 +}
 311 +
 312 +static void init_arena(cacheline_t* arena, size_t size)
 313 +{
 314 +    int i;
 315 +        size_t num_arena_elem = size / sizeof(cacheline_t);
 316 +
 317 +        /* Generate a cycle among the cache lines using Sattolo's algorithm.
 318 +           Every int in the cache line points to the same cache line.
 319 +           Note: Sequential walk doesn't care about these values. */
 320 +        for (i = 0; i < num_arena_elem; i++) {
 321 +                int j;
 322 +                for(j = 0; j < INTS_IN_CACHELINE; ++j)
 323 +                        arena[i].line[j] = i;
 324 +        }
 325 +        while(1 < i--) {
 326 +                int j = randrange(0, i);
 327 +                cacheline_t temp = arena[j];
 328 +                arena[j] = arena[i];
 329 +                arena[i] = temp;
 330 +        }
 331 +}
 332 +
 333 +static volatile int dont_optimize_me = 0;
 334 +
 335 +static void usage(char *error) {
 336 +	fprintf(stderr, "Error: %s\n", error);
 337 +	fprintf(stderr,
 338 +		"Usage:\n"
 339 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
 340 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
 341 +		"	rt_spin -l\n"
 342 +		"\n"
 343 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
 344 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-m CRITICALITY LEVEL]\n"
 345 +		"              [-k WSS] [-l LOOPS] [-b BUDGET]\n"
 346 +		"\n"
 347 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n");
 348 +	exit(EXIT_FAILURE);
 349 +}
 350 +
 351 +static int loop_once(int cs, int wss, unsigned int iter)
 352 +{
 353 +	run_bench(cs, wss, arena, local_buf, &exectime[iter]);
 354 +	dont_optimize_me = (int)exectime[iter];
 355 +	
 356 +	return dont_optimize_me;
 357 +}
 358 +
 359 +static int job(int cs, int wss, double exec_time, double program_end)
 360 +{
 361 +	if (wctime() > program_end)
 362 +		return 0;
 363 +	else {
 364 +		register unsigned int iter = 0;
 365 +		while(iter < loops) {
 366 +			loop_once(cs, wss, iter++);
 367 +		}
 368 +   		sleep_next_period(); 
 369 +    	return 1;
 370 +	}
 371 +}
 372 +
 373 +#define OPTSTR "p:wl:m:i:b:k:c:"
 374 +int main(int argc, char** argv)
 375 +{
 376 +	int ret, i;
 377 +	lt_t wcet, period, budget;
 378 +	double wcet_ms, period_ms, budget_ms;
 379 +	unsigned int priority = LITMUS_NO_PRIORITY;
 380 +	int migrate = 0;
 381 +	int cluster = 0;
 382 +	int opt;
 383 +	int wait = 0;
 384 +	double duration = 0, start = 0;
 385 +	struct rt_task param;
 386 +	struct mc2_task mc2_param;
 387 +	struct reservation_config config;
 388 +	int res_type = PERIODIC_POLLING;
 389 +	size_t arena_sz;
 390 +	int wss, cs;
 391 +
 392 +	/* default for reservation */
 393 +	config.id = 0;
 394 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
 395 +	config.cpu = -1;
 396 +	
 397 +	mc2_param.crit = CRIT_LEVEL_C;
 398 +	
 399 +	budget_ms = 1000;
 400 +	
 401 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
 402 +		switch (opt) {
 403 +		case 'w':
 404 +			wait = 1;
 405 +			break;
 406 +		case 'p':
 407 +			cluster = atoi(optarg);
 408 +			migrate = 1;
 409 +			config.cpu = cluster;
 410 +			break;
 411 +		case 'l':
 412 +			loops = atoi(optarg);
 413 +			break;
 414 +		case 'k':
 415 +			wss = atoi(optarg);
 416 +			break;
 417 +		case 'm':
 418 +			mc2_param.crit = atoi(optarg);
 419 +			if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
 420 +				res_type = PERIODIC_POLLING;
 421 +			}
 422 +			else
 423 +				usage("Invalid criticality level.");
 424 +			break;
 425 +		case 'b':
 426 +			budget_ms = atof(optarg);
 427 +			break;
 428 +		case 'i':
 429 +			config.priority = atoi(optarg);
 430 +			break;
 431 +		case 'c':
 432 +			cs = atoi(optarg);
 433 +			break;
 434 +		case ':':
 435 +			usage("Argument missing.");
 436 +			break;
 437 +		case '?':
 438 +		default:
 439 +			usage("Bad argument.");
 440 +			break;
 441 +		}
 442 +	}
 443 +	srand(getpid());
 444 +
 445 +	/*
 446 +	 * We need three parameters
 447 +	 */
 448 +	if (argc - optind < 3)
 449 +		usage("Arguments missing.");
 450 +
 451 +	wcet_ms   = atof(argv[optind + 0]);
 452 +	period_ms = atof(argv[optind + 1]);
 453 +
 454 +	wcet   = ms2ns(wcet_ms);
 455 +	period = ms2ns(period_ms);
 456 +	budget = ms2ns(budget_ms);
 457 +	if (wcet <= 0)
 458 +		usage("The worst-case execution time must be a "
 459 +				"positive number.");
 460 +	if (period <= 0)
 461 +		usage("The period must be a positive number.");
 462 +	if (wcet > period) {
 463 +		usage("The worst-case execution time must not "
 464 +				"exceed the period.");
 465 +	}
 466 +
 467 +	duration  = atof(argv[optind + 2]);
 468 +	
 469 +	if (migrate) {
 470 +		ret = be_migrate_to_domain(cluster);
 471 +		if (ret < 0)
 472 +			bail_out("could not migrate to target partition or cluster.");
 473 +	}
 474 +
 475 +	/* reservation config */
 476 +	config.id = gettid();
 477 +	config.polling_params.budget = budget;
 478 +	config.polling_params.period = period;
 479 +	config.polling_params.offset = 0;
 480 +	config.polling_params.relative_deadline = 0;
 481 +	
 482 +	if (config.polling_params.budget > config.polling_params.period) {
 483 +		usage("The budget must not exceed the period.");
 484 +	}
 485 +	
 486 +	/* create a reservation */
 487 +	ret = reservation_create(res_type, &config);
 488 +	if (ret < 0) {
 489 +		bail_out("failed to create reservation.");
 490 +	}
 491 +	
 492 +	init_rt_task_param(&param);
 493 +	param.exec_cost = wcet;
 494 +	param.period = period;
 495 +	param.priority = priority;
 496 +	param.cls = RT_CLASS_HARD;
 497 +	param.release_policy = TASK_PERIODIC;
 498 +	param.budget_policy = NO_ENFORCEMENT;
 499 +	if (migrate) {
 500 +		param.cpu = gettid();
 501 +	}
 502 +	ret = set_rt_task_param(gettid(), &param);
 503 +	if (ret < 0)
 504 +		bail_out("could not setup rt task params");
 505 +	
 506 +	mc2_param.res_id = gettid();
 507 +	ret = set_mc2_task_param(gettid(), &mc2_param);
 508 +	if (ret < 0)
 509 +		bail_out("could not setup mc2 task params");
 510 +	
 511 +	
 512 +	arena_sz = wss*1024;
 513 +	
 514 +	arena = alloc_shm(cs, arena_sz, 0, 0);
 515 +	if (!arena)
 516 +		bail_out("alloc_shm failed.\n");
 517 +	init_arena(arena, arena_sz);
 518 +	
 519 +	local_buf = alloc_local(arena_sz, 0, 0);
 520 +	if (!local_buf)
 521 +		bail_out("alloc_local failed.\n");
 522 +	init_arena(local_buf, arena_sz);
 523 +	
 524 +	ret = init_litmus();
 525 +	if (ret != 0)
 526 +		bail_out("init_litmus() failed\n");
 527 +
 528 +	start = wctime();
 529 +	ret = task_mode(LITMUS_RT_TASK);
 530 +	if (ret != 0)
 531 +		bail_out("could not become RT task");
 532 +
 533 +	if (mc2_param.crit == CRIT_LEVEL_C)
 534 +		set_page_color(-1);
 535 +	else
 536 +		set_page_color(config.cpu);
 537 +
 538 +	mlockall(MCL_CURRENT | MCL_FUTURE);
 539 +	
 540 +	if (wait) {
 541 +		ret = wait_for_ts_release();
 542 +		if (ret != 0)
 543 +			bail_out("wait_for_ts_release()");
 544 +		start = wctime();
 545 +	}
 546 +
 547 +	job(cs, wss, wcet_ms * 0.001, start + duration);
 548 +
 549 +	ret = task_mode(BACKGROUND_TASK);
 550 +	if (ret != 0)
 551 +		bail_out("could not become regular task (huh?)");
 552 +
 553 +	reservation_destroy(gettid(), config.cpu);
 554 +	dealloc_arena(arena, arena_sz);
 555 +	dealloc_arena(local_buf, arena_sz);
 556 +	printf("%s finished.\n", argv[0]);
 557 +	for (i = 0; i<loops; i++)
 558 +		printf("%llu\n", exectime[i]);
 559 +	return 0;
 560 +}
 561 diff --git bin/mc2spin.c bin/mc2spin.c
 562 new file mode 100644
 563 index 0000000..25b1c58
 564 --- /dev/null
 565 +++ bin/mc2spin.c
 566 @@ -0,0 +1,574 @@
 567 +#include <sys/time.h>
 568 +#include <sys/mman.h>
 569 +
 570 +#include <stdio.h>
 571 +#include <stdlib.h>
 572 +#include <unistd.h>
 573 +#include <time.h>
 574 +#include <string.h>
 575 +#include <assert.h>
 576 +#include <limits.h>
 577 +
 578 +
 579 +#include "litmus.h"
 580 +#include "common.h"
 581 +
 582 +#define PAGE_SIZE 4096
 583 +#define NUM_ITEMS 8192
 584 +
 585 +int *pages;
 586 +unsigned long *access_order;
 587 +
 588 +static void usage(char *error) {
 589 +	fprintf(stderr, "Error: %s\n", error);
 590 +	fprintf(stderr,
 591 +		"Usage:\n"
 592 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
 593 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
 594 +		"	rt_spin -l\n"
 595 +		"\n"
 596 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
 597 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
 598 +		"              [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
 599 +		"              [-i [start,end]:[start,end]...]\n"
 600 +		"\n"
 601 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n"
 602 +		"CRITICAL SECTION LENGTH is in milliseconds.\n");
 603 +	exit(EXIT_FAILURE);
 604 +}
 605 +
 606 +/*
 607 + * returns the character that made processing stop, newline or EOF
 608 + */
 609 +static int skip_to_next_line(FILE *fstream)
 610 +{
 611 +	int ch;
 612 +	for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
 613 +	return ch;
 614 +}
 615 +
 616 +static void skip_comments(FILE *fstream)
 617 +{
 618 +	int ch;
 619 +	for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
 620 +		skip_to_next_line(fstream);
 621 +	ungetc(ch, fstream);
 622 +}
 623 +
 624 +static void get_exec_times(const char *file, const int column,
 625 +			   int *num_jobs,    double **exec_times)
 626 +{
 627 +	FILE *fstream;
 628 +	int  cur_job, cur_col, ch;
 629 +	*num_jobs = 0;
 630 +
 631 +	fstream = fopen(file, "r");
 632 +	if (!fstream)
 633 +		bail_out("could not open execution time file");
 634 +
 635 +	/* figure out the number of jobs */
 636 +	do {
 637 +		skip_comments(fstream);
 638 +		ch = skip_to_next_line(fstream);
 639 +		if (ch != EOF)
 640 +			++(*num_jobs);
 641 +	} while (ch != EOF);
 642 +
 643 +	if (-1 == fseek(fstream, 0L, SEEK_SET))
 644 +		bail_out("rewinding file failed");
 645 +
 646 +	/* allocate space for exec times */
 647 +	*exec_times = calloc(*num_jobs, sizeof(*exec_times));
 648 +	if (!*exec_times)
 649 +		bail_out("couldn't allocate memory");
 650 +
 651 +	for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
 652 +
 653 +		skip_comments(fstream);
 654 +
 655 +		for (cur_col = 1; cur_col < column; ++cur_col) {
 656 +			/* discard input until we get to the column we want */
 657 +			int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
 658 +		}
 659 +
 660 +		/* get the desired exec. time */
 661 +		if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
 662 +			fprintf(stderr, "invalid execution time near line %d\n",
 663 +					cur_job);
 664 +			exit(EXIT_FAILURE);
 665 +		}
 666 +
 667 +		skip_to_next_line(fstream);
 668 +	}
 669 +
 670 +	assert(cur_job == *num_jobs);
 671 +	fclose(fstream);
 672 +}
 673 +
 674 +#define NUMS 4096
 675 +static int num[NUMS];
 676 +static char* progname;
 677 +
 678 +static int randrange(const int max)
 679 +{
 680 +	return (rand() / (RAND_MAX / max + 1));
 681 +}
 682 +
 683 +static void sattolo(unsigned long *items, const unsigned long len)
 684 +{
 685 +	unsigned long i;
 686 +	/* first set up 0, 1, ..., n - 1 */
 687 +	for (i = 0; i < len; i++)
 688 +		items[i] = i;
 689 +	/* note: i is now n */
 690 +	while (1 < i--) {
 691 +		/* 0 <= j < i */
 692 +		int t, j = randrange(i);
 693 +		t = items[i];
 694 +		items[i] = items[j];
 695 +		items[j] = t;
 696 +	}
 697 +}
 698 +
 699 +static int loop_once(void)
 700 +{
 701 +	int i, j = 0;
 702 +	for (i = 0; i < NUMS; i++)
 703 +		j += num[i]++;
 704 +	return j;
 705 +/*
 706 +	int i, tmp;
 707 +	for (i = 0; i < NUM_ITEMS; i++) {
 708 +		tmp = pages[access_order[i]];
 709 +		if (access_order[i] % 3 == 0)
 710 +			pages[access_order[i]] = i+tmp;
 711 +	}
 712 +	return 1;
 713 +*/
 714 +}
 715 +
 716 +static int loop_for(double exec_time, double emergency_exit)
 717 +{
 718 +	double last_loop = 0, loop_start;
 719 +	int tmp = 0;
 720 +
 721 +	double start = cputime();
 722 +	double now = cputime();
 723 +
 724 +	while (now + last_loop < start + exec_time) {
 725 +		loop_start = now;
 726 +		tmp += loop_once();
 727 +		now = cputime();
 728 +		last_loop = now - loop_start;
 729 +		if (emergency_exit && wctime() > emergency_exit) {
 730 +			/* Oops --- this should only be possible if the execution time tracking
 731 +			 * is broken in the LITMUS^RT kernel. */
 732 +			fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
 733 +			fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
 734 +			break;
 735 +		}
 736 +	}
 737 +
 738 +	return tmp;
 739 +}
 740 +
 741 +
 742 +static void debug_delay_loop(int count)
 743 +{
 744 +	double start, end, delay;
 745 +
 746 +	while (count--) {
 747 +		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
 748 +			start = wctime();
 749 +			loop_for(delay, 0);
 750 +			end = wctime();
 751 +			printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
 752 +			       delay,
 753 +			       end - start,
 754 +			       end - start - delay,
 755 +			       100 * (end - start - delay) / delay);
 756 +		}
 757 +	}
 758 +}
 759 +
 760 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
 761 +{
 762 +	double chunk1, chunk2;
 763 +
 764 +	if (wctime() > program_end)
 765 +		return 0;
 766 +	else {
 767 +		if (lock_od >= 0) {
 768 +			/* simulate critical section somewhere in the middle */
 769 +			chunk1 = drand48() * (exec_time - cs_length);
 770 +			chunk2 = exec_time - cs_length - chunk1;
 771 +
 772 +			/* non-critical section */
 773 +			loop_for(chunk1, program_end + 1);
 774 +
 775 +			/* critical section */
 776 +			litmus_lock(lock_od);
 777 +			loop_for(cs_length, program_end + 1);
 778 +			litmus_unlock(lock_od);
 779 +
 780 +			/* non-critical section */
 781 +			loop_for(chunk2, program_end + 2);
 782 +		} else {
 783 +			loop_for(exec_time, program_end + 1);
 784 +		}
 785 +		sleep_next_period();
 786 +		return 1;
 787 +	}
 788 +}
 789 +
 790 +struct lt_interval* parse_td_intervals(int num, char* optarg, unsigned int *num_intervals)
 791 +{
 792 +	int i, matched;
 793 +	struct lt_interval *slots = malloc(sizeof(slots[0]) * num);
 794 +	char** arg = (char**)malloc(sizeof(char*) * num);
 795 +	char *token, *saveptr;
 796 +	double start, end;
 797 +	
 798 +	for (i = 0; i < num; i++) {
 799 +		arg[i] = (char*)malloc(sizeof(char)*100);
 800 +	}
 801 +	
 802 +	i = 0;
 803 +	token = strtok_r(optarg, ":", &saveptr);
 804 +	while(token != NULL) {
 805 +		sprintf(arg[i++], "%s", token);
 806 +		token = strtok_r(NULL, ":", &saveptr);
 807 +	}
 808 +	
 809 +	*num_intervals = 0;
 810 +	
 811 +	for (i=0; i<num; i++) {
 812 +		matched = sscanf(arg[i], "[%lf,%lf]", &start, &end);
 813 +		if (matched != 2) {
 814 +			fprintf(stderr, "could not parse '%s' as interval\n", arg[i]);
 815 +			exit(5);
 816 +		}
 817 +		if (start < 0) {
 818 +			fprintf(stderr, "interval %s: must not start before zero\n", arg[i]);
 819 +			exit(5);
 820 +		}
 821 +		if (end <= start) {
 822 +			fprintf(stderr, "interval %s: end before start\n", arg[i]);
 823 +			exit(5);
 824 +		}
 825 +
 826 +		slots[i].start = ms2ns(start);
 827 +		slots[i].end   = ms2ns(end);
 828 +
 829 +		if (i > 0 && slots[i - 1].end >= slots[i].start) {
 830 +			fprintf(stderr, "interval %s: overlaps with previous interval\n", arg[i]);
 831 +			exit(5);
 832 +		}
 833 +
 834 +		(*num_intervals)++;
 835 +	}
 836 +	
 837 +	for (i=0; i<num; i++) {
 838 +		free(arg[i]);
 839 +	}
 840 +	free(arg);
 841 +	return slots;
 842 +}
 843 +
 844 +#define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:vh:m:i:b:"
 845 +int main(int argc, char** argv)
 846 +{
 847 +	int ret;
 848 +	lt_t wcet;
 849 +	lt_t period;
 850 +	lt_t hyperperiod;
 851 +	lt_t budget;
 852 +	double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
 853 +	unsigned int priority = LITMUS_NO_PRIORITY;
 854 +	int migrate = 0;
 855 +	int cluster = 0;
 856 +	int opt;
 857 +	int wait = 0;
 858 +	int test_loop = 0;
 859 +	int column = 1;
 860 +	const char *file = NULL;
 861 +	int want_enforcement = 0;
 862 +	double duration = 0, start = 0;
 863 +	double *exec_times = NULL;
 864 +	double scale = 1.0;
 865 +	task_class_t class = RT_CLASS_HARD;
 866 +	int cur_job = 0, num_jobs = 0;
 867 +	struct rt_task param;
 868 +	struct mc2_task mc2_param;
 869 +	struct reservation_config config;
 870 +	int res_type = PERIODIC_POLLING;
 871 +	int n_str, num_int = 0;
 872 +
 873 +	int verbose = 0;
 874 +	unsigned int job_no;
 875 +
 876 +	/* locking */
 877 +	int lock_od = -1;
 878 +	int resource_id = 0;
 879 +	const char *lock_namespace = "./rtspin-locks";
 880 +	int protocol = -1;
 881 +	double cs_length = 1; /* millisecond */
 882 +
 883 +	progname = argv[0];
 884 +
 885 +	/* default for reservation */
 886 +	config.id = 0;
 887 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
 888 +	config.cpu = -1;
 889 +	
 890 +	mc2_param.crit = CRIT_LEVEL_C;
 891 +	
 892 +	hyperperiod_ms = 1000;
 893 +	budget_ms = 10;
 894 +	
 895 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
 896 +		switch (opt) {
 897 +		case 'w':
 898 +			wait = 1;
 899 +			break;
 900 +		case 'p':
 901 +			cluster = atoi(optarg);
 902 +			migrate = 1;
 903 +			config.cpu = cluster;
 904 +			break;
 905 +		case 'q':
 906 +			priority = atoi(optarg);
 907 +			if (!litmus_is_valid_fixed_prio(priority))
 908 +				usage("Invalid priority.");
 909 +			break;
 910 +		case 'c':
 911 +			class = str2class(optarg);
 912 +			if (class == -1)
 913 +				usage("Unknown task class.");
 914 +			break;
 915 +		case 'e':
 916 +			want_enforcement = 1;
 917 +			break;
 918 +		case 'l':
 919 +			test_loop = 1;
 920 +			break;
 921 +		case 'o':
 922 +			column = atoi(optarg);
 923 +			break;
 924 +		case 'f':
 925 +			file = optarg;
 926 +			break;
 927 +		case 's':
 928 +			scale = atof(optarg);
 929 +			break;
 930 +		case 'X':
 931 +			protocol = lock_protocol_for_name(optarg);
 932 +			if (protocol < 0)
 933 +				usage("Unknown locking protocol specified.");
 934 +			break;
 935 +		case 'L':
 936 +			cs_length = atof(optarg);
 937 +			if (cs_length <= 0)
 938 +				usage("Invalid critical section length.");
 939 +			break;
 940 +		case 'Q':
 941 +			resource_id = atoi(optarg);
 942 +			if (resource_id <= 0 && strcmp(optarg, "0"))
 943 +				usage("Invalid resource ID.");
 944 +			break;
 945 +		case 'v':
 946 +			verbose = 1;
 947 +			break;
 948 +		case 'm':
 949 +			mc2_param.crit = atoi(optarg);
 950 +			if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
 951 +				usage("Invalid criticality level.");
 952 +			}
 953 +			res_type = PERIODIC_POLLING;
 954 +			break;
 955 +		case 'h':
 956 +			hyperperiod_ms = atof(optarg);
 957 +			break;
 958 +		case 'b':
 959 +			budget_ms = atof(optarg);
 960 +			break;
 961 +		case 'i':
 962 +			config.priority = atoi(optarg);
 963 +			break;
 964 +		case ':':
 965 +			usage("Argument missing.");
 966 +			break;
 967 +		case '?':
 968 +		default:
 969 +			usage("Bad argument.");
 970 +			break;
 971 +		}
 972 +	}
 973 +
 974 +	if (test_loop) {
 975 +		debug_delay_loop(1);
 976 +		return 0;
 977 +	}
 978 +
 979 +	if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
 980 +		usage("Bad criticailty level or priority");
 981 +
 982 +	srand(getpid());
 983 +
 984 +	if (file) {
 985 +		get_exec_times(file, column, &num_jobs, &exec_times);
 986 +
 987 +		if (argc - optind < 2)
 988 +			usage("Arguments missing.");
 989 +
 990 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
 991 +			/* convert the execution time to seconds */
 992 +			duration += exec_times[cur_job] * 0.001;
 993 +		}
 994 +	} else {
 995 +		/*
 996 +		 * if we're not reading from the CSV file, then we need
 997 +		 * three parameters
 998 +		 */
 999 +		if (argc - optind < 3)
1000 +			usage("Arguments missing.");
1001 +	}
1002 +
1003 +	wcet_ms   = atof(argv[optind + 0]);
1004 +	period_ms = atof(argv[optind + 1]);
1005 +
1006 +	wcet   = ms2ns(wcet_ms);
1007 +	period = ms2ns(period_ms);
1008 +	budget = ms2ns(budget_ms);
1009 +	hyperperiod = ms2ns(hyperperiod_ms);
1010 +	
1011 +	if (wcet <= 0)
1012 +		usage("The worst-case execution time must be a "
1013 +				"positive number.");
1014 +	if (period <= 0)
1015 +		usage("The period must be a positive number.");
1016 +	if (!file && wcet > period) {
1017 +		usage("The worst-case execution time must not "
1018 +				"exceed the period.");
1019 +	}
1020 +
1021 +	if (!file)
1022 +		duration  = atof(argv[optind + 2]);
1023 +	else if (file && num_jobs > 1)
1024 +		duration += period_ms * 0.001 * (num_jobs - 1);
1025 +
1026 +	if (migrate) {
1027 +		ret = be_migrate_to_domain(cluster);
1028 +		if (ret < 0)
1029 +			bail_out("could not migrate to target partition or cluster.");
1030 +	}
1031 +
1032 +	/* reservation config */
1033 +	config.id = gettid();
1034 +	
1035 +	if (hyperperiod%period != 0 ) {
1036 +		;//bail_out("hyperperiod must be multiple of period");
1037 +	}
1038 +	
1039 +	config.polling_params.budget = budget;
1040 +	config.polling_params.period = period;
1041 +	config.polling_params.offset = 0;
1042 +	config.polling_params.relative_deadline = 0;
1043 +	if (config.polling_params.budget > config.polling_params.period) {
1044 +		usage("The budget must not exceed the period.");
1045 +	}
1046 +	
1047 +	/* create a reservation */
1048 +	ret = reservation_create(res_type, &config);
1049 +	if (ret < 0) {
1050 +		bail_out("failed to create reservation.");
1051 +	}
1052 +	
1053 +	init_rt_task_param(&param);
1054 +	param.exec_cost = wcet;
1055 +	param.period = period;
1056 +	param.priority = priority;
1057 +	param.cls = class;
1058 +	param.release_policy = TASK_PERIODIC;
1059 +	param.budget_policy = (want_enforcement) ?
1060 +			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
1061 +	if (migrate) {
1062 +		param.cpu = gettid();
1063 +	}
1064 +	ret = set_rt_task_param(gettid(), &param);
1065 +//printf("SET_RT_TASK\n");
1066 +	if (ret < 0)
1067 +		bail_out("could not setup rt task params");
1068 +	
1069 +	mc2_param.res_id = gettid();
1070 +	ret = set_mc2_task_param(gettid(), &mc2_param);
1071 +//printf("SET_MC2_TASK\n");
1072 +	if (ret < 0)
1073 +		bail_out("could not setup mc2 task params");
1074 +
1075 +	pages = (int*)malloc(sizeof(int)*NUM_ITEMS);
1076 +	access_order = (unsigned long*)malloc(sizeof(unsigned long)*NUM_ITEMS);
1077 +	sattolo(access_order, NUM_ITEMS);
1078 +
1079 +	init_litmus();
1080 +printf("CALL\n");
1081 +	set_page_color(config.cpu);
1082 +printf("CALL\n");
1083 +
1084 +//printf("INIT_LITMUS\n");
1085 +	start = wctime();
1086 +	ret = task_mode(LITMUS_RT_TASK);
1087 +//printf("TASK_MODE\n");
1088 +	if (ret != 0)
1089 +		bail_out("could not become RT task");
1090 +
1091 +	if (protocol >= 0) {
1092 +		lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
1093 +		if (lock_od < 0) {
1094 +			perror("litmus_open_lock");
1095 +			usage("Could not open lock.");
1096 +		}
1097 +	}
1098 +
1099 +
1100 +	if (wait) {
1101 +//printf("BEFORE WAIT\n");
1102 +		ret = wait_for_ts_release();
1103 +		if (ret != 0)
1104 +			bail_out("wait_for_ts_release()");
1105 +		start = wctime();
1106 +	}
1107 +
1108 +	if (file) {
1109 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
1110 +			job(exec_times[cur_job] * 0.001 * scale,
1111 +			    start + duration,
1112 +			    lock_od, cs_length * 0.001);
1113 +		}
1114 +	} else {
1115 +		do {
1116 +			if (verbose) {
1117 +				get_job_no(&job_no);
1118 +				printf("rtspin/%d:%u @ %.4fms\n", gettid(),
1119 +					job_no, (wctime() - start) * 1000);
1120 +			}
1121 +		} while (job(wcet_ms * 0.001 * scale, start + duration,
1122 +			   lock_od, cs_length * 0.001));
1123 +	}
1124 +printf("BEFORE BACK_TASK\n");
1125 +	ret = task_mode(BACKGROUND_TASK);
1126 +	if (ret != 0)
1127 +		bail_out("could not become regular task (huh?)");
1128 +
1129 +	if (file)
1130 +		free(exec_times);
1131 +
1132 +	reservation_destroy(gettid(), config.cpu);
1133 +	
1134 +printf("CALL\n");
1135 +	set_page_color(config.cpu);
1136 +printf("CALL\n");
1137 +	free(pages);
1138 +	free(access_order);
1139 +	return 0;
1140 +}
1141 diff --git bin/mc2thrash.c bin/mc2thrash.c
1142 new file mode 100644
1143 index 0000000..044dc03
1144 --- /dev/null
1145 +++ bin/mc2thrash.c
1146 @@ -0,0 +1,272 @@
1147 +#include <sys/time.h>
1148 +#include <sys/mman.h>
1149 +
1150 +#include <stdio.h>
1151 +#include <stdlib.h>
1152 +#include <unistd.h>
1153 +#include <time.h>
1154 +#include <string.h>
1155 +#include <assert.h>
1156 +#include <limits.h>
1157 +
1158 +#include "litmus.h"
1159 +#include "common.h"
1160 +#include "cache_common.h"
1161 +
1162 +#define PAGE_SIZE (4096)
1163 +#define CACHELINE_SIZE 32
1164 +#define WSS 		2048
1165 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
1166 +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
1167 +#define INTS_IN_1KB	(1024 / sizeof(int))
1168 +
1169 +static cacheline_t* arena = NULL;
1170 +
1171 +static int random_walk(cacheline_t *mem, int write_cycle)
1172 +{
1173 +	/* a random cycle among the cache lines was set up by init_arena(). */
1174 +	int sum, i, next;
1175 +
1176 +	int numlines = WSS * CACHELINES_IN_1KB;
1177 +
1178 +	sum = 0;
1179 +
1180 +	next = mem - arena;
1181 +
1182 +	if (write_cycle == 0) {
1183 +		for (i = 0; i < numlines; i++) {
1184 +			/* every element in the cacheline has the same value */
1185 +			next = arena[next].line[0];
1186 +			sum += next;
1187 +		}
1188 +	}
1189 +	
1190 +	else {
1191 +		int w, which_line;
1192 +		for (i = 0, w = 0; i < numlines; i++) {
1193 +			which_line = next;
1194 +			next = arena[next].line[0];
1195 +			if((w % write_cycle) != (write_cycle - 1)) {
1196 +				sum += next;
1197 +			}
1198 +			else {
1199 +				((volatile cacheline_t*)arena)[which_line].line[0] = next;
1200 +			}
1201 +		}
1202 +	}
1203 +	return sum;
1204 +}
1205 +
1206 +static cacheline_t* random_start(void)
1207 +{
1208 +	return arena + randrange(0, ((WSS * 1024)/sizeof(cacheline_t)));
1209 +}
1210 +
1211 +static volatile int dont_optimize_me = 0;
1212 +
1213 +static void usage(char *error) {
1214 +	fprintf(stderr, "Error: %s\n", error);
1215 +	fprintf(stderr,
1216 +		"Usage:\n"
1217 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
1218 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
1219 +		"	rt_spin -l\n"
1220 +		"\n"
1221 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
1222 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-m CRITICALITY LEVEL]\n"
1223 +		"              [-k WSS] [-l LOOPS] [-b BUDGET]\n"
1224 +		"\n"
1225 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n");
1226 +	exit(EXIT_FAILURE);
1227 +}
1228 +
1229 +static int loop_once(void)
1230 +{
1231 +	cacheline_t *mem;
1232 +	int temp;
1233 +	
1234 +	mem = random_start();
1235 +	temp = random_walk(mem, 1);
1236 +    
1237 +	//mem = sequential_start(wss);
1238 +	//temp = sequential_walk(mem, wss, 0);
1239 +	dont_optimize_me = temp;
1240 +	
1241 +	return dont_optimize_me;
1242 +}
1243 +
1244 +static int job(double exec_time, double program_end)
1245 +{
1246 +	if (wctime() > program_end)
1247 +		return 0;
1248 +	else {
1249 +		double last_loop = 0, loop_start;
1250 +		double start = cputime();
1251 +		double now = cputime();
1252 +		while(now + last_loop < start + exec_time) {
1253 +			loop_start = now;
1254 +			loop_once();
1255 +			now = cputime();
1256 +			last_loop = now - loop_start;
1257 +		}
1258 +		sleep_next_period(); 
1259 +   		return 1;
1260 +	}
1261 +}
1262 +
1263 +#define OPTSTR "p:wm:i:k:"
1264 +int main(int argc, char** argv)
1265 +{
1266 +	int ret, i;
1267 +	lt_t wcet, period, budget;
1268 +	double wcet_ms, period_ms;
1269 +	unsigned int priority = LITMUS_NO_PRIORITY;
1270 +	int migrate = 0;
1271 +	int cluster = 0;
1272 +	int opt;
1273 +	int wait = 0;
1274 +	double duration = 0, start = 0;
1275 +	struct rt_task param;
1276 +	struct mc2_task mc2_param;
1277 +	struct reservation_config config;
1278 +	int res_type = PERIODIC_POLLING;
1279 +	size_t arena_sz;
1280 +	
1281 +	/* default for reservation */
1282 +	config.id = 0;
1283 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
1284 +	config.cpu = -1;
1285 +	mc2_param.crit = CRIT_LEVEL_C;
1286 +	
1287 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1288 +		switch (opt) {
1289 +		case 'w':
1290 +			wait = 1;
1291 +			break;
1292 +		case 'p':
1293 +			cluster = atoi(optarg);
1294 +			migrate = 1;
1295 +			config.cpu = cluster;
1296 +			break;
1297 +		case 'm':
1298 +			mc2_param.crit = atoi(optarg);
1299 +			if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
1300 +				res_type = PERIODIC_POLLING;
1301 +			}
1302 +			else
1303 +				usage("Invalid criticality level.");
1304 +			break;
1305 +		case 'i':
1306 +			config.priority = atoi(optarg);
1307 +			break;
1308 +		case ':':
1309 +			usage("Argument missing.");
1310 +			break;
1311 +		case '?':
1312 +		default:
1313 +			usage("Bad argument.");
1314 +			break;
1315 +		}
1316 +	}
1317 +	srand(getpid());
1318 +	/* We need three parameters */
1319 +	if (argc - optind < 3)
1320 +		usage("Arguments missing.");
1321 +
1322 +	wcet_ms   = atof(argv[optind + 0]);
1323 +	period_ms = atof(argv[optind + 1]);
1324 +
1325 +	wcet   = ms2ns(wcet_ms);
1326 +	period = ms2ns(period_ms);
1327 +	budget = ms2ns(period_ms);
1328 +	if (wcet <= 0)
1329 +		usage("The worst-case execution time must be a "
1330 +				"positive number.");
1331 +	if (period <= 0)
1332 +		usage("The period must be a positive number.");
1333 +	if (wcet > period) {
1334 +		usage("The worst-case execution time must not "
1335 +				"exceed the period.");
1336 +	}
1337 +
1338 +	duration  = atof(argv[optind + 2]);
1339 +	
1340 +	if (migrate) {
1341 +		ret = be_migrate_to_domain(cluster);
1342 +		if (ret < 0)
1343 +			bail_out("could not migrate to target partition or cluster.");
1344 +	}
1345 +
1346 +	/* reservation config */
1347 +	config.id = gettid();
1348 +	config.polling_params.budget = budget;
1349 +	config.polling_params.period = period;
1350 +	config.polling_params.offset = 0;
1351 +	config.polling_params.relative_deadline = 0;
1352 +	
1353 +	if (config.polling_params.budget > config.polling_params.period) {
1354 +		usage("The budget must not exceed the period.");
1355 +	}
1356 +	
1357 +	/* create a reservation */
1358 +	ret = reservation_create(res_type, &config);
1359 +	if (ret < 0) {
1360 +		bail_out("failed to create reservation.");
1361 +	}
1362 +	
1363 +	init_rt_task_param(&param);
1364 +	param.exec_cost = wcet;
1365 +	param.period = period;
1366 +	param.priority = priority;
1367 +	param.cls = RT_CLASS_HARD;
1368 +	param.release_policy = TASK_PERIODIC;
1369 +	param.budget_policy = NO_ENFORCEMENT;
1370 +	if (migrate) {
1371 +		param.cpu = gettid();
1372 +	}
1373 +	ret = set_rt_task_param(gettid(), &param);
1374 +	if (ret < 0)
1375 +		bail_out("could not setup rt task params");
1376 +	
1377 +	mc2_param.res_id = gettid();
1378 +	ret = set_mc2_task_param(gettid(), &mc2_param);
1379 +	if (ret < 0)
1380 +		bail_out("could not setup mc2 task params");
1381 +	
1382 +	arena_sz = WSS*1024;
1383 +	arena = alloc_arena(arena_sz, 0, 1);
1384 +	init_arena(arena, arena_sz);
1385 +	
1386 +	ret = init_litmus();
1387 +	if (ret != 0)
1388 +		bail_out("init_litmus() failed\n");
1389 +
1390 +	start = wctime();
1391 +	ret = task_mode(LITMUS_RT_TASK);
1392 +	if (ret != 0)
1393 +		bail_out("could not become RT task");
1394 +
1395 +	if (mc2_param.crit == CRIT_LEVEL_C)
1396 +		set_page_color(-1);
1397 +	else
1398 +		set_page_color(config.cpu);
1399 +	
1400 +	lock_memory();
1401 +	
1402 +	if (wait) {
1403 +		ret = wait_for_ts_release();
1404 +		if (ret != 0)
1405 +			bail_out("wait_for_ts_release()");
1406 +		start = wctime();
1407 +	}
1408 +
1409 +	while (job(wcet_ms * 0.001, start + duration)) {};
1410 +
1411 +	ret = task_mode(BACKGROUND_TASK);
1412 +	if (ret != 0)
1413 +		bail_out("could not become regular task (huh?)");
1414 +
1415 +	reservation_destroy(gettid(), config.cpu);
1416 +	dealloc_arena(arena, arena_sz);
1417 +	return 0;
1418 +}
1419 diff --git bin/resctrl.c bin/resctrl.c
1420 new file mode 100644
1421 index 0000000..63b5054
1422 --- /dev/null
1423 +++ bin/resctrl.c
1424 @@ -0,0 +1,242 @@
1425 +#include <stdio.h>
1426 +#include <stdlib.h>
1427 +#include <string.h>
1428 +#include <unistd.h>
1429 +#include <limits.h>
1430 +#include <signal.h>
1431 +
1432 +#include <sched.h>
1433 +
1434 +#include "litmus.h"
1435 +#include "common.h"
1436 +
1437 +const char *usage_msg =
1438 +	"Usage: resctrl OPTIONS [INTERVAL-START,INTERVAL-END]*\n"
1439 +	"    -n ID             create new reservation with id ID\n"
1440 +	"    -a PID            attach already-running process PID to reservation\n"
1441 +	"    -r ID             specify which reservation to attach to (not needed with -n)\n"
1442 +	"    -t TYPE           type of reservation (polling-periodic, polling-sporadic, table-driven)\n"
1443 +	"    -c CPU            physical partition or cluster to assign to\n"
1444 +	"    -b BUDGET         polling reservation budget (in ms, default: 10ms)\n"
1445 +	"    -p PERIOD         polling reservation period (in ms, default: 100ms)\n"
1446 +	"    -d DEADLINE       relative deadline, implicit by default (in ms)\n"
1447 +	"    -o OFFSET         offset (also known as phase), zero by default (in ms)\n"
1448 +	"    -q PRIORITY       priority to use (EDF by default, highest priority = 1)\n"
1449 +	"    -m MAJOR-CYCLE    major cycle length (in ms, for table-driven reservations) \n"
1450 +	"\n";
1451 +
1452 +void usage(char *error) {
1453 +	fprintf(stderr, "%s\n%s", error, usage_msg);
1454 +	exit(1);
1455 +}
1456 +
1457 +
1458 +static void attach_task(int attach_pid, struct reservation_config *config)
1459 +{
1460 +	int ret;
1461 +	struct rt_task param;
1462 +	struct sched_param linux_param;
1463 +
1464 +	ret = be_migrate_thread_to_cpu(attach_pid, config->cpu);
1465 +	if (ret < 0) {
1466 +		fprintf(stderr, "failed to migrate task %d to CPU %d\n",
1467 +			attach_pid, config->cpu);
1468 +		exit(4);
1469 +	}
1470 +
1471 +	init_rt_task_param(&param);
1472 +	/* dummy values */
1473 +	param.exec_cost = ms2ns(100);
1474 +	param.period    = ms2ns(100);
1475 +	/* specify reservation as "virtual" CPU */
1476 +	param.cpu       = config->id;
1477 +
1478 +	ret = set_rt_task_param(attach_pid, &param);
1479 +	if (ret < 0) {
1480 +		fprintf(stderr, "failed to set RT task parameters for task %d (%m)\n",
1481 +			attach_pid);
1482 +		exit(2);
1483 +	}
1484 +
1485 +	linux_param.sched_priority = 0;
1486 +	ret = sched_setscheduler(attach_pid, SCHED_LITMUS, &linux_param);
1487 +	if (ret < 0) {
1488 +		fprintf(stderr, "failed to transition task %d to LITMUS^RT class (%m)\n",
1489 +			attach_pid);
1490 +		exit(3);
1491 +	}
1492 +}
1493 +
1494 +static struct lt_interval* parse_td_intervals(int argc, char** argv,
1495 +	unsigned int *num_intervals, lt_t major_cycle)
1496 +{
1497 +	int i, matched;
1498 +	struct lt_interval *slots = malloc(sizeof(slots[0]) * argc);
1499 +	double start, end;
1500 +
1501 +	*num_intervals = 0;
1502 +	for (i = 0; i < argc; i++) {
1503 +		matched = sscanf(argv[i], "[%lf,%lf]", &start, &end);
1504 +		if (matched != 2) {
1505 +			fprintf(stderr, "could not parse '%s' as interval\n", argv[i]);
1506 +			exit(5);
1507 +		}
1508 +		if (start < 0) {
1509 +			fprintf(stderr, "interval %s: must not start before zero\n", argv[i]);
1510 +			exit(5);
1511 +		}
1512 +		if (end <= start) {
1513 +			fprintf(stderr, "interval %s: end before start\n", argv[i]);
1514 +			exit(5);
1515 +		}
1516 +
1517 +		slots[i].start = ms2ns(start);
1518 +		slots[i].end   = ms2ns(end);
1519 +
1520 +		if (i > 0 && slots[i - 1].end >= slots[i].start) {
1521 +			fprintf(stderr, "interval %s: overlaps with previous interval\n", argv[i]);
1522 +			exit(5);
1523 +		}
1524 +
1525 +		if (slots[i].end >= major_cycle) {
1526 +			fprintf(stderr, "interval %s: exceeds major cycle length\n", argv[i]);
1527 +			exit(5);
1528 +		}
1529 +
1530 +		(*num_intervals)++;
1531 +	}
1532 +
1533 +	return slots;
1534 +}
1535 +
1536 +#define OPTSTR "n:a:r:t:c:b:p:d:o:q:m:h"
1537 +
1538 +int main(int argc, char** argv)
1539 +{
1540 +	int ret, opt;
1541 +	double budget_ms, period_ms, offset_ms, deadline_ms, major_cycle_ms;
1542 +	int create_new = 0;
1543 +	int attach_pid = 0;
1544 +	int res_type = SPORADIC_POLLING;
1545 +
1546 +	struct reservation_config config;
1547 +
1548 +	/* Reasonable defaults */
1549 +	offset_ms      =    0;
1550 +	deadline_ms    =    0;
1551 +	budget_ms      =   10;
1552 +	period_ms      =  100;
1553 +	major_cycle_ms = 1000;
1554 +
1555 +	config.id = 0;
1556 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
1557 +	config.cpu = 0;
1558 +
1559 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1560 +		switch (opt) {
1561 +		case 'b':
1562 +			budget_ms = atof(optarg);
1563 +			break;
1564 +		case 'p':
1565 +			period_ms = atof(optarg);
1566 +			break;
1567 +		case 'd':
1568 +			deadline_ms = atof(optarg);
1569 +			if (deadline_ms <= 0) {
1570 +				usage("The relative deadline must be a positive"
1571 +					" number.");
1572 +			}
1573 +			break;
1574 +		case 'o':
1575 +			offset_ms = atof(optarg);
1576 +			break;
1577 +		case 'm':
1578 +			major_cycle_ms = atof(optarg);
1579 +			break;
1580 +
1581 +		case 'q':
1582 +			config.priority = atoi(optarg);
1583 +			if (!config.priority)
1584 +				usage("-q: invalid priority");
1585 +			break;
1586 +		case 'c':
1587 +			config.cpu = atoi(optarg);
1588 +			break;
1589 +
1590 +		case 'n':
1591 +			create_new = 1;
1592 +			config.id  = atoi(optarg);
1593 +			break;
1594 +		case 'a':
1595 +			attach_pid = atoi(optarg);
1596 +			if (!attach_pid)
1597 +				usage("-a: invalid PID");
1598 +			break;
1599 +
1600 +		case 'r':
1601 +			config.id  = atoi(optarg);
1602 +			break;
1603 +
1604 +		case 't':
1605 +			if (strcmp(optarg, "polling-periodic") == 0) {
1606 +				res_type = PERIODIC_POLLING;
1607 +			} else if (strcmp(optarg, "polling-sporadic") == 0) {
1608 +				res_type = SPORADIC_POLLING;
1609 +			}  else if (strcmp(optarg, "table-driven") == 0) {
1610 +				res_type = TABLE_DRIVEN;
1611 +				/* Default for table-driven reservations to
1612 +				 * maximum priority. EDF has not meaning for
1613 +				 * table-driven reservations. */
1614 +				if (config.priority == LITMUS_NO_PRIORITY)
1615 +					config.priority = LITMUS_HIGHEST_PRIORITY;
1616 +			} else {
1617 +				usage("Unknown reservation type.");
1618 +			}
1619 +			break;
1620 +
1621 +		case 'h':
1622 +			usage("");
1623 +			break;
1624 +		case ':':
1625 +			usage("Argument missing.");
1626 +			break;
1627 +		case '?':
1628 +		default:
1629 +			usage("Bad argument.");
1630 +			break;
1631 +		}
1632 +	}
1633 +
1634 +	if (res_type != TABLE_DRIVEN) {
1635 +		config.polling_params.budget = ms2ns(budget_ms);
1636 +		config.polling_params.period = ms2ns(period_ms);
1637 +		config.polling_params.offset = ms2ns(offset_ms);
1638 +		config.polling_params.relative_deadline = ms2ns(deadline_ms);
1639 +		if (config.polling_params.budget > config.polling_params.period) {
1640 +			usage("The budget must not exceed the period.");
1641 +		}
1642 +	} else {
1643 +		config.table_driven_params.major_cycle_length = ms2ns(major_cycle_ms);
1644 +		argc -= optind;
1645 +		argv += optind;
1646 +		config.table_driven_params.intervals = parse_td_intervals(
1647 +			argc, argv, &config.table_driven_params.num_intervals,
1648 +			config.table_driven_params.major_cycle_length);
1649 +		if (!config.table_driven_params.num_intervals)
1650 +			usage("Table-driven reservations require at least one interval to be specified.");
1651 +	}
1652 +
1653 +	if (create_new) {
1654 +		ret = reservation_create(res_type, &config);
1655 +		if (ret < 0) {
1656 +			fprintf(stderr, "failed to create reservation %u (%m)\n",
1657 +				config.id);
1658 +			exit(1);
1659 +		}
1660 +	}
1661 +
1662 +	if (attach_pid)
1663 +		attach_task(attach_pid, &config);
1664 +
1665 +	return 0;
1666 +}
1667 diff --git bin/rtspin.c bin/rtspin.c
1668 index b4156cc..fd57c45 100644
1669 --- bin/rtspin.c
1670 +++ bin/rtspin.c
1671 @@ -6,7 +6,7 @@
1672  #include <time.h>
1673  #include <string.h>
1674  #include <assert.h>
1675 -
1676 +#include <limits.h>
1677  
1678  #include "litmus.h"
1679  #include "common.h"
1680 @@ -184,16 +184,17 @@ static int job(double exec_time, double program_end, int lock_od, double cs_leng
1681  	}
1682  }
1683  
1684 -#define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:"
1685 +#define OPTSTR "p:c:wlveo:f:s:q:r:X:L:Q:v"
1686  int main(int argc, char** argv)
1687  {
1688  	int ret;
1689  	lt_t wcet;
1690  	lt_t period;
1691  	double wcet_ms, period_ms;
1692 -	unsigned int priority = LITMUS_LOWEST_PRIORITY;
1693 +	unsigned int priority = LITMUS_NO_PRIORITY;
1694  	int migrate = 0;
1695  	int cluster = 0;
1696 +	int reservation = -1;
1697  	int opt;
1698  	int wait = 0;
1699  	int test_loop = 0;
1700 @@ -207,6 +208,9 @@ int main(int argc, char** argv)
1701  	int cur_job = 0, num_jobs = 0;
1702  	struct rt_task param;
1703  
1704 +	int verbose = 0;
1705 +	unsigned int job_no;
1706 +
1707  	/* locking */
1708  	int lock_od = -1;
1709  	int resource_id = 0;
1710 @@ -225,6 +229,9 @@ int main(int argc, char** argv)
1711  			cluster = atoi(optarg);
1712  			migrate = 1;
1713  			break;
1714 +		case 'r':
1715 +			reservation = atoi(optarg);
1716 +			break;
1717  		case 'q':
1718  			priority = atoi(optarg);
1719  			if (!litmus_is_valid_fixed_prio(priority))
1720 @@ -265,6 +272,9 @@ int main(int argc, char** argv)
1721  			if (resource_id <= 0 && strcmp(optarg, "0"))
1722  				usage("Invalid resource ID.");
1723  			break;
1724 +		case 'v':
1725 +			verbose = 1;
1726 +			break;
1727  		case ':':
1728  			usage("Argument missing.");
1729  			break;
1730 @@ -334,14 +344,19 @@ int main(int argc, char** argv)
1731  	param.cls = class;
1732  	param.budget_policy = (want_enforcement) ?
1733  			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
1734 -	if (migrate)
1735 -		param.cpu = domain_to_first_cpu(cluster);
1736 +	if (migrate) {
1737 +		if (reservation >= 0)
1738 +			param.cpu = reservation;
1739 +		else
1740 +			param.cpu = domain_to_first_cpu(cluster);
1741 +	}
1742  	ret = set_rt_task_param(gettid(), &param);
1743  	if (ret < 0)
1744  		bail_out("could not setup rt task params");
1745  
1746  	init_litmus();
1747  
1748 +	start = wctime();
1749  	ret = task_mode(LITMUS_RT_TASK);
1750  	if (ret != 0)
1751  		bail_out("could not become RT task");
1752 @@ -355,14 +370,14 @@ int main(int argc, char** argv)
1753  		}
1754  	}
1755  
1756 +
1757  	if (wait) {
1758  		ret = wait_for_ts_release();
1759  		if (ret != 0)
1760  			bail_out("wait_for_ts_release()");
1761 +		start = wctime();
1762  	}
1763  
1764 -	start = wctime();
1765 -
1766  	if (file) {
1767  		/* use times read from the CSV file */
1768  		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
1769 @@ -372,8 +387,14 @@ int main(int argc, char** argv)
1770  			    lock_od, cs_length * 0.001);
1771  		}
1772  	} else {
1773 -		/* convert to seconds and scale */
1774 -		while (job(wcet_ms * 0.001 * scale, start + duration,
1775 +		do {
1776 +			if (verbose) {
1777 +				get_job_no(&job_no);
1778 +				printf("rtspin/%d:%u @ %.4fms\n", gettid(),
1779 +					job_no, (wctime() - start) * 1000);
1780 +			}
1781 +			/* convert to seconds and scale */
1782 +		} while (job(wcet_ms * 0.001 * scale, start + duration,
1783  			   lock_od, cs_length * 0.001));
1784  	}
1785  
1786 diff --git include/cache_common.h include/cache_common.h
1787 new file mode 100644
1788 index 0000000..2957dd3
1789 --- /dev/null
1790 +++ include/cache_common.h
1791 @@ -0,0 +1,213 @@
1792 +#ifndef __CACHE_COMMON_H__
1793 +#define __CACHE_COMMON_H__
1794 +
1795 +#include <stdio.h>
1796 +#include <stdlib.h>
1797 +#include <time.h>
1798 +#include <string.h>
1799 +#include <assert.h>
1800 +
1801 +#include <signal.h>
1802 +#include <sys/mman.h>
1803 +#include <sys/types.h>
1804 +#include <sys/stat.h>
1805 +#include <fcntl.h>
1806 +#include <unistd.h>
1807 +
1808 +#include <sys/io.h>
1809 +#include <sys/utsname.h>
1810 +
1811 +#include <sched.h>
1812 +#include <sys/time.h>
1813 +#include <sys/resource.h>
1814 +
1815 +#include "litmus.h"
1816 +#include "asm/cycles.h"
1817 +
1818 +#if defined(__i386__) || defined(__x86_64__)
1819 +#include "asm/irq.h"
1820 +#endif
1821 +
1822 +
1823 +#define UNCACHE_DEV "/dev/litmus/uncache"
1824 +
1825 +static void die(char *error)
1826 +{
1827 +    fprintf(stderr, "Error: %s (errno: %m)\n",
1828 +        error);
1829 +    exit(1);
1830 +}
1831 +
1832 +static int migrate_to(int cpu)
1833 +{
1834 +    int ret;
1835 +
1836 +    static __thread cpu_set_t* cpu_set = NULL;
1837 +    static __thread size_t cpu_set_sz;
1838 +    static __thread int num_cpus;
1839 +    if(!cpu_set)
1840 +    {
1841 +        num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
1842 +        cpu_set = CPU_ALLOC(num_cpus);
1843 +        cpu_set_sz = CPU_ALLOC_SIZE(num_cpus);
1844 +    }
1845 +
1846 +    CPU_ZERO_S(cpu_set_sz, cpu_set);
1847 +    CPU_SET_S(cpu, cpu_set_sz, cpu_set);
1848 +    ret = sched_setaffinity(0 /* self */, cpu_set_sz, cpu_set);
1849 +    return ret;
1850 +}
1851 +
1852 +static int check_migrations(int num_cpus)
1853 +{
1854 +    int cpu, err;
1855 +
1856 +    for (cpu = 0; cpu < num_cpus; cpu++) {
1857 +        err = migrate_to(cpu);
1858 +        if (err != 0) {
1859 +            fprintf(stderr, "Migration to CPU %d failed: %m.\n",
1860 +                cpu + 1);
1861 +            return 1;
1862 +        }
1863 +    }
1864 +    return 0;
1865 +}
1866 +
1867 +static int become_posix_realtime_task(int prio)
1868 +{
1869 +    struct sched_param param;
1870 +    memset(&param, 0, sizeof(param));
1871 +    param.sched_priority = prio;
1872 +    return sched_setscheduler(0 /* self */, SCHED_FIFO, &param);
1873 +}
1874 +
1875 +static int renice(int nice_val)
1876 +{
1877 +        return setpriority(PRIO_PROCESS, 0 /* self */, nice_val);
1878 +}
1879 +
1880 +static int lock_memory(void)
1881 +{
1882 +    return mlockall(MCL_CURRENT | MCL_FUTURE);
1883 +}
1884 +
1885 +/* define CACHELINE_SIZE if not provided by compiler args */
1886 +#ifndef CACHELINE_SIZE
1887 +#if defined(__i386__) || defined(__x86_64__)
1888 +/* recent intel cpus */
1889 +#define CACHELINE_SIZE 64
1890 +#elif defined(__arm__)
1891 +/* at least with Cortex-A9 cpus ("8 words") */
1892 +#define CACHELINE_SIZE 32
1893 +#else
1894 +#error "Could not determine cacheline size!"
1895 +#endif
1896 +#endif
1897 +
1898 +//#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
1899 +//typedef struct cacheline
1900 +//{
1901 +//        int line[INTS_IN_CACHELINE];
1902 +//} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
1903 +
1904 +static cacheline_t* alloc_arena(size_t size, int use_huge_pages, int use_uncache_pages)
1905 +{
1906 +    int flags = MAP_PRIVATE | MAP_POPULATE;
1907 +    cacheline_t* arena = NULL;
1908 +    int fd;
1909 +
1910 +    if(use_huge_pages)
1911 +        flags |= MAP_HUGETLB;
1912 +
1913 +	if(use_uncache_pages) {
1914 +			fd = open(UNCACHE_DEV, O_RDWR);
1915 +			if (fd == -1)
1916 +					die("Failed to open uncache device. Are you running the LITMUS^RT kernel?");
1917 +	}
1918 +	else {
1919 +			fd = -1;
1920 +			flags |= MAP_ANONYMOUS;
1921 +	}
1922 +
1923 +    arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0);
1924 +	
1925 +    if(use_uncache_pages)
1926 +		close(fd);
1927 +
1928 +    assert(arena);
1929 +
1930 +        return arena;
1931 +}
1932 +
1933 +static void dealloc_arena(cacheline_t* arena, size_t size)
1934 +{
1935 +		int ret = munmap((void*)arena, size);
1936 +        if(ret != 0)
1937 +                die("munmap() error");
1938 +}
1939 +
1940 +static int randrange(int min, int max)
1941 +{
1942 +        /* generate a random number on the range [min, max) w/o skew */
1943 +        int limit = max - min;
1944 +        int devisor = RAND_MAX/limit;
1945 +        int retval;
1946 +
1947 +        do {
1948 +                retval = rand() / devisor;
1949 +        } while(retval == limit);
1950 +        retval += min;
1951 +
1952 +        return retval;
1953 +}
1954 +
1955 +static void init_arena(cacheline_t* arena, size_t size)
1956 +{
1957 +    int i;
1958 +        size_t num_arena_elem = size / sizeof(cacheline_t);
1959 +
1960 +        /* Generate a cycle among the cache lines using Sattolo's algorithm.
1961 +           Every int in the cache line points to the same cache line.
1962 +           Note: Sequential walk doesn't care about these values. */
1963 +        for (i = 0; i < num_arena_elem; i++) {
1964 +                int j;
1965 +                for(j = 0; j < INTS_IN_CACHELINE; ++j)
1966 +                        arena[i].line[j] = i;
1967 +        }
1968 +        while(1 < i--) {
1969 +                int j = randrange(0, i);
1970 +                cacheline_t temp = arena[j];
1971 +                arena[j] = arena[i];
1972 +                arena[i] = temp;
1973 +        }
1974 +}
1975 +
1976 +static void sleep_us(int microseconds)
1977 +{
1978 +    struct timespec delay;
1979 +
1980 +    delay.tv_sec = 0;
1981 +    delay.tv_nsec = microseconds * 1000;
1982 +    if (nanosleep(&delay, NULL) != 0)
1983 +        die("sleep failed");
1984 +}
1985 +
1986 +static int completed(int nSamples, int* history, int nCategories)
1987 +{
1988 +        int i;
1989 +        for(i = 0; i < nCategories; ++i)
1990 +                if(history[i] < nSamples)
1991 +                        return 0;
1992 +        return 1;
1993 +}
1994 +
1995 +inline unsigned long get_cyclecount (void)
1996 +{
1997 +	unsigned long value;
1998 +	// Read CCNT Register
1999 +	asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
2000 +	return value;
2001 +}
2002 +
2003 +
2004 +#endif
2005 diff --git include/color_shm.h include/color_shm.h
2006 new file mode 100644
2007 index 0000000..449ec9d
2008 --- /dev/null
2009 +++ include/color_shm.h
2010 @@ -0,0 +1,20 @@
2011 +#include <sys/types.h>
2012 +#include <sys/ioctl.h>
2013 +#include <fcntl.h>
2014 +
2015 +#define SHM_MAJOR		(240)
2016 +
2017 +struct color_ioctl_cmd {
2018 +	unsigned int color;
2019 +	unsigned int bank;
2020 +};
2021 +
2022 +struct color_ioctl_offset {
2023 +	unsigned long offset;
2024 +	int lock;
2025 +};
2026 +
2027 +#define SET_COLOR_SHM_CMD		_IOW(SHM_MAJOR, 0x1, struct color_ioctl_cmd)
2028 +#define SET_COLOR_SHM_OFFSET	_IOW(SHM_MAJOR, 0x2, struct color_ioctl_offset)
2029 +
2030 +void* color_mmap(size_t size, struct color_ioctl_cmd cmd, struct color_ioctl_offset offset);
2031 diff --git include/litmus.h include/litmus.h
2032 index f99ccec..f39feb6 100644
2033 --- include/litmus.h
2034 +++ include/litmus.h
2035 @@ -40,11 +40,21 @@ extern "C" {
2036  
2037  #include "migration.h"
2038  
2039 +#include "litmus/mc2_common.h"
2040 +
2041  /**
2042   * @private
2043   * Number of semaphore protocol object types
2044   */
2045 -#define SCHED_LITMUS 6
2046 +#define SCHED_LITMUS 7
2047 +
2048 +#define CACHELINE_SIZE 32
2049 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
2050 +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
2051 +typedef struct cacheline
2052 +{
2053 +        int line[INTS_IN_CACHELINE];
2054 +} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
2055  
2056  /**
2057   * Initialise a real-time task param struct
2058 @@ -146,6 +156,12 @@ int sporadic_clustered(lt_t e_ns, lt_t p_ns, int cluster);
2059  /** Convert microseconds to nanoseconds
2060    * @param us Time units in microseconds */
2061  #define us2ns(us) ((us)*1000LL)
2062 +#define ns2s(ns)  ((ns)/1000000000LL)
2063 +#define ns2ms(ns) ((ns)/1000000LL)
2064 +#define ns2us(ns) ((ns)/1000LL)
2065 +#define us2ms(us) ((us)/1000LL)
2066 +#define us2s(us)  ((us)/1000000LL)
2067 +#define ms2s(ms)  ((ms)/1000LL)
2068  
2069  /**
2070   * Locking protocols for allocated shared objects
2071 @@ -416,6 +432,19 @@ int null_call(cycles_t *timestamp);
2072   */
2073  struct control_page* get_ctrl_page(void);
2074  
2075 +int reservation_create(int rtype, void *config);
2076 +
2077 +int reservation_destroy(unsigned int reservation_id, int cpu);
2078 +
2079 +int set_mc2_task_param(pid_t pid, struct mc2_task* param);
2080 +
2081 +int set_page_color(int cpu);
2082 +
2083 +int test_call(unsigned int param);
2084 +
2085 +int run_bench(int type, int size, cacheline_t *src, cacheline_t *dst, lt_t __user *ts);
2086 +
2087 +int lock_buffer(void* addr, size_t size, unsigned int lock_way, unsigned int unlock_way); 
2088  #ifdef __cplusplus
2089  }
2090  #endif
2091 diff --git src/color_shm.c src/color_shm.c
2092 new file mode 100644
2093 index 0000000..8531445
2094 --- /dev/null
2095 +++ src/color_shm.c
2096 @@ -0,0 +1,40 @@
2097 +#include <sys/mman.h>
2098 +#include <stdio.h>
2099 +
2100 +#include "color_shm.h"
2101 +
2102 +void* color_mmap(size_t size, struct color_ioctl_cmd cmd, struct color_ioctl_offset offset)
2103 +{
2104 +	int ret, fd;
2105 +	void *mem;
2106 +	
2107 +	fd = open("/dev/litmus/color_shm", O_RDWR);
2108 +	if (fd < 0) {
2109 +		printf("Device open error.\n");
2110 +		return NULL;
2111 +	}
2112 +
2113 +	ret = ioctl(fd, SET_COLOR_SHM_CMD, &cmd);
2114 +	if (ret < 0) {
2115 +		printf("ioctl failed.\n");
2116 +		return NULL;
2117 +	}
2118 +	
2119 +	ret = ioctl(fd, SET_COLOR_SHM_OFFSET, &offset);
2120 +	if (ret < 0) {
2121 +		printf("ioctl failed.\n");
2122 +		return NULL;
2123 +	}
2124 +	
2125 +	size += offset.offset;
2126 +	mem = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
2127 +	if (mem == MAP_FAILED) {
2128 +		printf("mmap failed.\n");
2129 +		return MAP_FAILED;
2130 +	}
2131 +	close(fd);
2132 +	
2133 +	mem += offset.offset;
2134 +	
2135 +	return mem;
2136 +}
2137 \ No newline at end of file
2138 diff --git src/kernel_iface.c src/kernel_iface.c
2139 index ca874ff..a2c2104 100644
2140 --- src/kernel_iface.c
2141 +++ src/kernel_iface.c
2142 @@ -2,7 +2,7 @@
2143  #include <sys/fcntl.h> /* for O_RDWR */
2144  #include <sys/unistd.h>
2145  #include <sched.h> /* for sched_yield() */
2146 -
2147 +#include <assert.h>
2148  
2149  #include <stdio.h>
2150  
2151 diff --git src/syscalls.c src/syscalls.c
2152 index c68f15b..01ed57a 100644
2153 --- src/syscalls.c
2154 +++ src/syscalls.c
2155 @@ -86,3 +86,33 @@ int null_call(cycles_t *timestamp)
2156  {
2157  	return syscall(__NR_null_call, timestamp);
2158  }
2159 +
2160 +int reservation_create(int rtype, void *config)
2161 +{
2162 +	return syscall(__NR_reservation_create, rtype, config);
2163 +}
2164 +
2165 +int reservation_destroy(unsigned int reservation_id, int cpu)
2166 +{
2167 +	return syscall(__NR_reservation_destroy, reservation_id, cpu);
2168 +}
2169 +
2170 +int set_mc2_task_param(pid_t pid, struct mc2_task *param)
2171 +{
2172 +	return syscall(__NR_set_mc2_task_param, pid, param);
2173 +}
2174 +
2175 +int set_page_color(int cpu)
2176 +{
2177 +	return syscall(__NR_set_page_color, cpu);
2178 +}
2179 +
2180 +int run_bench(int type, int wss, cacheline_t *src, cacheline_t *dst, lt_t *ts)
2181 +{
2182 +	return syscall(__NR_run_test, type, wss, src, dst, ts);
2183 +}
2184 +
2185 +int lock_buffer(void* addr, size_t size, unsigned int lock_way, unsigned int unlock_way)
2186 +{
2187 +	return syscall(__NR_lock_buffer, addr, size, lock_way, unlock_way);
2188 +}
2189 

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

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