diff --git .gitignore .gitignore
index a52500b..ec913c5 100644
--- .gitignore
+++ .gitignore
@@ -3,10 +3,13 @@
 *.a
 
 
+# editor backup files
+*~
 
 # generated files
 tests/test_catalog.inc
 *.d
+*.d.*
 docs/
 
 # executables
@@ -23,6 +26,13 @@ showst
 rtspin
 cycles
 measure_syscall
+uncache
+resctrl
+mc2pollute
+mc2spin
+mc2syn
+memthrash
+mttest
 
 # build system files
 .config
@@ -32,3 +42,5 @@ test_catalog.inc
 # files copied in from the kernel tree
 include/litmus
 arch/*/include/asm
+arch/x86/include/generated
+arch/x86/include/uapi
diff --git Makefile Makefile
index 4742fd2..3e6ee15 100644
--- Makefile
+++ Makefile
@@ -19,7 +19,7 @@ LITMUS_KERNEL ?= ../litmus-rt
 # Internal configuration.
 
 # compiler flags
-flags-debug    = -O2 -Wall -Werror -g -Wdeclaration-after-statement
+flags-debug    = -O0 -Wall -g -Wdeclaration-after-statement
 flags-api      = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE
 
 # architecture-specific flags
@@ -73,11 +73,14 @@ AR  := ${CROSS_COMPILE}${AR}
 
 all     = lib ${rt-apps}
 rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
-	  base_mt_task uncache runtests
+	base_mt_task uncache runtests resctrl mc2mem \
+	mc2spin mtdag mode_request rt_mode_poll
+
+#mc2thrash mc2thrash1 mc2thrash2 mc2thrash3
 
 .PHONY: all lib clean dump-config TAGS tags cscope help doc
 
-all: ${all} inc/config.makefile
+all: ${all} inc/config.makefile post-build
 
 # Write a distilled version of the flags for clients of the library. Ideally,
 # this should depend on liblitmus.a, but that requires LIBLITMUS to be a
@@ -126,6 +129,7 @@ clean:
 	rm -f inc/config.makefile
 	rm -f tags TAGS cscope.files cscope.out
 	rm -r -f docs
+	rm -f mc2mem*
 
 # Emacs Tags
 TAGS:
@@ -143,6 +147,8 @@ cscope:
 	@find . -type f -and  -iname '*.[ch]' | xargs printf "%s\n" > cscope.files
 	@cscope -b
 
+post-build:
+	
 # ##############################################################################
 # Kernel headers.
 # The kernel does not like being #included directly, so let's
@@ -168,7 +174,8 @@ litmus-headers = \
 	include/litmus/rt_param.h \
 	include/litmus/fpmath.h \
 	include/litmus/unistd_32.h \
-	include/litmus/unistd_64.h
+	include/litmus/unistd_64.h \
+	include/litmus/mc2_common.h
 
 unistd-headers = \
   $(foreach file,${unistd-${ARCH}},arch/${include-${ARCH}}/include/$(file))
@@ -234,6 +241,22 @@ obj-release_ts = release_ts.o
 obj-measure_syscall = null_call.o
 lib-measure_syscall = -lm
 
+obj-resctrl = resctrl.o
+
+obj-mc2spin = mc2spin.o common.o
+lib-mc2spin = -lrt -static
+
+obj-mc2mem = mc2mem.o common.o
+lib-mc2mem = -lrt -static
+
+obj-mtdag = mtdag.o common.o
+ldf-mtdag = -lrt -pthread -static
+
+obj-mode_request = mode_request.o common.o
+lib-mode_request = -lrt -static
+
+obj-rt_mode_poll = rt_mode_poll.o common.o
+lib-rt_mode_poll = -lrt -static
 # ##############################################################################
 # Build everything that depends on liblitmus.
 
diff --git bin/base_mt_task.c bin/base_mt_task.c
index aec79a4..1665203 100644
--- bin/base_mt_task.c
+++ bin/base_mt_task.c
@@ -29,11 +29,13 @@
 /* Let's create 10 threads in the example, 
  * for a total utilization of 1.
  */
-#define NUM_THREADS      10 
+#define NUM_THREADS      3 
 
 /* The information passed to each thread. Could be anything. */
 struct thread_context {
 	int id;
+	int cpu;
+	int job_no;
 };
 
 /* The real-time thread program. Doesn't have to be the same for
@@ -45,7 +47,7 @@ void* rt_thread(void *tcontext);
  * Returns 1 -> task should exit.
  *         0 -> task should continue.
  */
-int job(void);
+int job(struct thread_context *tcx);
 
 
 /* Catch errors.
@@ -97,6 +99,8 @@ int main(int argc, char** argv)
 	 */
 	for (i = 0; i < NUM_THREADS; i++) {
 		ctx[i].id = i;
+		ctx[i].cpu = 0;
+		ctx[i].job_no = 0;
 		pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i));
 	}
 
@@ -125,6 +129,7 @@ void* rt_thread(void *tcontext)
 	int do_exit;
 	struct thread_context *ctx = (struct thread_context *) tcontext;
 	struct rt_task param;
+	int ret;
 
 	/* Set up task parameters */
 	init_rt_task_param(&param);
@@ -157,6 +162,12 @@ void* rt_thread(void *tcontext)
 	 * where CPU ranges from 0 to "Number of CPUs" - 1 before calling
 	 * set_rt_task_param().
 	 */
+	param.cpu = ctx->cpu;
+	ret = be_migrate_to_cpu(ctx->cpu);
+	if (ret < 0) {
+		printf("RT Thread %d fails to migrate to CPU%d\n", ctx->id, ctx->cpu);
+		return NULL;
+	}
 	CALL( set_rt_task_param(gettid(), &param) );
 
 	/*****
@@ -176,7 +187,7 @@ void* rt_thread(void *tcontext)
 		/* Wait until the next job is released. */
 		sleep_next_period();
 		/* Invoke job. */
-		do_exit = job();		
+		do_exit = job(ctx);		
 	} while (!do_exit);
 
 
@@ -192,10 +203,13 @@ void* rt_thread(void *tcontext)
 
 
 
-int job(void) 
+int job(struct thread_context *tcx) 
 {
 	/* Do real-time calculation. */
-
+	printf("Job executinig\n");
+	tcx->job_no++;
+	if (tcx->job_no == 5)
+		return 1;
 	/* Don't exit. */
 	return 0;
 }
diff --git bin/mc2mem.c bin/mc2mem.c
new file mode 100644
index 0000000..1087381
--- /dev/null
+++ bin/mc2mem.c
@@ -0,0 +1,326 @@
+#include <sys/time.h>
+#include <sys/mman.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <math.h>
+
+#include "litmus.h"
+#include "common.h"
+#include "cache_common.h"
+
+#define PAGE_SIZE (4096)
+#define CACHELINE_SIZE 32
+#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
+#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
+#define INTS_IN_1KB	(1024 / sizeof(int))
+#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
+
+static int loops = 100;
+static cacheline_t* arena = NULL;
+static int verbose = 0;
+
+struct timeval t1,t2;
+
+
+#define UNCACHE_DEV "/dev/litmus/uncache"
+
+/* Random walk around the arena in cacheline-sized chunks.
+   Cacheline-sized chucks ensures the same utilization of each
+   hit line as sequential read. (Otherwise, our utilization
+   would only be 1/INTS_IN_CACHELINE.) */
+static int random_walk(cacheline_t *mem, int wss, int write_cycle)
+{
+	/* a random cycle among the cache lines was set up by init_arena(). */
+	int sum, i, next;
+
+	int numlines = wss * CACHELINES_IN_1KB;
+
+	sum = 0;
+
+	/* contents of arena is structured s.t. offsets are all
+	   w.r.t. to start of arena, so compute the initial offset */
+	next = mem - arena;
+
+	if (write_cycle == 0) {
+		for (i = 0; i < numlines; i++) {
+			/* every element in the cacheline has the same value */
+			next = arena[next].line[0];
+			sum += next;
+		}
+	}
+	
+	else {
+		int w, which_line;
+		for (i = 0, w = 0; i < numlines; i++) {
+			which_line = next;
+			next = arena[next].line[0];
+			if((w % write_cycle) != (write_cycle - 1)) {
+				sum += next;
+			}
+			else {
+				((volatile cacheline_t*)arena)[which_line].line[0] = next;
+			}
+		}
+	}
+	return sum;
+}
+
+static cacheline_t* random_start(int wss)
+{
+	return arena + randrange(0, ((wss * 1024)/sizeof(cacheline_t)));
+}
+
+static volatile int dont_optimize_me = 0;
+
+static void usage(char *error) {
+	fprintf(stderr, "Error: %s\n", error);
+	fprintf(stderr,
+		"Usage:\n"
+		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
+		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
+		"	rt_spin -l\n"
+		"\n"
+		"COMMON-OPTS = [-w] [-s SCALE]\n"
+		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-m CRITICALITY LEVEL]\n"
+		"              [-k WSS] [-l LOOPS] [-b BUDGET]\n"
+		"\n"
+		"WCET and PERIOD are milliseconds, DURATION is seconds.\n");
+	exit(EXIT_FAILURE);
+}
+
+static int loop_once(int wss)
+{
+	cacheline_t *mem;
+	int temp;
+	
+	mem = random_start(wss);
+	temp = random_walk(mem, wss, 1);
+    
+	//mem = sequential_start(wss);
+	//temp = sequential_walk(mem, wss, 0);
+	dont_optimize_me = temp;
+	
+	return dont_optimize_me;
+}
+
+static int job(int wss, double exec_time, double program_end)
+{
+	if (wctime() > program_end)
+		return 0;
+	else {
+		register unsigned int iter = 0;
+		register cycles_t t;
+		t = get_cycles();
+		while(iter++ < loops) {
+			loop_once(wss);
+		}
+		t = get_cycles() - t;
+		if (verbose)
+			printf("%ld cycles\n", t);
+  		sleep_next_period(); 
+    	return 1;
+	}
+}
+
+#define OPTSTR "p:wl:m:i:b:k:vs:"
+int main(int argc, char** argv)
+{
+	int ret, i;
+	lt_t wcet, period, budget;
+	double wcet_ms, period_ms, budget_ms;
+	unsigned int priority = LITMUS_NO_PRIORITY;
+	int migrate = 0;
+	int cluster = 0;
+	int opt;
+	int wait = 0;
+	double duration = 0, start = 0;
+	struct rt_task param;
+	struct mc2_task mc2_param;
+	struct reservation_config config;
+	int res_type = PERIODIC_POLLING;
+	size_t arena_sz;
+	int wss = 1;
+	uint32_t mode_mask;
+
+	/* default for reservation */
+	config.id = 0;
+	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
+	config.cpu = -1;
+	
+	mc2_param.crit = CRIT_LEVEL_C;
+	
+	budget_ms = 1000;
+	
+	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
+		switch (opt) {
+		case 'w':
+			wait = 1;
+			break;
+		case 'p':
+			cluster = atoi(optarg);
+			migrate = 1;
+			config.cpu = cluster;
+			break;
+		case 'l':
+			loops = atoi(optarg);
+			break;
+		case 's':
+			wss = atoi(optarg);
+			break;
+		case 'k':
+			mode_mask = atoi(optarg);
+			break;
+		case 'm':
+			mc2_param.crit = atoi(optarg);
+			if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
+				res_type = PERIODIC_POLLING;
+			}
+			else
+				usage("Invalid criticality level.");
+			break;
+		case 'b':
+			budget_ms = atof(optarg);
+			break;
+		case 'i':
+			config.priority = atoi(optarg);
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case ':':
+			usage("Argument missing.");
+			break;
+		case '?':
+		default:
+			usage("Bad argument.");
+			break;
+		}
+	}
+	srand(getpid());
+
+	/*
+	 * We need three parameters
+	 */
+	if (argc - optind < 3)
+		usage("Arguments missing.");
+
+	wcet_ms   = atof(argv[optind + 0]);
+	period_ms = atof(argv[optind + 1]);
+
+	wcet   = ms2ns(wcet_ms);
+	period = ms2ns(period_ms);
+	budget = ms2ns(budget_ms);
+	if (wcet <= 0)
+		usage("The worst-case execution time must be a "
+				"positive number.");
+	if (period <= 0)
+		usage("The period must be a positive number.");
+	if (wcet > period) {
+		usage("The worst-case execution time must not "
+				"exceed the period.");
+	}
+	if (wss == 0) {
+		usage("You need to specify a WSS (-k option).");
+	}
+
+	duration  = atof(argv[optind + 2]);
+	
+	if (migrate) {
+		ret = be_migrate_to_domain(cluster);
+		if (ret < 0)
+			bail_out("could not migrate to target partition or cluster.");
+	}
+
+	/* reservation config */
+	config.id = gettid();
+	config.polling_params.budget = budget;
+	config.polling_params.period = period;
+	config.polling_params.offset = 0;
+	config.polling_params.relative_deadline = 0;
+	
+	if (config.polling_params.budget > config.polling_params.period) {
+		usage("The budget must not exceed the period.");
+	}
+	
+	/* create a reservation */
+	for(i = 0; i < 32; i++){
+		if ( !( (1 << i) & mode_mask) )
+			continue;
+		config.mode = i;
+		ret = reservation_create(res_type, &config);
+		if (ret < 0) {
+			bail_out("failed to create reservation.");
+		}
+	}
+	
+	init_rt_task_param(&param);
+	param.exec_cost = wcet;
+	param.period = period;
+	param.priority = priority;
+	param.cls = RT_CLASS_HARD;
+	param.release_policy = TASK_PERIODIC;
+	param.budget_policy = NO_ENFORCEMENT;
+	if (migrate) {
+		param.cpu = gettid();
+		//param.cpu = config.cpu;
+	}
+	ret = set_rt_task_param(gettid(), &param);
+	if (ret < 0)
+		bail_out("could not setup rt task params");
+	
+	mc2_param.res_id = gettid();
+	mc2_param.mode_mask = mode_mask;
+	ret = set_mc2_task_param(gettid(), &mc2_param);
+	if (ret < 0)
+		bail_out("could not setup mc2 task params");
+	
+	arena_sz = wss*1024;
+	arena = alloc_arena(arena_sz, 0, 0);
+	init_arena(arena, arena_sz);
+	
+	mlockall(MCL_CURRENT | MCL_FUTURE);
+	
+	ret = init_litmus();
+	if (ret != 0)
+		bail_out("init_litmus() failed\n");
+
+	start = wctime();
+	ret = task_mode(LITMUS_RT_TASK);
+	if (ret != 0)
+		bail_out("could not become RT task");
+
+	if (mc2_param.crit == CRIT_LEVEL_C)
+		set_page_color(-1);
+	else
+		set_page_color(config.cpu);
+
+	mlockall(MCL_CURRENT | MCL_FUTURE);
+	
+	if (wait) {
+		ret = wait_for_ts_release();
+		if (ret != 0)
+			bail_out("wait_for_ts_release()");
+		start = wctime();
+	}
+
+	while (job(wss, wcet_ms * 0.001, start + duration)) {};
+
+//set_page_color(config.cpu);
+	//test_call(0);
+	ret = task_mode(BACKGROUND_TASK);
+	if (ret != 0)
+		bail_out("could not become regular task (huh?)");
+
+	reservation_destroy(gettid(), config.cpu);
+	dealloc_arena(arena, arena_sz);
+	printf("%s finished.\n", argv[0]);
+	//test_call(1);
+	return 0;
+}
diff --git bin/mc2spin.c bin/mc2spin.c
new file mode 100644
index 0000000..dfb5c80
--- /dev/null
+++ bin/mc2spin.c
@@ -0,0 +1,545 @@
+#include <sys/time.h>
+#include <sys/mman.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#include "litmus.h"
+#include "common.h"
+
+#define PAGE_SIZE 4096
+
+static void usage(char *error) {
+	fprintf(stderr, "Error: %s\n", error);
+	fprintf(stderr,
+		"Usage:\n"
+		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
+		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
+		"	rt_spin -l\n"
+		"\n"
+		"COMMON-OPTS = [-w] [-s SCALE]\n"
+		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
+		"              [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
+		"              [-i [start,end]:[start,end]...]\n"
+		"\n"
+		"WCET and PERIOD are milliseconds, DURATION is seconds.\n"
+		"CRITICAL SECTION LENGTH is in milliseconds.\n");
+	exit(EXIT_FAILURE);
+}
+
+/*
+ * returns the character that made processing stop, newline or EOF
+ */
+static int skip_to_next_line(FILE *fstream)
+{
+	int ch;
+	for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
+	return ch;
+}
+
+static void skip_comments(FILE *fstream)
+{
+	int ch;
+	for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
+		skip_to_next_line(fstream);
+	ungetc(ch, fstream);
+}
+
+static void get_exec_times(const char *file, const int column,
+			   int *num_jobs,    double **exec_times)
+{
+	FILE *fstream;
+	int  cur_job, cur_col, ch;
+	*num_jobs = 0;
+
+	fstream = fopen(file, "r");
+	if (!fstream)
+		bail_out("could not open execution time file");
+
+	/* figure out the number of jobs */
+	do {
+		skip_comments(fstream);
+		ch = skip_to_next_line(fstream);
+		if (ch != EOF)
+			++(*num_jobs);
+	} while (ch != EOF);
+
+	if (-1 == fseek(fstream, 0L, SEEK_SET))
+		bail_out("rewinding file failed");
+
+	/* allocate space for exec times */
+	*exec_times = calloc(*num_jobs, sizeof(*exec_times));
+	if (!*exec_times)
+		bail_out("couldn't allocate memory");
+
+	for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
+
+		skip_comments(fstream);
+
+		for (cur_col = 1; cur_col < column; ++cur_col) {
+			/* discard input until we get to the column we want */
+			int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
+		}
+
+		/* get the desired exec. time */
+		if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
+			fprintf(stderr, "invalid execution time near line %d\n",
+					cur_job);
+			exit(EXIT_FAILURE);
+		}
+
+		skip_to_next_line(fstream);
+	}
+
+	assert(cur_job == *num_jobs);
+	fclose(fstream);
+}
+
+#define NUMS 16
+static int num[NUMS];
+static char* progname;
+
+static int loop_once(void)
+{
+	int i, j = 0;
+	for (i = 0; i < NUMS; i++)
+		j += num[i];
+	return j;
+}
+
+static int loop_for(double exec_time, double emergency_exit)
+{
+	double last_loop = 0, loop_start;
+	int tmp = 0;
+
+	double start = cputime();
+	double now = cputime();
+
+	while (now + last_loop < start + exec_time) {
+		loop_start = now;
+		tmp += loop_once();
+		now = cputime();
+		last_loop = now - loop_start;
+		if (emergency_exit && wctime() > emergency_exit) {
+			/* Oops --- this should only be possible if the execution time tracking
+			 * is broken in the LITMUS^RT kernel. */
+			fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
+			fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
+			break;
+		}
+	}
+
+	return tmp;
+}
+
+
+static void debug_delay_loop(int count)
+{
+	double start, end, delay;
+
+	while (count--) {
+		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
+			start = wctime();
+			loop_for(delay, 0);
+			end = wctime();
+			printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
+			       delay,
+			       end - start,
+			       end - start - delay,
+			       100 * (end - start - delay) / delay);
+		}
+	}
+}
+
+static int job(double exec_time, double program_end, int lock_od, double cs_length)
+{
+	double chunk1, chunk2;
+
+	if (wctime() > program_end)
+		return 0;
+	else {
+		if (lock_od >= 0) {
+			/* simulate critical section somewhere in the middle */
+			chunk1 = drand48() * (exec_time - cs_length);
+			chunk2 = exec_time - cs_length - chunk1;
+
+			/* non-critical section */
+			loop_for(chunk1, program_end + 1);
+
+			/* critical section */
+			litmus_lock(lock_od);
+			loop_for(cs_length, program_end + 1);
+			litmus_unlock(lock_od);
+
+			/* non-critical section */
+			loop_for(chunk2, program_end + 2);
+		} else {
+			loop_for(exec_time, program_end + 1);
+		}
+		sleep_next_period();
+		return 1;
+	}
+}
+
+struct lt_interval* parse_td_intervals(int num, char* optarg, unsigned int *num_intervals)
+{
+	int i, matched;
+	struct lt_interval *slots = malloc(sizeof(slots[0]) * num);
+	char** arg = (char**)malloc(sizeof(char*) * num);
+	char *token, *saveptr;
+	double start, end;
+	
+	for (i = 0; i < num; i++) {
+		arg[i] = (char*)malloc(sizeof(char)*100);
+	}
+	
+	i = 0;
+	token = strtok_r(optarg, ":", &saveptr);
+	while(token != NULL) {
+		sprintf(arg[i++], "%s", token);
+		token = strtok_r(NULL, ":", &saveptr);
+	}
+	
+	*num_intervals = 0;
+	
+	for (i=0; i<num; i++) {
+		matched = sscanf(arg[i], "[%lf,%lf]", &start, &end);
+		if (matched != 2) {
+			fprintf(stderr, "could not parse '%s' as interval\n", arg[i]);
+			exit(5);
+		}
+		if (start < 0) {
+			fprintf(stderr, "interval %s: must not start before zero\n", arg[i]);
+			exit(5);
+		}
+		if (end <= start) {
+			fprintf(stderr, "interval %s: end before start\n", arg[i]);
+			exit(5);
+		}
+
+		slots[i].start = ms2ns(start);
+		slots[i].end   = ms2ns(end);
+
+		if (i > 0 && slots[i - 1].end >= slots[i].start) {
+			fprintf(stderr, "interval %s: overlaps with previous interval\n", arg[i]);
+			exit(5);
+		}
+
+		(*num_intervals)++;
+	}
+	
+	for (i=0; i<num; i++) {
+		free(arg[i]);
+	}
+	free(arg);
+	return slots;
+}
+
+#define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:vh:m:i:b:k:"
+int main(int argc, char** argv)
+{
+	int ret;
+	lt_t wcet;
+	lt_t period;
+	lt_t hyperperiod;
+	lt_t budget;
+	double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
+	unsigned int priority = LITMUS_NO_PRIORITY;
+	int migrate = 0;
+	int cluster = 0;
+	int opt;
+	int wait = 0;
+	int test_loop = 0;
+	int column = 1;
+	const char *file = NULL;
+	int want_enforcement = 0;
+	double duration = 0, start = 0;
+	double *exec_times = NULL;
+	double scale = 1.0;
+	task_class_t class = RT_CLASS_HARD;
+	int cur_job = 0, num_jobs = 0;
+	struct rt_task param;
+	struct mc2_task mc2_param;
+	struct reservation_config config;
+	int res_type = PERIODIC_POLLING;
+	int i;
+	uint32_t mode_mask;
+
+	int verbose = 0;
+	unsigned int job_no;
+
+	/* locking */
+	int lock_od = -1;
+	int resource_id = 0;
+	const char *lock_namespace = "./rtspin-locks";
+	int protocol = -1;
+	double cs_length = 1; /* millisecond */
+
+	progname = argv[0];
+
+	/* default for reservation */
+	config.id = 0;
+	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
+	config.cpu = -1;
+	
+	mc2_param.crit = CRIT_LEVEL_C;
+	
+	hyperperiod_ms = 1000;
+	budget_ms = 10;
+	
+	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
+		switch (opt) {
+		case 'w':
+			wait = 1;
+			break;
+		case 'p':
+			cluster = atoi(optarg);
+			migrate = 1;
+			config.cpu = cluster;
+			break;
+		case 'q':
+			priority = atoi(optarg);
+			if (!litmus_is_valid_fixed_prio(priority))
+				usage("Invalid priority.");
+			break;
+		case 'c':
+			class = str2class(optarg);
+			if (class == -1)
+				usage("Unknown task class.");
+			break;
+		case 'e':
+			want_enforcement = 1;
+			break;
+		case 'l':
+			test_loop = 1;
+			break;
+		case 'o':
+			column = atoi(optarg);
+			break;
+		case 'f':
+			file = optarg;
+			break;
+		case 's':
+			scale = atof(optarg);
+			break;
+		case 'X':
+			protocol = lock_protocol_for_name(optarg);
+			if (protocol < 0)
+				usage("Unknown locking protocol specified.");
+			break;
+		case 'L':
+			cs_length = atof(optarg);
+			if (cs_length <= 0)
+				usage("Invalid critical section length.");
+			break;
+		case 'Q':
+			resource_id = atoi(optarg);
+			if (resource_id <= 0 && strcmp(optarg, "0"))
+				usage("Invalid resource ID.");
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case 'm':
+			mc2_param.crit = atoi(optarg);
+			if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
+				usage("Invalid criticality level.");
+			}
+			res_type = PERIODIC_POLLING;
+			break;
+		case 'h':
+			hyperperiod_ms = atof(optarg);
+			break;
+		case 'b':
+			budget_ms = atof(optarg);
+			break;
+		case 'i':
+			config.priority = atoi(optarg);
+			break;
+		case 'k':
+			mode_mask = atoi(optarg);
+			break;
+		case ':':
+			usage("Argument missing.");
+			break;
+		case '?':
+		default:
+			usage("Bad argument.");
+			break;
+		}
+	}
+
+	if (test_loop) {
+		debug_delay_loop(1);
+		return 0;
+	}
+
+	if (mc2_param.crit == CRIT_LEVEL_A && config.priority == LITMUS_NO_PRIORITY)
+		usage("Bad criticailty level or priority");
+	if (mc2_param.crit == CRIT_LEVEL_B) {
+		config.priority = LITMUS_NO_PRIORITY;
+	}
+	
+	if (mc2_param.crit == CRIT_LEVEL_C) {
+		config.priority = LITMUS_NO_PRIORITY;
+		config.cpu = -1;
+	}
+
+	srand(getpid());
+
+	if (file) {
+		get_exec_times(file, column, &num_jobs, &exec_times);
+
+		if (argc - optind < 2)
+			usage("Arguments missing.");
+
+		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
+			/* convert the execution time to seconds */
+			duration += exec_times[cur_job] * 0.001;
+		}
+	} else {
+		/*
+		 * if we're not reading from the CSV file, then we need
+		 * three parameters
+		 */
+		if (argc - optind < 3)
+			usage("Arguments missing.");
+	}
+
+	wcet_ms   = atof(argv[optind + 0]);
+	period_ms = atof(argv[optind + 1]);
+
+	wcet   = ms2ns(wcet_ms);
+	period = ms2ns(period_ms);
+	budget = ms2ns(budget_ms);
+	hyperperiod = ms2ns(hyperperiod_ms);
+	
+	if (wcet <= 0)
+		usage("The worst-case execution time must be a "
+				"positive number.");
+	if (period <= 0)
+		usage("The period must be a positive number.");
+	if (!file && wcet > period) {
+		usage("The worst-case execution time must not "
+				"exceed the period.");
+	}
+
+	if (!file)
+		duration  = atof(argv[optind + 2]);
+	else if (file && num_jobs > 1)
+		duration += period_ms * 0.001 * (num_jobs - 1);
+
+	if (migrate) {
+		ret = be_migrate_to_domain(cluster);
+		if (ret < 0)
+			bail_out("could not migrate to target partition or cluster.");
+	}
+
+	/* reservation config */
+	config.id = gettid();
+	
+	if (hyperperiod%period != 0 ) {
+		;//bail_out("hyperperiod must be multiple of period");
+	}
+	
+	config.polling_params.budget = budget;
+	config.polling_params.period = period;
+	config.polling_params.offset = 0;
+	config.polling_params.relative_deadline = 0;
+	if (config.polling_params.budget > config.polling_params.period) {
+		usage("The budget must not exceed the period.");
+	}
+	/* create a reservation */
+	for(i = 0; i < 32; i++){
+		if ( !( (1 << i) & mode_mask) )
+			continue;
+		config.mode = i;
+		ret = reservation_create(res_type, &config);
+		if (ret < 0) {
+			bail_out("failed to create reservation.");
+		}
+	}
+	
+	init_rt_task_param(&param);
+	param.exec_cost = wcet;
+	param.period = period;
+	param.priority = priority;
+	param.cls = class;
+	param.release_policy = TASK_PERIODIC;
+	param.budget_policy = (want_enforcement) ?
+			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
+	if (migrate) {
+		param.cpu = gettid();
+	}
+	ret = set_rt_task_param(gettid(), &param);
+//printf("SET_RT_TASK\n");
+	if (ret < 0)
+		bail_out("could not setup rt task params");
+	
+	mc2_param.res_id = gettid();
+	mc2_param.mode_mask = mode_mask;
+	ret = set_mc2_task_param(gettid(), &mc2_param);
+//printf("SET_MC2_TASK\n");
+	if (ret < 0)
+		bail_out("could not setup mc2 task params");
+
+	init_litmus();
+
+//printf("INIT_LITMUS\n");
+	start = wctime();
+	ret = task_mode(LITMUS_RT_TASK);
+//printf("TASK_MODE\n");
+	set_page_color(config.cpu);
+	if (ret != 0)
+		bail_out("could not become RT task");
+
+	if (protocol >= 0) {
+		lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
+		if (lock_od < 0) {
+			perror("litmus_open_lock");
+			usage("Could not open lock.");
+		}
+	}
+
+
+	if (wait) {
+//printf("BEFORE WAIT\n");
+		ret = wait_for_ts_release();
+		if (ret != 0)
+			bail_out("wait_for_ts_release()");
+		start = wctime();
+	}
+
+	if (file) {
+		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
+			job(exec_times[cur_job] * 0.001 * scale,
+			    start + duration,
+			    lock_od, cs_length * 0.001);
+		}
+	} else {
+		do {
+			if (verbose) {
+				get_job_no(&job_no);
+				printf("rtspin/%d:%u @ %.4fms\n", gettid(),
+					job_no, (wctime() - start) * 1000);
+			}
+		} while (job(wcet_ms * 0.001 * scale, start + duration,
+			   lock_od, cs_length * 0.001));
+	}
+	ret = task_mode(BACKGROUND_TASK);
+	if (ret != 0)
+		bail_out("could not become regular task (huh?)");
+
+	if (file)
+		free(exec_times);
+
+	reservation_destroy(gettid(), config.cpu);
+	
+	return 0;
+}
diff --git bin/mode_request.c bin/mode_request.c
new file mode 100644
index 0000000..010add1
--- /dev/null
+++ bin/mode_request.c
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "litmus.h"
+
+#define __NR_request_mode 408
+
+static int keep_running;
+
+void sig_handler(int signum) {
+	int ret;
+
+	usleep(100000);
+	ret = syscall(__NR_request_mode, 0);
+	usleep(1000000);
+	keep_running = 0;
+	
+}
+
+int main(int argc, char* argv[]) {
+	int ret, req_mode = 0;
+	int interval_ms;
+	int max_mode = 9;
+	
+	signal(SIGINT, sig_handler);
+	
+	if (argc == 2) {
+		max_mode = atoi(argv[1]);
+		printf("%d\n", max_mode);
+	}
+	
+	keep_running = 1;
+	usleep(500000); // ms 
+	while (keep_running) {
+		req_mode = (req_mode%max_mode)+1;
+		
+		if (keep_running)
+			ret = syscall(__NR_request_mode, req_mode);
+		interval_ms = rand() % 1000 - 500;  // ms
+		usleep(1000*(1000 + interval_ms));
+	}
+	
+	
+	return ret;
+} 
diff --git bin/mode_skeleton.c bin/mode_skeleton.c
new file mode 100644
index 0000000..cae5851
--- /dev/null
+++ bin/mode_skeleton.c
@@ -0,0 +1,256 @@
+#include <sys/time.h>
+#include <sys/mman.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#include "litmus.h"
+#include "common.h"
+
+extern int main_job(void);
+
+static char* progname;
+int loops = 10;
+//struct timeval t1, t2;
+
+static void usage(char *error) {
+	fprintf(stderr, "Error: %s\n", error);
+	fprintf(stderr,
+		"Usage:\n"
+		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
+		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
+		"	rt_spin -l\n"
+		"\n"
+		"COMMON-OPTS = [-w] [-s SCALE]\n"
+		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
+		"\n"
+		"WCET and PERIOD are microseconds, DURATION is seconds.\n");
+	exit(EXIT_FAILURE);
+}
+
+inline unsigned long get_cyclecount (void)
+{
+	unsigned long value;
+	// Read CCNT Register
+	asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
+	return value;
+}
+
+static int job(double exec_time, double program_end)
+{
+	if (wctime() > program_end)
+		return 0;
+	else {
+		register int iter = 0;
+		//register unsigned long t;
+		//t = get_cyclecount();
+		//gettimeofday(&t1, NULL);
+		while (iter++ < loops) {
+			main_job();
+		}
+		//t = get_cyclecount() - t;
+		//printf("%ld cycles\n", t);
+		//gettimeofday(&t2, NULL);
+		//printf("%ld us\n", ((t2.tv_sec * 1000000 + t2.tv_usec) - (t1.tv_sec * 1000000 + t1.tv_usec)));
+		sleep_next_period();
+		return 1;
+	}
+}
+
+#define OPTSTR "p:wves:l:m:i:b:k:"
+int main(int argc, char** argv)
+{
+	int ret;
+	lt_t wcet;
+	lt_t period;
+	lt_t budget;
+	double wcet_us, period_us, budget_us;
+	unsigned int priority = LITMUS_NO_PRIORITY;
+	int migrate = 0;
+	int cluster = 0;
+	int opt;
+	int wait = 0;
+	int want_enforcement = 0;
+	double duration = 0, start = 0;
+	double scale = 1.0;
+	task_class_t class = RT_CLASS_HARD;
+	struct rt_task param;
+	struct mc2_task mc2_param;
+	struct reservation_config config;
+	int res_type = PERIODIC_POLLING;
+	uint32_t mode_mask = (1 << 0);
+	int i;
+	unsigned int job_no;
+
+
+	progname = argv[0];
+
+	/* default for reservation */
+	config.id = 0;
+	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
+	config.cpu = -1;
+	
+	mc2_param.crit = CRIT_LEVEL_C;
+	
+	budget_us = 10000;
+
+	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
+		switch (opt) {
+		case 'w':
+			wait = 1;
+			break;
+		case 'p':
+			cluster = atoi(optarg);
+			migrate = 1;
+			config.cpu = cluster;
+			break;
+		case 'e':
+			want_enforcement = 1;
+			break;
+		case 's':
+			scale = atof(optarg);
+			break;
+		case 'l':
+			loops = atoi(optarg);
+			break;
+		case 'm':
+			mc2_param.crit = atoi(optarg);
+			if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
+				usage("Invalid criticality level.");
+			}
+			res_type = PERIODIC_POLLING;
+			break;
+		case 'b':
+			budget_us = atof(optarg);
+			break;
+		case 'i':
+			config.priority = atoi(optarg);
+			break;
+		case 'k':
+			mode_mask = atoi(optarg);
+		case ':':
+			usage("Argument missing.");
+			break;
+		case '?':
+		default:
+			usage("Bad argument.");
+			break;
+		}
+	}
+
+	if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
+		usage("Bad criticailty level or priority");
+
+	if (argc - optind < 3)
+		usage("Arguments missing.");
+
+	wcet_us   = atof(argv[optind + 0]);
+	period_us = atof(argv[optind + 1]);
+
+	wcet   = us2ns(wcet_us);
+	period = us2ns(period_us);
+	budget = us2ns(budget_us);
+	
+	if (wcet <= 0)
+		usage("The worst-case execution time must be a "
+				"positive number.");
+	if (period <= 0)
+		usage("The period must be a positive number.");
+	if (wcet > period) {
+		usage("The worst-case execution time must not "
+				"exceed the period.");
+	}
+
+	duration  = atof(argv[optind + 2]);
+
+	if (migrate) {
+		ret = be_migrate_to_domain(cluster);
+		if (ret < 0)
+			bail_out("could not migrate to target partition or cluster.");
+	}
+
+	/* reservation config */
+	config.id = gettid();
+	
+	config.polling_params.budget = budget;
+	config.polling_params.period = period;
+	config.polling_params.offset = 0;
+	config.polling_params.relative_deadline = 0;
+	if (config.polling_params.budget > config.polling_params.period) {
+		usage("The budget must not exceed the period.");
+	}
+	
+	/* create reservations */
+	for(i = 0; i < 32; i++){
+		if ( !((1 << i) & mode_mask ) )
+			continue;
+		config.mode = i;
+		ret = reservation_create(res_type, &config);
+		if (ret < 0) {
+			bail_out("failed to create reservation.");
+		}
+	}
+	
+	init_rt_task_param(&param);
+	param.exec_cost = wcet;
+	param.period = period;
+	param.priority = priority;
+	param.cls = class;
+	param.release_policy = TASK_PERIODIC;
+	param.budget_policy = (want_enforcement) ?
+			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
+	if (migrate) {
+		param.cpu = gettid();
+	}
+	ret = set_rt_task_param(gettid(), &param);
+	
+	if (ret < 0)
+		bail_out("could not setup rt task params");
+	
+	mc2_param.res_id = gettid();
+	mc2_param.mode_mask = mode_mask;
+	ret = set_mc2_task_param(gettid(), &mc2_param);
+//printf("SET_MC2_TASK\n");
+	if (ret < 0)
+		bail_out("could not setup mc2 task params");
+
+	init_litmus();
+//printf("CALL\n");
+	if (mc2_param.crit == CRIT_LEVEL_C)
+		set_page_color(8);
+	else if (mc2_param.crit < CRIT_LEVEL_C)
+		set_page_color(config.cpu*2 + mc2_param.crit);
+//printf("CALL\n");
+
+//printf("INIT_LITMUS\n");
+	start = wctime();
+	ret = task_mode(LITMUS_RT_TASK);
+//printf("TASK_MODE\n");
+	if (ret != 0)
+		bail_out("could not become RT task");
+
+
+	if (wait) {
+//printf("BEFORE WAIT\n");
+		ret = wait_for_ts_release();
+		if (ret != 0)
+			bail_out("wait_for_ts_release()");
+		start = wctime();
+	}
+
+	while (job(wcet_us * 0.000001 * scale, start + duration)) {};
+
+	ret = task_mode(BACKGROUND_TASK);
+	if (ret != 0)
+		bail_out("could not become regular task (huh?)");
+
+	reservation_destroy(gettid(), config.cpu);
+	printf("%s/%d finished.\n",progname, gettid());	
+	return 0;
+}
diff --git bin/mtdag.c bin/mtdag.c
new file mode 100644
index 0000000..adf6d8d
--- /dev/null
+++ bin/mtdag.c
@@ -0,0 +1,291 @@
+/* based_mt_task.c -- A basic multi-threaded real-time task skeleton. 
+ *
+ * This (by itself useless) task demos how to setup a multi-threaded LITMUS^RT
+ * real-time task. Familiarity with the single threaded example (base_task.c)
+ * is assumed.
+ *
+ * Currently, liblitmus still lacks automated support for real-time
+ * tasks, but internaly it is thread-safe, and thus can be used together
+ * with pthreads.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+/* Include gettid() */
+#include <sys/types.h>
+
+/* Include threading support. */
+#include <pthread.h>
+
+/* Include the LITMUS^RT API.*/
+#include "litmus.h"
+#include "color_shm.h"
+#include "asm/cycles.h"
+
+#define PERIOD            100
+#define RELATIVE_DEADLINE 100
+#define EXEC_COST         10
+
+/* Let's create 10 threads in the example, 
+ * for a total utilization of 1.
+ */
+#define NUM_THREADS      2 
+
+/* The information passed to each thread. Could be anything. */
+struct thread_context {
+	int id;
+	int cpu;
+	int job_no;
+	char* shm1;
+	char* shm2;
+	char* shm3;
+};
+
+/* The real-time thread program. Doesn't have to be the same for
+ * all threads. Here, we only have one that will invoke job().
+ */
+void* rt_thread(void *tcontext);
+
+/* Declare the periodically invoked job. 
+ * Returns 1 -> task should exit.
+ *         0 -> task should continue.
+ */
+int job(struct thread_context *tcx);
+
+
+/* Catch errors.
+ */
+#define CALL( exp ) do { \
+		int ret; \
+		ret = exp; \
+		if (ret != 0) \
+			fprintf(stderr, "%s failed: %m\n", #exp);\
+		else \
+			fprintf(stderr, "%s ok.\n", #exp); \
+	} while (0)
+
+
+/* Basic setup is the same as in the single-threaded example. However, 
+ * we do some thread initiliazation first before invoking the job.
+ */
+int main(int argc, char** argv)
+{
+	int i;
+	struct thread_context ctx[NUM_THREADS];
+	pthread_t             task[NUM_THREADS];
+	char *shm1;
+	char *shm2;
+	char *shm3;
+	struct color_ioctl_cmd shm_info;
+	struct color_ioctl_offset shm_offset;
+	/* The task is in background mode upon startup. */		
+
+
+	/*****
+	 * 1) Command line paramter parsing would be done here.
+	 */
+
+
+       
+	/*****
+	 * 2) Work environment (e.g., global data structures, file data, etc.) would
+	 *    be setup here.
+	 */
+
+	shm_info.color = 0x00000001;
+	shm_info.bank = 0x00000020;
+	shm_offset.offset = 0;
+	shm_offset.lock = 1;
+	
+	shm1 = (char*)color_mmap(1024, shm_info, shm_offset);
+	if (!shm1) {
+		printf("color mmap failed.\n");
+		exit(-1);
+	}
+	else {
+		printf("Mapped vaddr = %p\n", shm1);
+	}
+
+	shm_info.color = 0x00000003;
+	shm_offset.offset = 1024;
+	shm2 = (char*)color_mmap(4096, shm_info, shm_offset);
+	if (!shm2) {
+                printf("color mmap failed.\n");
+                exit(-1);
+        }
+        else {
+                printf("Mapped vaddr = %p\n", shm2);
+	}
+
+	mlockall(MCL_CURRENT | MCL_FUTURE);
+	/*****
+	 * 3) Initialize LITMUS^RT.
+	 *    Task parameters will be specified per thread.
+	 */
+	init_litmus();
+
+
+	/***** 
+	 * 4) Launch threads.
+	 */
+	for (i = 0; i < NUM_THREADS; i++) {
+		ctx[i].id = i;
+		ctx[i].cpu = 0;
+		ctx[i].job_no = 0;
+		ctx[i].shm1 = shm1;
+		ctx[i].shm3 = shm2;
+		ctx[i].shm2 = shm3;
+		pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i));
+	}
+
+	
+	/*****
+	 * 5) Wait for RT threads to terminate.
+	 */
+	for (i = 0; i < NUM_THREADS; i++)
+		pthread_join(task[i], NULL);
+	
+
+	/***** 
+	 * 6) Clean up, maybe print results and stats, and exit.
+	 */
+	return 0;
+}
+
+
+
+/* A real-time thread is very similar to the main function of a single-threaded
+ * real-time app. Notice, that init_rt_thread() is called to initialized per-thread
+ * data structures of the LITMUS^RT user space libary.
+ */
+void* rt_thread(void *tcontext)
+{
+	int do_exit;
+	struct thread_context *ctx = (struct thread_context *) tcontext;
+	struct rt_task param;
+	int ret;
+	struct mc2_task mc2_param;
+	struct reservation_config res_config;
+
+	/* Set up task parameters */
+	init_rt_task_param(&param);
+	param.exec_cost = ms2ns(EXEC_COST);
+	param.period = ms2ns(PERIOD);
+	param.relative_deadline = ms2ns(RELATIVE_DEADLINE*(ctx->id+1));
+
+	/* What to do in the case of budget overruns? */
+	param.budget_policy = NO_ENFORCEMENT;
+
+	/* The task class parameter is ignored by most plugins. */
+	param.cls = RT_CLASS_SOFT;
+
+	/* The priority parameter is only used by fixed-priority plugins. */
+	param.priority = LITMUS_LOWEST_PRIORITY;
+
+	/* Make presence visible. */
+	printf("RT Thread %d active.\n", ctx->id);
+
+	/* reservation config */
+	res_config.id = gettid();
+	res_config.polling_params.budget = ms2ns(EXEC_COST+1);
+	res_config.polling_params.period = param.period;
+	res_config.polling_params.offset = 0;
+	res_config.polling_params.relative_deadline = 0;
+	res_config.priority = LITMUS_MAX_PRIORITY;
+	res_config.cpu = ctx->cpu;
+	mc2_param.crit = CRIT_LEVEL_A;
+	mc2_param.res_id = gettid();
+	/*****
+	 * 1) Initialize real-time settings.
+	 */
+	CALL( init_rt_thread() );
+
+	ret = reservation_create(PERIODIC_POLLING, &res_config);
+	if (ret < 0) {
+		printf("reservation failed.\n");
+		return NULL;
+	}
+	
+	/* To specify a partition, do
+	 *
+	 * param.cpu = CPU;
+	 * be_migrate_to(CPU);
+	 *
+	 * where CPU ranges from 0 to "Number of CPUs" - 1 before calling
+	 * set_rt_task_param().
+	 */
+	param.cpu = ctx->cpu;
+	ret = be_migrate_to_cpu(ctx->cpu);
+	if (ret < 0) {
+		printf("RT Thread %d fails to migrate to CPU%d\n", ctx->id, ctx->cpu);
+		return NULL;
+	}
+	CALL( set_rt_task_param(gettid(), &param) );
+
+	CALL( set_mc2_task_param(gettid(), &mc2_param) );
+	/*****
+	 * 2) Transition to real-time mode.
+	 */
+	CALL( task_mode(LITMUS_RT_TASK) );
+
+	/* The task is now executing as a real-time task if the call didn't fail. 
+	 */
+
+
+
+	/*****
+	 * 3) Invoke real-time jobs.
+	 */
+	do {
+		/* Wait until the next job is released. */
+		sleep_next_period();
+		/* Invoke job. */
+		do_exit = job(ctx);		
+	} while (!do_exit);
+
+
+	
+	/*****
+	 * 4) Transition to background mode.
+	 */
+	CALL( task_mode(BACKGROUND_TASK) );
+	reservation_destroy(gettid(), res_config.cpu);
+
+	return NULL;
+}
+
+
+
+int job(struct thread_context *tcx) 
+{
+	int i;
+	char* buf1 = tcx->shm1;
+	char* buf2 = tcx->shm2;
+	char* buf3 = tcx->shm3;
+	char tmp = 0;
+	/* Do real-time calculation. */
+	printf("Task %d Job %d executinig\n", tcx->id, tcx->job_no);
+
+	if (tcx->id == 0) {
+		printf("READ\n");
+		for (i=0; i<600; i++) {
+			char t = buf1[i];
+			printf("%x ", t);
+		}
+		printf("\n");
+
+		;
+	}
+	//test_call(0);
+	tcx->job_no++;
+	if (tcx->job_no == 10)
+		return 1;
+	/* Don't exit. */
+	return 0;
+}
diff --git bin/resctrl.c bin/resctrl.c
new file mode 100644
index 0000000..63b5054
--- /dev/null
+++ bin/resctrl.c
@@ -0,0 +1,242 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <signal.h>
+
+#include <sched.h>
+
+#include "litmus.h"
+#include "common.h"
+
+const char *usage_msg =
+	"Usage: resctrl OPTIONS [INTERVAL-START,INTERVAL-END]*\n"
+	"    -n ID             create new reservation with id ID\n"
+	"    -a PID            attach already-running process PID to reservation\n"
+	"    -r ID             specify which reservation to attach to (not needed with -n)\n"
+	"    -t TYPE           type of reservation (polling-periodic, polling-sporadic, table-driven)\n"
+	"    -c CPU            physical partition or cluster to assign to\n"
+	"    -b BUDGET         polling reservation budget (in ms, default: 10ms)\n"
+	"    -p PERIOD         polling reservation period (in ms, default: 100ms)\n"
+	"    -d DEADLINE       relative deadline, implicit by default (in ms)\n"
+	"    -o OFFSET         offset (also known as phase), zero by default (in ms)\n"
+	"    -q PRIORITY       priority to use (EDF by default, highest priority = 1)\n"
+	"    -m MAJOR-CYCLE    major cycle length (in ms, for table-driven reservations) \n"
+	"\n";
+
+void usage(char *error) {
+	fprintf(stderr, "%s\n%s", error, usage_msg);
+	exit(1);
+}
+
+
+static void attach_task(int attach_pid, struct reservation_config *config)
+{
+	int ret;
+	struct rt_task param;
+	struct sched_param linux_param;
+
+	ret = be_migrate_thread_to_cpu(attach_pid, config->cpu);
+	if (ret < 0) {
+		fprintf(stderr, "failed to migrate task %d to CPU %d\n",
+			attach_pid, config->cpu);
+		exit(4);
+	}
+
+	init_rt_task_param(&param);
+	/* dummy values */
+	param.exec_cost = ms2ns(100);
+	param.period    = ms2ns(100);
+	/* specify reservation as "virtual" CPU */
+	param.cpu       = config->id;
+
+	ret = set_rt_task_param(attach_pid, &param);
+	if (ret < 0) {
+		fprintf(stderr, "failed to set RT task parameters for task %d (%m)\n",
+			attach_pid);
+		exit(2);
+	}
+
+	linux_param.sched_priority = 0;
+	ret = sched_setscheduler(attach_pid, SCHED_LITMUS, &linux_param);
+	if (ret < 0) {
+		fprintf(stderr, "failed to transition task %d to LITMUS^RT class (%m)\n",
+			attach_pid);
+		exit(3);
+	}
+}
+
+static struct lt_interval* parse_td_intervals(int argc, char** argv,
+	unsigned int *num_intervals, lt_t major_cycle)
+{
+	int i, matched;
+	struct lt_interval *slots = malloc(sizeof(slots[0]) * argc);
+	double start, end;
+
+	*num_intervals = 0;
+	for (i = 0; i < argc; i++) {
+		matched = sscanf(argv[i], "[%lf,%lf]", &start, &end);
+		if (matched != 2) {
+			fprintf(stderr, "could not parse '%s' as interval\n", argv[i]);
+			exit(5);
+		}
+		if (start < 0) {
+			fprintf(stderr, "interval %s: must not start before zero\n", argv[i]);
+			exit(5);
+		}
+		if (end <= start) {
+			fprintf(stderr, "interval %s: end before start\n", argv[i]);
+			exit(5);
+		}
+
+		slots[i].start = ms2ns(start);
+		slots[i].end   = ms2ns(end);
+
+		if (i > 0 && slots[i - 1].end >= slots[i].start) {
+			fprintf(stderr, "interval %s: overlaps with previous interval\n", argv[i]);
+			exit(5);
+		}
+
+		if (slots[i].end >= major_cycle) {
+			fprintf(stderr, "interval %s: exceeds major cycle length\n", argv[i]);
+			exit(5);
+		}
+
+		(*num_intervals)++;
+	}
+
+	return slots;
+}
+
+#define OPTSTR "n:a:r:t:c:b:p:d:o:q:m:h"
+
+int main(int argc, char** argv)
+{
+	int ret, opt;
+	double budget_ms, period_ms, offset_ms, deadline_ms, major_cycle_ms;
+	int create_new = 0;
+	int attach_pid = 0;
+	int res_type = SPORADIC_POLLING;
+
+	struct reservation_config config;
+
+	/* Reasonable defaults */
+	offset_ms      =    0;
+	deadline_ms    =    0;
+	budget_ms      =   10;
+	period_ms      =  100;
+	major_cycle_ms = 1000;
+
+	config.id = 0;
+	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
+	config.cpu = 0;
+
+	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
+		switch (opt) {
+		case 'b':
+			budget_ms = atof(optarg);
+			break;
+		case 'p':
+			period_ms = atof(optarg);
+			break;
+		case 'd':
+			deadline_ms = atof(optarg);
+			if (deadline_ms <= 0) {
+				usage("The relative deadline must be a positive"
+					" number.");
+			}
+			break;
+		case 'o':
+			offset_ms = atof(optarg);
+			break;
+		case 'm':
+			major_cycle_ms = atof(optarg);
+			break;
+
+		case 'q':
+			config.priority = atoi(optarg);
+			if (!config.priority)
+				usage("-q: invalid priority");
+			break;
+		case 'c':
+			config.cpu = atoi(optarg);
+			break;
+
+		case 'n':
+			create_new = 1;
+			config.id  = atoi(optarg);
+			break;
+		case 'a':
+			attach_pid = atoi(optarg);
+			if (!attach_pid)
+				usage("-a: invalid PID");
+			break;
+
+		case 'r':
+			config.id  = atoi(optarg);
+			break;
+
+		case 't':
+			if (strcmp(optarg, "polling-periodic") == 0) {
+				res_type = PERIODIC_POLLING;
+			} else if (strcmp(optarg, "polling-sporadic") == 0) {
+				res_type = SPORADIC_POLLING;
+			}  else if (strcmp(optarg, "table-driven") == 0) {
+				res_type = TABLE_DRIVEN;
+				/* Default for table-driven reservations to
+				 * maximum priority. EDF has not meaning for
+				 * table-driven reservations. */
+				if (config.priority == LITMUS_NO_PRIORITY)
+					config.priority = LITMUS_HIGHEST_PRIORITY;
+			} else {
+				usage("Unknown reservation type.");
+			}
+			break;
+
+		case 'h':
+			usage("");
+			break;
+		case ':':
+			usage("Argument missing.");
+			break;
+		case '?':
+		default:
+			usage("Bad argument.");
+			break;
+		}
+	}
+
+	if (res_type != TABLE_DRIVEN) {
+		config.polling_params.budget = ms2ns(budget_ms);
+		config.polling_params.period = ms2ns(period_ms);
+		config.polling_params.offset = ms2ns(offset_ms);
+		config.polling_params.relative_deadline = ms2ns(deadline_ms);
+		if (config.polling_params.budget > config.polling_params.period) {
+			usage("The budget must not exceed the period.");
+		}
+	} else {
+		config.table_driven_params.major_cycle_length = ms2ns(major_cycle_ms);
+		argc -= optind;
+		argv += optind;
+		config.table_driven_params.intervals = parse_td_intervals(
+			argc, argv, &config.table_driven_params.num_intervals,
+			config.table_driven_params.major_cycle_length);
+		if (!config.table_driven_params.num_intervals)
+			usage("Table-driven reservations require at least one interval to be specified.");
+	}
+
+	if (create_new) {
+		ret = reservation_create(res_type, &config);
+		if (ret < 0) {
+			fprintf(stderr, "failed to create reservation %u (%m)\n",
+				config.id);
+			exit(1);
+		}
+	}
+
+	if (attach_pid)
+		attach_task(attach_pid, &config);
+
+	return 0;
+}
diff --git bin/rt_compress.c bin/rt_compress.c
new file mode 100644
index 0000000..9647854
--- /dev/null
+++ bin/rt_compress.c
@@ -0,0 +1,283 @@
+#include <sys/time.h>
+#include <sys/mman.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#include "litmus.h"
+#include "common.h"
+
+extern int main_job(void);
+static char* progname;
+
+static void usage(char *error) {
+	fprintf(stderr, "Error: %s\n", error);
+	fprintf(stderr,
+		"Usage:\n"
+		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
+		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
+		"	rt_spin -l\n"
+		"\n"
+		"COMMON-OPTS = [-w] [-s SCALE]\n"
+		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
+		"              [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
+		"\n"
+		"WCET and PERIOD are milliseconds, DURATION is seconds.\n"
+		"CRITICAL SECTION LENGTH is in milliseconds.\n");
+	exit(EXIT_FAILURE);
+}
+
+static int job(double exec_time, double program_end, int lock_od, double cs_length)
+{
+	if (wctime() > program_end)
+		return 0;
+	else {
+		main_job();
+		sleep_next_period();
+		return 1;
+	}
+}
+
+#define OPTSTR "p:c:wves:q:X:L:Q:vh:m:i:b:"
+int main(int argc, char** argv)
+{
+	int ret;
+	lt_t wcet;
+	lt_t period;
+	lt_t hyperperiod;
+	lt_t budget;
+	double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
+	unsigned int priority = LITMUS_NO_PRIORITY;
+	int migrate = 0;
+	int cluster = 0;
+	int opt;
+	int wait = 0;
+	int want_enforcement = 0;
+	double duration = 0, start = 0;
+	double scale = 1.0;
+	task_class_t class = RT_CLASS_HARD;
+	struct rt_task param;
+	struct mc2_task mc2_param;
+	struct reservation_config config;
+	int res_type = PERIODIC_POLLING;
+
+	int verbose = 0;
+	unsigned int job_no;
+
+	/* locking */
+	int lock_od = -1;
+	int resource_id = 0;
+	const char *lock_namespace = "./rtspin-locks";
+	int protocol = -1;
+	double cs_length = 1; /* millisecond */
+
+	progname = argv[0];
+
+	/* default for reservation */
+	config.id = 0;
+	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
+	config.cpu = -1;
+	
+	mc2_param.crit = CRIT_LEVEL_C;
+	
+	hyperperiod_ms = 1000;
+	budget_ms = 10;
+	
+	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
+		switch (opt) {
+		case 'w':
+			wait = 1;
+			break;
+		case 'p':
+			cluster = atoi(optarg);
+			migrate = 1;
+			config.cpu = cluster;
+			break;
+		case 'q':
+			priority = atoi(optarg);
+			if (!litmus_is_valid_fixed_prio(priority))
+				usage("Invalid priority.");
+			break;
+		case 'c':
+			class = str2class(optarg);
+			if (class == -1)
+				usage("Unknown task class.");
+			break;
+		case 'e':
+			want_enforcement = 1;
+			break;
+		case 's':
+			scale = atof(optarg);
+			break;
+		case 'X':
+			protocol = lock_protocol_for_name(optarg);
+			if (protocol < 0)
+				usage("Unknown locking protocol specified.");
+			break;
+		case 'L':
+			cs_length = atof(optarg);
+			if (cs_length <= 0)
+				usage("Invalid critical section length.");
+			break;
+		case 'Q':
+			resource_id = atoi(optarg);
+			if (resource_id <= 0 && strcmp(optarg, "0"))
+				usage("Invalid resource ID.");
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case 'm':
+			mc2_param.crit = atoi(optarg);
+			if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
+				usage("Invalid criticality level.");
+			}
+			res_type = PERIODIC_POLLING;
+			break;
+		case 'h':
+			hyperperiod_ms = atof(optarg);
+			break;
+		case 'b':
+			budget_ms = atof(optarg);
+			break;
+		case 'i':
+			config.priority = atoi(optarg);
+			break;
+		case ':':
+			usage("Argument missing.");
+			break;
+		case '?':
+		default:
+			usage("Bad argument.");
+			break;
+		}
+	}
+
+	if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
+		usage("Bad criticailty level or priority");
+
+	if (argc - optind < 3)
+		usage("Arguments missing.");
+
+	wcet_ms   = atof(argv[optind + 0]);
+	period_ms = atof(argv[optind + 1]);
+
+	wcet   = ms2ns(wcet_ms);
+	period = ms2ns(period_ms);
+	budget = ms2ns(budget_ms);
+	hyperperiod = ms2ns(hyperperiod_ms);
+	
+	if (wcet <= 0)
+		usage("The worst-case execution time must be a "
+				"positive number.");
+	if (period <= 0)
+		usage("The period must be a positive number.");
+	if (wcet > period) {
+		usage("The worst-case execution time must not "
+				"exceed the period.");
+	}
+
+	duration  = atof(argv[optind + 2]);
+
+	if (migrate) {
+		ret = be_migrate_to_domain(cluster);
+		if (ret < 0)
+			bail_out("could not migrate to target partition or cluster.");
+	}
+
+	/* reservation config */
+	config.id = gettid();
+	
+	if (hyperperiod%period != 0 ) {
+		;//bail_out("hyperperiod must be multiple of period");
+	}
+	
+	config.polling_params.budget = budget;
+	config.polling_params.period = period;
+	config.polling_params.offset = 0;
+	config.polling_params.relative_deadline = 0;
+	if (config.polling_params.budget > config.polling_params.period) {
+		usage("The budget must not exceed the period.");
+	}
+	
+	/* create a reservation */
+	ret = reservation_create(res_type, &config);
+	if (ret < 0) {
+		bail_out("failed to create reservation.");
+	}
+	
+	init_rt_task_param(&param);
+	param.exec_cost = wcet;
+	param.period = period;
+	param.priority = priority;
+	param.cls = class;
+	param.release_policy = TASK_PERIODIC;
+	param.budget_policy = (want_enforcement) ?
+			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
+	if (migrate) {
+		param.cpu = gettid();
+	}
+	ret = set_rt_task_param(gettid(), &param);
+	
+	if (ret < 0)
+		bail_out("could not setup rt task params");
+	
+	mc2_param.res_id = gettid();
+	ret = set_mc2_task_param(gettid(), &mc2_param);
+//printf("SET_MC2_TASK\n");
+	if (ret < 0)
+		bail_out("could not setup mc2 task params");
+
+	init_litmus();
+//printf("CALL\n");
+	//set_page_color(config.cpu);
+//printf("CALL\n");
+
+//printf("INIT_LITMUS\n");
+	start = wctime();
+	ret = task_mode(LITMUS_RT_TASK);
+//printf("TASK_MODE\n");
+	if (ret != 0)
+		bail_out("could not become RT task");
+
+	if (protocol >= 0) {
+		lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
+		if (lock_od < 0) {
+			perror("litmus_open_lock");
+			usage("Could not open lock.");
+		}
+	}
+
+
+	if (wait) {
+//printf("BEFORE WAIT\n");
+		ret = wait_for_ts_release();
+		if (ret != 0)
+			bail_out("wait_for_ts_release()");
+		start = wctime();
+	}
+
+	do {
+		if (verbose) {
+			get_job_no(&job_no);
+			printf("rtspin/%d:%u @ %.4fms\n", gettid(),
+				job_no, (wctime() - start) * 1000);
+		}
+	} while (job(wcet_ms * 0.001 * scale, start + duration,
+		   lock_od, cs_length * 0.001));
+
+printf("BEFORE BACK_TASK\n");
+	ret = task_mode(BACKGROUND_TASK);
+	if (ret != 0)
+		bail_out("could not become regular task (huh?)");
+
+	reservation_destroy(gettid(), config.cpu);
+	
+	return 0;
+}
diff --git bin/rt_mode_poll.c bin/rt_mode_poll.c
new file mode 100644
index 0000000..d05521c
--- /dev/null
+++ bin/rt_mode_poll.c
@@ -0,0 +1,221 @@
+#include <sys/time.h>
+#include <sys/mman.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#include "litmus.h"
+#include "common.h"
+
+#define __NR_request_mode 408
+#define __NR_enact_mode 409
+
+int main_job(void){
+	return syscall(__NR_enact_mode);
+}
+
+static char* progname;
+
+static void usage(char *error) {
+	fprintf(stderr, "Error: %s\n", error);
+	fprintf(stderr,
+		"Usage:\n"
+		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
+		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
+		"	rt_spin -l\n"
+		"\n"
+		"COMMON-OPTS = [-w] [-s SCALE]\n"
+		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
+		"\n"
+		"WCET and PERIOD are microseconds, DURATION is seconds.\n");
+	exit(EXIT_FAILURE);
+}
+
+static int job(double program_end)
+{
+	if (wctime() > program_end)
+		return 0;
+	else {
+		main_job();
+		sleep_next_period();
+		return 1;
+	}
+}
+
+#define OPTSTR "p:wvel:b:k:"
+int main(int argc, char** argv)
+{
+	int ret;
+	lt_t wcet;
+	lt_t period;
+	lt_t budget;
+	double wcet_ms, period_ms, budget_ms;
+	unsigned int priority = 0; //guarantee highest priority to this task
+	int migrate = 0;
+	int cluster = 0;
+	int opt;
+	int wait = 0;
+	int want_enforcement = 0;
+	task_class_t class = RT_CLASS_HARD;
+	struct rt_task param;
+	struct mc2_task mc2_param;
+	struct reservation_config config;
+	int res_type = PERIODIC_POLLING;
+	uint32_t mode_mask = (1 << 0);
+	int i;
+	double duration = 0, start = 0;
+	struct control_page* ctl_page = NULL;
+
+	progname = argv[0];
+
+	/* default for reservation */
+	config.id = 0;
+	config.priority = 1;
+	config.cpu = -1;
+	
+	mc2_param.crit = CRIT_LEVEL_A;
+	
+	budget_ms = 10;
+
+	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
+		switch (opt) {
+		case 'w':
+			wait = 1;
+			break;
+		case 'p':
+			cluster = atoi(optarg);
+			migrate = 1;
+			config.cpu = cluster;
+			break;
+		case 'e':
+			want_enforcement = 1;
+			break;
+		case 'b':
+			budget_ms = atof(optarg);
+			break;
+		case 'k':
+			mode_mask = atoi(optarg);
+			break;
+		case ':':
+			usage("Argument missing.");
+			break;
+		case '?':
+		default:
+			usage("Bad argument.");
+			break;
+		}
+	}
+
+	if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
+		usage("Bad criticailty level or priority");
+
+	if (argc - optind < 2)
+		usage("Arguments missing.");
+
+	wcet_ms   = atof(argv[optind + 0]);
+	period_ms = atof(argv[optind + 1]);
+
+	wcet   = ms2ns(wcet_ms);
+	period = ms2ns(period_ms);
+	budget = ms2ns(budget_ms);
+	
+	if (wcet <= 0)
+		usage("The worst-case execution time must be a "
+				"positive number.");
+	if (period <= 0)
+		usage("The period must be a positive number.");
+	if (wcet > period) {
+		usage("The worst-case execution time must not "
+				"exceed the period.");
+	}
+
+	duration  = atof(argv[optind + 2]);
+	
+	if (migrate) {
+		ret = be_migrate_to_domain(cluster);
+		if (ret < 0)
+			bail_out("could not migrate to target partition or cluster.");
+	}
+	else{
+		bail_out("rt_mode_poll must be migrated.");
+	}
+
+	/* reservation config */
+	config.id = gettid();
+	
+	config.polling_params.budget = budget;
+	config.polling_params.period = period;
+	config.polling_params.offset = 0;
+	config.polling_params.relative_deadline = 0;
+	if (config.polling_params.budget > config.polling_params.period) {
+		usage("The budget must not exceed the period.");
+	}
+
+	/* create reservation's */
+	for( i = 0; i < 32; i++){
+		if ( !( (1 << i) & mode_mask ) )
+			continue;
+		config.mode = i;
+		ret = reservation_create(res_type, &config);
+		if (ret < 0) {
+			bail_out("failed to create reservation.");
+		}
+	}
+	
+	init_rt_task_param(&param);
+	param.exec_cost = wcet;
+	param.period = period;
+	param.priority = priority;
+	param.cls = class;
+	param.release_policy = TASK_PERIODIC;
+	param.budget_policy = (want_enforcement) ?
+			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
+	if (migrate) {
+		param.cpu = gettid();
+	}
+	ret = set_rt_task_param(gettid(), &param);
+	
+	if (ret < 0)
+		bail_out("could not setup rt task params");
+	
+	mc2_param.res_id = gettid();
+	mc2_param.mode_mask = mode_mask;
+	ret = set_mc2_task_param(gettid(), &mc2_param);
+	if (ret < 0)
+		bail_out("could not setup mc2 task params");
+
+	init_litmus();
+	ctl_page = get_ctrl_page();
+	if (!ctl_page)
+		bail_out("could not get ctrl_page");
+	ctl_page->mode_poll_task = 1;
+	
+	start = wctime();
+	ret = task_mode(LITMUS_RT_TASK);
+	if (ret != 0)
+		bail_out("could not become RT task");
+
+	set_page_color(config.cpu);
+
+	if (wait) {
+		ret = wait_for_ts_release();
+		if (ret != 0)
+			bail_out("wait_for_ts_release()");
+		start = wctime();
+	}
+
+	while (job(start + duration)) {};
+
+	ret = task_mode(BACKGROUND_TASK);
+	if (ret != 0)
+		bail_out("could not become regular task (huh?)");
+
+	reservation_destroy(gettid(), config.cpu);
+	return 0;
+}
diff --git bin/rt_skeleton.c bin/rt_skeleton.c
new file mode 100644
index 0000000..16e189a
--- /dev/null
+++ bin/rt_skeleton.c
@@ -0,0 +1,247 @@
+#include <sys/time.h>
+#include <sys/mman.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#include "litmus.h"
+#include "common.h"
+
+extern int main_job(void);
+
+static char* progname;
+int loops = 10;
+//struct timeval t1, t2;
+
+static void usage(char *error) {
+	fprintf(stderr, "Error: %s\n", error);
+	fprintf(stderr,
+		"Usage:\n"
+		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
+		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
+		"	rt_spin -l\n"
+		"\n"
+		"COMMON-OPTS = [-w] [-s SCALE]\n"
+		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
+		"\n"
+		"WCET and PERIOD are microseconds, DURATION is seconds.\n");
+	exit(EXIT_FAILURE);
+}
+
+inline unsigned long get_cyclecount (void)
+{
+	unsigned long value;
+	// Read CCNT Register
+	asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
+	return value;
+}
+
+static int job(double exec_time, double program_end)
+{
+	if (wctime() > program_end)
+		return 0;
+	else {
+		register int iter = 0;
+		//register unsigned long t;
+		//t = get_cyclecount();
+		//gettimeofday(&t1, NULL);
+		while (iter++ < loops) {
+			main_job();
+		}
+		//t = get_cyclecount() - t;
+		//printf("%ld cycles\n", t);
+		//gettimeofday(&t2, NULL);
+		//printf("%ld us\n", ((t2.tv_sec * 1000000 + t2.tv_usec) - (t1.tv_sec * 1000000 + t1.tv_usec)));
+		sleep_next_period();
+		return 1;
+	}
+}
+
+#define OPTSTR "p:wves:l:m:i:b:"
+int main(int argc, char** argv)
+{
+	int ret;
+	lt_t wcet;
+	lt_t period;
+	lt_t budget;
+	double wcet_us, period_us, budget_us;
+	unsigned int priority = LITMUS_NO_PRIORITY;
+	int migrate = 0;
+	int cluster = 0;
+	int opt;
+	int wait = 0;
+	int want_enforcement = 0;
+	double duration = 0, start = 0;
+	double scale = 1.0;
+	task_class_t class = RT_CLASS_HARD;
+	struct rt_task param;
+	struct mc2_task mc2_param;
+	struct reservation_config config;
+	int res_type = PERIODIC_POLLING;
+
+	unsigned int job_no;
+
+
+	progname = argv[0];
+
+	/* default for reservation */
+	config.id = 0;
+	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
+	config.cpu = -1;
+	
+	mc2_param.crit = CRIT_LEVEL_C;
+	
+	budget_us = 10000;
+
+	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
+		switch (opt) {
+		case 'w':
+			wait = 1;
+			break;
+		case 'p':
+			cluster = atoi(optarg);
+			migrate = 1;
+			config.cpu = cluster;
+			break;
+		case 'e':
+			want_enforcement = 1;
+			break;
+		case 's':
+			scale = atof(optarg);
+			break;
+		case 'l':
+			loops = atoi(optarg);
+			break;
+		case 'm':
+			mc2_param.crit = atoi(optarg);
+			if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
+				usage("Invalid criticality level.");
+			}
+			res_type = PERIODIC_POLLING;
+			break;
+		case 'b':
+			budget_us = atof(optarg);
+			break;
+		case 'i':
+			config.priority = atoi(optarg);
+			break;
+		case ':':
+			usage("Argument missing.");
+			break;
+		case '?':
+		default:
+			usage("Bad argument.");
+			break;
+		}
+	}
+
+	if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
+		usage("Bad criticailty level or priority");
+
+	if (argc - optind < 3)
+		usage("Arguments missing.");
+
+	wcet_us   = atof(argv[optind + 0]);
+	period_us = atof(argv[optind + 1]);
+
+	wcet   = us2ns(wcet_us);
+	period = us2ns(period_us);
+	budget = us2ns(budget_us);
+	
+	if (wcet <= 0)
+		usage("The worst-case execution time must be a "
+				"positive number.");
+	if (period <= 0)
+		usage("The period must be a positive number.");
+	if (wcet > period) {
+		usage("The worst-case execution time must not "
+				"exceed the period.");
+	}
+
+	duration  = atof(argv[optind + 2]);
+
+	if (migrate) {
+		ret = be_migrate_to_domain(cluster);
+		if (ret < 0)
+			bail_out("could not migrate to target partition or cluster.");
+	}
+
+	/* reservation config */
+	config.id = gettid();
+	
+	config.polling_params.budget = budget;
+	config.polling_params.period = period;
+	config.polling_params.offset = 0;
+	config.polling_params.relative_deadline = 0;
+	if (config.polling_params.budget > config.polling_params.period) {
+		usage("The budget must not exceed the period.");
+	}
+	
+	/* create a reservation */
+	ret = reservation_create(res_type, &config);
+	if (ret < 0) {
+		bail_out("failed to create reservation.");
+	}
+	
+	init_rt_task_param(&param);
+	param.exec_cost = wcet;
+	param.period = period;
+	param.priority = priority;
+	param.cls = class;
+	param.release_policy = TASK_PERIODIC;
+	param.budget_policy = (want_enforcement) ?
+			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
+	if (migrate) {
+		param.cpu = gettid();
+	}
+	ret = set_rt_task_param(gettid(), &param);
+	
+	if (ret < 0)
+		bail_out("could not setup rt task params");
+	
+	mc2_param.res_id = gettid();
+	ret = set_mc2_task_param(gettid(), &mc2_param);
+//printf("SET_MC2_TASK\n");
+	if (ret < 0)
+		bail_out("could not setup mc2 task params");
+
+	init_litmus();
+//printf("CALL\n");
+	if (mc2_param.crit == CRIT_LEVEL_C)
+		set_page_color(8);
+	else if (mc2_param.crit < CRIT_LEVEL_C)
+		set_page_color(config.cpu*2 + mc2_param.crit);
+//printf("CALL\n");
+
+//printf("INIT_LITMUS\n");
+	start = wctime();
+	ret = task_mode(LITMUS_RT_TASK);
+//printf("TASK_MODE\n");
+	if (ret != 0)
+		bail_out("could not become RT task");
+
+
+	if (wait) {
+//printf("BEFORE WAIT\n");
+		ret = wait_for_ts_release();
+		if (ret != 0)
+			bail_out("wait_for_ts_release()");
+		start = wctime();
+	}
+
+	while (job(wcet_us * 0.000001 * scale, start + duration)) {};
+
+	ret = task_mode(BACKGROUND_TASK);
+	if (ret != 0)
+		bail_out("could not become regular task (huh?)");
+
+	reservation_destroy(gettid(), config.cpu);
+	printf("%s/%d finished.\n",progname, gettid());	
+	return 0;
+}
diff --git bin/rt_skeleton_ms.c bin/rt_skeleton_ms.c
new file mode 100644
index 0000000..d545635
--- /dev/null
+++ bin/rt_skeleton_ms.c
@@ -0,0 +1,282 @@
+#include <sys/time.h>
+#include <sys/mman.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#include "litmus.h"
+#include "common.h"
+
+extern int main_job(void);
+static char* progname;
+
+static void usage(char *error) {
+	fprintf(stderr, "Error: %s\n", error);
+	fprintf(stderr,
+		"Usage:\n"
+		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
+		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
+		"	rt_spin -l\n"
+		"\n"
+		"COMMON-OPTS = [-w] [-s SCALE]\n"
+		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
+		"              [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
+		"\n"
+		"WCET and PERIOD are milliseconds, DURATION is seconds.\n"
+		"CRITICAL SECTION LENGTH is in milliseconds.\n");
+	exit(EXIT_FAILURE);
+}
+
+static int job(double exec_time, double program_end, int lock_od, double cs_length)
+{
+	if (wctime() > program_end)
+		return 0;
+	else {
+		main_job();
+		sleep_next_period();
+		return 1;
+	}
+}
+
+#define OPTSTR "p:c:wves:q:X:L:Q:vh:m:i:b:"
+int main(int argc, char** argv)
+{
+	int ret;
+	lt_t wcet;
+	lt_t period;
+	lt_t hyperperiod;
+	lt_t budget;
+	double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
+	unsigned int priority = LITMUS_NO_PRIORITY;
+	int migrate = 0;
+	int cluster = 0;
+	int opt;
+	int wait = 0;
+	int want_enforcement = 0;
+	double duration = 0, start = 0;
+	double scale = 1.0;
+	task_class_t class = RT_CLASS_HARD;
+	struct rt_task param;
+	struct mc2_task mc2_param;
+	struct reservation_config config;
+	int res_type = PERIODIC_POLLING;
+
+	int verbose = 0;
+	unsigned int job_no;
+
+	/* locking */
+	int lock_od = -1;
+	int resource_id = 0;
+	const char *lock_namespace = "./rtspin-locks";
+	int protocol = -1;
+	double cs_length = 1; /* millisecond */
+
+	progname = argv[0];
+
+	/* default for reservation */
+	config.id = 0;
+	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
+	config.cpu = -1;
+	
+	mc2_param.crit = CRIT_LEVEL_C;
+	
+	hyperperiod_ms = 1000;
+	budget_ms = 10;
+
+	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
+		switch (opt) {
+		case 'w':
+			wait = 1;
+			break;
+		case 'p':
+			cluster = atoi(optarg);
+			migrate = 1;
+			config.cpu = cluster;
+			break;
+		case 'q':
+			priority = atoi(optarg);
+			if (!litmus_is_valid_fixed_prio(priority))
+				usage("Invalid priority.");
+			break;
+		case 'c':
+			class = str2class(optarg);
+			if (class == -1)
+				usage("Unknown task class.");
+			break;
+		case 'e':
+			want_enforcement = 1;
+			break;
+		case 's':
+			scale = atof(optarg);
+			break;
+		case 'X':
+			protocol = lock_protocol_for_name(optarg);
+			if (protocol < 0)
+				usage("Unknown locking protocol specified.");
+			break;
+		case 'L':
+			cs_length = atof(optarg);
+			if (cs_length <= 0)
+				usage("Invalid critical section length.");
+			break;
+		case 'Q':
+			resource_id = atoi(optarg);
+			if (resource_id <= 0 && strcmp(optarg, "0"))
+				usage("Invalid resource ID.");
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case 'm':
+			mc2_param.crit = atoi(optarg);
+			if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
+				usage("Invalid criticality level.");
+			}
+			res_type = PERIODIC_POLLING;
+			break;
+		case 'h':
+			hyperperiod_ms = atof(optarg);
+			break;
+		case 'b':
+			budget_ms = atof(optarg);
+			break;
+		case 'i':
+			config.priority = atoi(optarg);
+			break;
+		case ':':
+			usage("Argument missing.");
+			break;
+		case '?':
+		default:
+			usage("Bad argument.");
+			break;
+		}
+	}
+
+	if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
+		usage("Bad criticailty level or priority");
+
+	if (argc - optind < 3)
+		usage("Arguments missing.");
+
+	wcet_ms   = atof(argv[optind + 0]);
+	period_ms = atof(argv[optind + 1]);
+
+	wcet   = ms2ns(wcet_ms);
+	period = ms2ns(period_ms);
+	budget = ms2ns(budget_ms);
+	hyperperiod = ms2ns(hyperperiod_ms);
+	
+	if (wcet <= 0)
+		usage("The worst-case execution time must be a "
+				"positive number.");
+	if (period <= 0)
+		usage("The period must be a positive number.");
+	if (wcet > period) {
+		usage("The worst-case execution time must not "
+				"exceed the period.");
+	}
+
+	duration  = atof(argv[optind + 2]);
+
+	if (migrate) {
+		ret = be_migrate_to_domain(cluster);
+		if (ret < 0)
+			bail_out("could not migrate to target partition or cluster.");
+	}
+
+	/* reservation config */
+	config.id = gettid();
+	
+	if (hyperperiod%period != 0 ) {
+		;//bail_out("hyperperiod must be multiple of period");
+	}
+	
+	config.polling_params.budget = budget;
+	config.polling_params.period = period;
+	config.polling_params.offset = 0;
+	config.polling_params.relative_deadline = 0;
+	if (config.polling_params.budget > config.polling_params.period) {
+		usage("The budget must not exceed the period.");
+	}
+	
+	/* create a reservation */
+	ret = reservation_create(res_type, &config);
+	if (ret < 0) {
+		bail_out("failed to create reservation.");
+	}
+	
+	init_rt_task_param(&param);
+	param.exec_cost = wcet;
+	param.period = period;
+	param.priority = priority;
+	param.cls = class;
+	param.release_policy = TASK_PERIODIC;
+	param.budget_policy = (want_enforcement) ?
+			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
+	if (migrate) {
+		param.cpu = gettid();
+	}
+	ret = set_rt_task_param(gettid(), &param);
+	
+	if (ret < 0)
+		bail_out("could not setup rt task params");
+	
+	mc2_param.res_id = gettid();
+	ret = set_mc2_task_param(gettid(), &mc2_param);
+//printf("SET_MC2_TASK\n");
+	if (ret < 0)
+		bail_out("could not setup mc2 task params");
+
+	init_litmus();
+//printf("CALL\n");
+	set_page_color(config.cpu);
+//printf("CALL\n");
+
+//printf("INIT_LITMUS\n");
+	start = wctime();
+	ret = task_mode(LITMUS_RT_TASK);
+//printf("TASK_MODE\n");
+	if (ret != 0)
+		bail_out("could not become RT task");
+
+	if (protocol >= 0) {
+		lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
+		if (lock_od < 0) {
+			perror("litmus_open_lock");
+			usage("Could not open lock.");
+		}
+	}
+
+
+	if (wait) {
+//printf("BEFORE WAIT\n");
+		ret = wait_for_ts_release();
+		if (ret != 0)
+			bail_out("wait_for_ts_release()");
+		start = wctime();
+	}
+
+	do {
+		if (verbose) {
+			get_job_no(&job_no);
+			printf("rtspin/%d:%u @ %.4fms\n", gettid(),
+				job_no, (wctime() - start) * 1000);
+		}
+	} while (job(wcet_ms * 0.001 * scale, start + duration,
+		   lock_od, cs_length * 0.001));
+
+	ret = task_mode(BACKGROUND_TASK);
+	if (ret != 0)
+		bail_out("could not become regular task (huh?)");
+
+	reservation_destroy(gettid(), config.cpu);
+printf("%s/%d finished.\n",progname, gettid());	
+	return 0;
+}
diff --git bin/rt_skeleton_us.c bin/rt_skeleton_us.c
new file mode 100644
index 0000000..ecf3ed8
--- /dev/null
+++ bin/rt_skeleton_us.c
@@ -0,0 +1,282 @@
+#include <sys/time.h>
+#include <sys/mman.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+
+#include "litmus.h"
+#include "common.h"
+
+extern int main_job(void);
+static char* progname;
+
+static void usage(char *error) {
+	fprintf(stderr, "Error: %s\n", error);
+	fprintf(stderr,
+		"Usage:\n"
+		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
+		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
+		"	rt_spin -l\n"
+		"\n"
+		"COMMON-OPTS = [-w] [-s SCALE]\n"
+		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
+		"              [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
+		"\n"
+		"WCET and PERIOD are microseconds, DURATION is seconds.\n"
+		"CRITICAL SECTION LENGTH is in microseconds.\n");
+	exit(EXIT_FAILURE);
+}
+
+static int job(double exec_time, double program_end, int lock_od, double cs_length)
+{
+	if (wctime() > program_end)
+		return 0;
+	else {
+		main_job();
+		sleep_next_period();
+		return 1;
+	}
+}
+
+#define OPTSTR "p:c:wves:q:X:L:Q:vh:m:i:b:"
+int main(int argc, char** argv)
+{
+	int ret;
+	lt_t wcet;
+	lt_t period;
+	lt_t hyperperiod;
+	lt_t budget;
+	double wcet_us, period_us, hyperperiod_us, budget_us;
+	unsigned int priority = LITMUS_NO_PRIORITY;
+	int migrate = 0;
+	int cluster = 0;
+	int opt;
+	int wait = 0;
+	int want_enforcement = 0;
+	double duration = 0, start = 0;
+	double scale = 1.0;
+	task_class_t class = RT_CLASS_HARD;
+	struct rt_task param;
+	struct mc2_task mc2_param;
+	struct reservation_config config;
+	int res_type = PERIODIC_POLLING;
+
+	int verbose = 0;
+	unsigned int job_no;
+
+	/* locking */
+	int lock_od = -1;
+	int resource_id = 0;
+	const char *lock_namespace = "./rtspin-locks";
+	int protocol = -1;
+	double cs_length = 1; /* millisecond */
+
+	progname = argv[0];
+
+	/* default for reservation */
+	config.id = 0;
+	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
+	config.cpu = -1;
+	
+	mc2_param.crit = CRIT_LEVEL_C;
+	
+	hyperperiod_us = 1000000;
+	budget_us = 10000;
+
+	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
+		switch (opt) {
+		case 'w':
+			wait = 1;
+			break;
+		case 'p':
+			cluster = atoi(optarg);
+			migrate = 1;
+			config.cpu = cluster;
+			break;
+		case 'q':
+			priority = atoi(optarg);
+			if (!litmus_is_valid_fixed_prio(priority))
+				usage("Invalid priority.");
+			break;
+		case 'c':
+			class = str2class(optarg);
+			if (class == -1)
+				usage("Unknown task class.");
+			break;
+		case 'e':
+			want_enforcement = 1;
+			break;
+		case 's':
+			scale = atof(optarg);
+			break;
+		case 'X':
+			protocol = lock_protocol_for_name(optarg);
+			if (protocol < 0)
+				usage("Unknown locking protocol specified.");
+			break;
+		case 'L':
+			cs_length = atof(optarg);
+			if (cs_length <= 0)
+				usage("Invalid critical section length.");
+			break;
+		case 'Q':
+			resource_id = atoi(optarg);
+			if (resource_id <= 0 && strcmp(optarg, "0"))
+				usage("Invalid resource ID.");
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case 'm':
+			mc2_param.crit = atoi(optarg);
+			if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
+				usage("Invalid criticality level.");
+			}
+			res_type = PERIODIC_POLLING;
+			break;
+		case 'h':
+			hyperperiod_us = atof(optarg);
+			break;
+		case 'b':
+			budget_us = atof(optarg);
+			break;
+		case 'i':
+			config.priority = atoi(optarg);
+			break;
+		case ':':
+			usage("Argument missing.");
+			break;
+		case '?':
+		default:
+			usage("Bad argument.");
+			break;
+		}
+	}
+
+	if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
+		usage("Bad criticailty level or priority");
+
+	if (argc - optind < 3)
+		usage("Arguments missing.");
+
+	wcet_us   = atof(argv[optind + 0]);
+	period_us = atof(argv[optind + 1]);
+
+	wcet   = us2ns(wcet_us);
+	period = us2ns(period_us);
+	budget = us2ns(budget_us);
+	hyperperiod = us2ns(hyperperiod_us);
+	
+	if (wcet <= 0)
+		usage("The worst-case execution time must be a "
+				"positive number.");
+	if (period <= 0)
+		usage("The period must be a positive number.");
+	if (wcet > period) {
+		usage("The worst-case execution time must not "
+				"exceed the period.");
+	}
+
+	duration  = atof(argv[optind + 2]);
+
+	if (migrate) {
+		ret = be_migrate_to_domain(cluster);
+		if (ret < 0)
+			bail_out("could not migrate to target partition or cluster.");
+	}
+
+	/* reservation config */
+	config.id = gettid();
+	
+	if (hyperperiod%period != 0 ) {
+		;//bail_out("hyperperiod must be multiple of period");
+	}
+	
+	config.polling_params.budget = budget;
+	config.polling_params.period = period;
+	config.polling_params.offset = 0;
+	config.polling_params.relative_deadline = 0;
+	if (config.polling_params.budget > config.polling_params.period) {
+		usage("The budget must not exceed the period.");
+	}
+	
+	/* create a reservation */
+	ret = reservation_create(res_type, &config);
+	if (ret < 0) {
+		bail_out("failed to create reservation.");
+	}
+	
+	init_rt_task_param(&param);
+	param.exec_cost = wcet;
+	param.period = period;
+	param.priority = priority;
+	param.cls = class;
+	param.release_policy = TASK_PERIODIC;
+	param.budget_policy = (want_enforcement) ?
+			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
+	if (migrate) {
+		param.cpu = gettid();
+	}
+	ret = set_rt_task_param(gettid(), &param);
+	
+	if (ret < 0)
+		bail_out("could not setup rt task params");
+	
+	mc2_param.res_id = gettid();
+	ret = set_mc2_task_param(gettid(), &mc2_param);
+//printf("SET_MC2_TASK\n");
+	if (ret < 0)
+		bail_out("could not setup mc2 task params");
+
+	init_litmus();
+//printf("CALL\n");
+	set_page_color(config.cpu);
+//printf("CALL\n");
+
+//printf("INIT_LITMUS\n");
+	start = wctime();
+	ret = task_mode(LITMUS_RT_TASK);
+//printf("TASK_MODE\n");
+	if (ret != 0)
+		bail_out("could not become RT task");
+
+	if (protocol >= 0) {
+		lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
+		if (lock_od < 0) {
+			perror("litmus_open_lock");
+			usage("Could not open lock.");
+		}
+	}
+
+
+	if (wait) {
+//printf("BEFORE WAIT\n");
+		ret = wait_for_ts_release();
+		if (ret != 0)
+			bail_out("wait_for_ts_release()");
+		start = wctime();
+	}
+
+	do {
+		if (verbose) {
+			get_job_no(&job_no);
+			printf("rtspin/%d:%u @ %.4fms\n", gettid(),
+				job_no, (wctime() - start) * 1000);
+		}
+	} while (job(wcet_us * 0.000001 * scale, start + duration,
+		   lock_od, cs_length * 0.000001));
+
+	ret = task_mode(BACKGROUND_TASK);
+	if (ret != 0)
+		bail_out("could not become regular task (huh?)");
+
+	reservation_destroy(gettid(), config.cpu);
+printf("%s/%d finished.\n",progname, gettid());	
+	return 0;
+}
diff --git bin/rtspin.c bin/rtspin.c
index ea7f192..fd57c45 100644
--- bin/rtspin.c
+++ bin/rtspin.c
@@ -6,7 +6,7 @@
 #include <time.h>
 #include <string.h>
 #include <assert.h>
-
+#include <limits.h>
 
 #include "litmus.h"
 #include "common.h"
@@ -191,7 +191,7 @@ int main(int argc, char** argv)
 	lt_t wcet;
 	lt_t period;
 	double wcet_ms, period_ms;
-	unsigned int priority = LITMUS_LOWEST_PRIORITY;
+	unsigned int priority = LITMUS_NO_PRIORITY;
 	int migrate = 0;
 	int cluster = 0;
 	int reservation = -1;
diff --git include/cache_common.h include/cache_common.h
new file mode 100644
index 0000000..2957dd3
--- /dev/null
+++ include/cache_common.h
@@ -0,0 +1,213 @@
+#ifndef __CACHE_COMMON_H__
+#define __CACHE_COMMON_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <assert.h>
+
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <sys/io.h>
+#include <sys/utsname.h>
+
+#include <sched.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "litmus.h"
+#include "asm/cycles.h"
+
+#if defined(__i386__) || defined(__x86_64__)
+#include "asm/irq.h"
+#endif
+
+
+#define UNCACHE_DEV "/dev/litmus/uncache"
+
+static void die(char *error)
+{
+    fprintf(stderr, "Error: %s (errno: %m)\n",
+        error);
+    exit(1);
+}
+
+static int migrate_to(int cpu)
+{
+    int ret;
+
+    static __thread cpu_set_t* cpu_set = NULL;
+    static __thread size_t cpu_set_sz;
+    static __thread int num_cpus;
+    if(!cpu_set)
+    {
+        num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+        cpu_set = CPU_ALLOC(num_cpus);
+        cpu_set_sz = CPU_ALLOC_SIZE(num_cpus);
+    }
+
+    CPU_ZERO_S(cpu_set_sz, cpu_set);
+    CPU_SET_S(cpu, cpu_set_sz, cpu_set);
+    ret = sched_setaffinity(0 /* self */, cpu_set_sz, cpu_set);
+    return ret;
+}
+
+static int check_migrations(int num_cpus)
+{
+    int cpu, err;
+
+    for (cpu = 0; cpu < num_cpus; cpu++) {
+        err = migrate_to(cpu);
+        if (err != 0) {
+            fprintf(stderr, "Migration to CPU %d failed: %m.\n",
+                cpu + 1);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static int become_posix_realtime_task(int prio)
+{
+    struct sched_param param;
+    memset(&param, 0, sizeof(param));
+    param.sched_priority = prio;
+    return sched_setscheduler(0 /* self */, SCHED_FIFO, &param);
+}
+
+static int renice(int nice_val)
+{
+        return setpriority(PRIO_PROCESS, 0 /* self */, nice_val);
+}
+
+static int lock_memory(void)
+{
+    return mlockall(MCL_CURRENT | MCL_FUTURE);
+}
+
+/* define CACHELINE_SIZE if not provided by compiler args */
+#ifndef CACHELINE_SIZE
+#if defined(__i386__) || defined(__x86_64__)
+/* recent intel cpus */
+#define CACHELINE_SIZE 64
+#elif defined(__arm__)
+/* at least with Cortex-A9 cpus ("8 words") */
+#define CACHELINE_SIZE 32
+#else
+#error "Could not determine cacheline size!"
+#endif
+#endif
+
+//#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
+//typedef struct cacheline
+//{
+//        int line[INTS_IN_CACHELINE];
+//} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
+
+static cacheline_t* alloc_arena(size_t size, int use_huge_pages, int use_uncache_pages)
+{
+    int flags = MAP_PRIVATE | MAP_POPULATE;
+    cacheline_t* arena = NULL;
+    int fd;
+
+    if(use_huge_pages)
+        flags |= MAP_HUGETLB;
+
+	if(use_uncache_pages) {
+			fd = open(UNCACHE_DEV, O_RDWR);
+			if (fd == -1)
+					die("Failed to open uncache device. Are you running the LITMUS^RT kernel?");
+	}
+	else {
+			fd = -1;
+			flags |= MAP_ANONYMOUS;
+	}
+
+    arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0);
+	
+    if(use_uncache_pages)
+		close(fd);
+
+    assert(arena);
+
+        return arena;
+}
+
+static void dealloc_arena(cacheline_t* arena, size_t size)
+{
+		int ret = munmap((void*)arena, size);
+        if(ret != 0)
+                die("munmap() error");
+}
+
+static int randrange(int min, int max)
+{
+        /* generate a random number on the range [min, max) w/o skew */
+        int limit = max - min;
+        int devisor = RAND_MAX/limit;
+        int retval;
+
+        do {
+                retval = rand() / devisor;
+        } while(retval == limit);
+        retval += min;
+
+        return retval;
+}
+
+static void init_arena(cacheline_t* arena, size_t size)
+{
+    int i;
+        size_t num_arena_elem = size / sizeof(cacheline_t);
+
+        /* Generate a cycle among the cache lines using Sattolo's algorithm.
+           Every int in the cache line points to the same cache line.
+           Note: Sequential walk doesn't care about these values. */
+        for (i = 0; i < num_arena_elem; i++) {
+                int j;
+                for(j = 0; j < INTS_IN_CACHELINE; ++j)
+                        arena[i].line[j] = i;
+        }
+        while(1 < i--) {
+                int j = randrange(0, i);
+                cacheline_t temp = arena[j];
+                arena[j] = arena[i];
+                arena[i] = temp;
+        }
+}
+
+static void sleep_us(int microseconds)
+{
+    struct timespec delay;
+
+    delay.tv_sec = 0;
+    delay.tv_nsec = microseconds * 1000;
+    if (nanosleep(&delay, NULL) != 0)
+        die("sleep failed");
+}
+
+static int completed(int nSamples, int* history, int nCategories)
+{
+        int i;
+        for(i = 0; i < nCategories; ++i)
+                if(history[i] < nSamples)
+                        return 0;
+        return 1;
+}
+
+inline unsigned long get_cyclecount (void)
+{
+	unsigned long value;
+	// Read CCNT Register
+	asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
+	return value;
+}
+
+
+#endif
diff --git include/color_shm.h include/color_shm.h
new file mode 100644
index 0000000..449ec9d
--- /dev/null
+++ include/color_shm.h
@@ -0,0 +1,20 @@
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#define SHM_MAJOR		(240)
+
+struct color_ioctl_cmd {
+	unsigned int color;
+	unsigned int bank;
+};
+
+struct color_ioctl_offset {
+	unsigned long offset;
+	int lock;
+};
+
+#define SET_COLOR_SHM_CMD		_IOW(SHM_MAJOR, 0x1, struct color_ioctl_cmd)
+#define SET_COLOR_SHM_OFFSET	_IOW(SHM_MAJOR, 0x2, struct color_ioctl_offset)
+
+void* color_mmap(size_t size, struct color_ioctl_cmd cmd, struct color_ioctl_offset offset);
diff --git include/litmus.h include/litmus.h
index b9dbdb5..b70917e 100644
--- include/litmus.h
+++ include/litmus.h
@@ -40,12 +40,22 @@ extern "C" {
 
 #include "migration.h"
 
+#include "litmus/mc2_common.h"
+
 /**
  * @private
  * The numeric ID of the LITMUS^RT scheduling class.
  */
 #define SCHED_LITMUS 7
 
+#define CACHELINE_SIZE 32
+#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
+#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
+typedef struct cacheline
+{
+        int line[INTS_IN_CACHELINE];
+} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
+
 /**
  * Initialise a real-time task param struct
  * @param param Pointer to the struct to initialise
@@ -146,6 +156,12 @@ int sporadic_clustered(lt_t e_ns, lt_t p_ns, int cluster);
 /** Convert microseconds to nanoseconds
   * @param us Time units in microseconds */
 #define us2ns(us) ((us)*1000LL)
+#define ns2s(ns)  ((ns)/1000000000LL)
+#define ns2ms(ns) ((ns)/1000000LL)
+#define ns2us(ns) ((ns)/1000LL)
+#define us2ms(us) ((us)/1000LL)
+#define us2s(us)  ((us)/1000000LL)
+#define ms2s(ms)  ((ms)/1000LL)
 
 /**
  * Locking protocols for allocated shared objects
@@ -286,6 +302,12 @@ void exit_np(void);
  */
 int  requested_to_preempt(void);
 
+/* pgm support */
+void enter_pgm_wait(void);
+void exit_pgm_wait(void);
+void enter_pgm_send(void);
+void exit_pgm_send(void);
+
 /***** Task System support *****/
 /**
  * Wait until task master releases all real-time tasks
@@ -416,6 +438,20 @@ int null_call(cycles_t *timestamp);
  */
 struct control_page* get_ctrl_page(void);
 
+int reservation_create(int rtype, void *config);
+
+int reservation_destroy(unsigned int reservation_id, int cpu);
+
+int set_mc2_task_param(pid_t pid, struct mc2_task* param);
+
+int set_page_color(int cpu);
+
+int test_call(unsigned int param);
+
+int run_bench(int type, int size, cacheline_t *src, cacheline_t *dst, lt_t __user *ts);
+
+int lock_buffer(void* vaddr, size_t size, unsigned int lock_way, unsigned int unlock_way);
+
 #ifdef __cplusplus
 }
 #endif
diff --git src/color_shm.c src/color_shm.c
new file mode 100644
index 0000000..15332aa
--- /dev/null
+++ src/color_shm.c
@@ -0,0 +1,42 @@
+#include <sys/mman.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "color_shm.h"
+
+void* color_mmap(size_t size, struct color_ioctl_cmd cmd, struct color_ioctl_offset offset)
+{
+	int ret, fd;
+	void *mem;
+	
+	fd = open("/dev/litmus/color_shm", O_RDWR);
+	if (fd < 0) {
+		printf("Device open error.\n");
+		return NULL;
+	}
+
+	ret = ioctl(fd, SET_COLOR_SHM_CMD, &cmd);
+	if (ret < 0) {
+		printf("ioctl failed.\n");
+		return NULL;
+	}
+	
+	ret = ioctl(fd, SET_COLOR_SHM_OFFSET, &offset);
+	if (ret < 0) {
+		printf("ioctl failed.\n");
+		return NULL;
+	}
+	
+	size += offset.offset;
+	mem = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+	if (mem == MAP_FAILED) {
+		printf("mmap failed.\n");
+		return MAP_FAILED;
+	}
+	close(fd);
+	
+	mem += offset.offset;
+	
+	return mem;
+}
+
diff --git src/kernel_iface.c src/kernel_iface.c
index ca874ff..273ecb2 100644
--- src/kernel_iface.c
+++ src/kernel_iface.c
@@ -2,7 +2,7 @@
 #include <sys/fcntl.h> /* for O_RDWR */
 #include <sys/unistd.h>
 #include <sched.h> /* for sched_yield() */
-
+#include <assert.h>
 
 #include <stdio.h>
 
@@ -98,6 +98,8 @@ int init_kernel_iface(void)
 		     != LITMUS_CP_OFFSET_TS_SC_START);
 	BUILD_BUG_ON(offsetof(struct control_page, irq_syscall_start)
 		     != LITMUS_CP_OFFSET_IRQ_SC_START);
+	BUILD_BUG_ON(offsetof(struct control_page, mode_poll_task)
+		     != LITMUS_CP_OFFSET_MODE_POLL_TASK);
 
 	err = map_file(LITMUS_CTRL_DEVICE, &mapped_at, CTRL_PAGES * page_size);
 
@@ -110,7 +112,7 @@ int init_kernel_iface(void)
 		fprintf(stderr, "%s: cannot open LITMUS^RT control page (%m)\n",
 			__FUNCTION__);
 	}
-
+	ctrl_page->mode_poll_task = 0;
 	return err;
 }
 
@@ -140,6 +142,63 @@ int requested_to_preempt(void)
 	return (likely(ctrl_page != NULL) && ctrl_page->sched.np.preempt);
 }
 
+#ifdef CONFIG_PGMRT_SUPPORT
+void enter_pgm_wait(void) 		
+{ 		
+        if (likely(ctrl_page != NULL) || init_kernel_iface() == 0) { 		
+                assert(!ctrl_page->pgm_waiting); 		
+                ctrl_page->pgm_waiting = 1; 		
+                __sync_synchronize(); 		
+        } 		
+        else { 		
+                fprintf(stderr, "enter_pgm_wait: control page not mapped!\n"); 		
+        } 		
+} 		
+		
+void exit_pgm_wait(void) 		
+{ 		
+        if (likely(ctrl_page != NULL)) { 		
+                assert(ctrl_page->pgm_waiting); 		
+                ctrl_page->pgm_waiting = 0; 		
+                __sync_synchronize(); 		
+        } 		
+        else { 		
+                fprintf(stderr, "exit_pgm_wait: control page not mapped!\n"); 		
+        } 		
+} 		
+		
+void enter_pgm_send(void) 		
+{ 		
+        if (likely(ctrl_page != NULL) || init_kernel_iface() == 0) { 		
+                assert(!ctrl_page->pgm_sending); 		
+                ctrl_page->pgm_sending = 1; /* we will become boosted if 		
+                                               anyone tries to preempt us. */ 		
+                __sync_synchronize(); 		
+        } 		
+        else { 		
+                fprintf(stderr, "enter_pgm_send: control page not mapped!\n"); 		
+        } 		
+} 		
+		
+void exit_pgm_send(void) 		
+{ 		
+        if (likely(ctrl_page != NULL)) { 		
+                assert(ctrl_page->pgm_sending); 		
+		
+                ctrl_page->pgm_satisfied = 1; 		
+                __sync_synchronize(); 		
+		
+                /* re-eval priority. Should clear pgm_sending and pgm_satisfied. */ 		
+                sched_yield(); 		
+		
+                /* double check that Litmus is doing its job */ 		
+                assert(!ctrl_page->pgm_sending && !ctrl_page->pgm_satisfied); 		
+        } 		
+        else { 		
+                fprintf(stderr, "exit_pgm_send: control page not mapped!\n"); 		
+        } 		
+}
+#endif
 /* init and return a ptr to the control page for
  * preemption and migration overhead analysis
  *
diff --git src/syscalls.c src/syscalls.c
index c68f15b..6ec0cd9 100644
--- src/syscalls.c
+++ src/syscalls.c
@@ -86,3 +86,34 @@ int null_call(cycles_t *timestamp)
 {
 	return syscall(__NR_null_call, timestamp);
 }
+
+int reservation_create(int rtype, void *config)
+{
+	return syscall(__NR_reservation_create, rtype, config);
+}
+
+int reservation_destroy(unsigned int reservation_id, int cpu)
+{
+	return syscall(__NR_reservation_destroy, reservation_id, cpu);
+}
+
+int set_mc2_task_param(pid_t pid, struct mc2_task *param)
+{
+	return syscall(__NR_set_mc2_task_param, pid, param);
+}
+
+int set_page_color(int cpu)
+{
+	return syscall(__NR_set_page_color, cpu);
+}
+
+int run_bench(int type, int wss, cacheline_t *src, cacheline_t *dst, lt_t *ts)
+{
+	return syscall(__NR_run_test, type, wss, src, dst, ts);
+}
+
+int lock_buffer(void* vaddr, size_t size, unsigned int lock_way, unsigned int unlock_way)
+{
+	return syscall(__NR_lock_buffer, vaddr, size, lock_way, unlock_way);
+}
+
