Attachment 'MC2-liblitmus-imx6-rtss15.patch'

Download

   1 From 54ab0e29794e9f22aacd206102d9e4d643e28efe Mon Sep 17 00:00:00 2001
   2 From: Bjoern Brandenburg <bbb@mpi-sws.org>
   3 Date: Thu, 12 Jun 2014 13:32:21 +0200
   4 Subject: [PATCH 1/7] Add test cases for enforcement of periods of periodic
   5  tasks
   6 
   7 ---
   8  tests/sched.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   9  1 file changed, 83 insertions(+)
  10 
  11 diff --git a/tests/sched.c b/tests/sched.c
  12 index 6fd6d89..a91e736 100644
  13 --- a/tests/sched.c
  14 +++ b/tests/sched.c
  15 @@ -1,6 +1,7 @@
  16  #include <sys/wait.h> /* for waitpid() */
  17  #include <unistd.h>
  18  #include <stdio.h>
  19 +#include <math.h>
  20  
  21  #include "tests.h"
  22  #include "litmus.h"
  23 @@ -76,4 +77,86 @@ TESTCASE(preempt_on_resume, P_FP | PSN_EDF,
  24  	ASSERT( status ==  SIGUSR2);
  25  }
  26  
  27 +#define PERIOD 100 /* in ms */
  28 +#define JOBS 10
  29 +#define ACCEPTABLE_MARGIN 5 /* in ms --- must be largish for QEMU */
  30  
  31 +TESTCASE(jobs_are_rate_limited, LITMUS,
  32 +	 "periodic jobs are rate-limited (w/o synchronous release)")
  33 +{
  34 +	struct rt_task params;
  35 +	double start, end, actual_delta_ms;
  36 +	int i;
  37 +
  38 +	init_rt_task_param(&params);
  39 +	params.cpu        = 0;
  40 +	params.exec_cost  = ms2ns(40);
  41 +	params.period     = ms2ns(PERIOD);
  42 +	params.release_policy = TASK_PERIODIC;
  43 +
  44 +	SYSCALL( set_rt_task_param(gettid(), &params) );
  45 +	SYSCALL( be_migrate_to_cpu(params.cpu) );
  46 +	SYSCALL( task_mode(LITMUS_RT_TASK) );
  47 +
  48 +	start = wctime();
  49 +	for (i = 0; i < JOBS; i++)
  50 +		SYSCALL( sleep_next_period() );
  51 +	end  = wctime();
  52 +
  53 +	SYSCALL( task_mode(BACKGROUND_TASK) );
  54 +
  55 +	actual_delta_ms = (end - start) * 1000.0;
  56 +	if (fabs(JOBS * PERIOD - actual_delta_ms) > ACCEPTABLE_MARGIN)
  57 +		fprintf(stderr, "actual_delta_ms:%.4f  expected:%.4f\n",
  58 +			actual_delta_ms, (double) (JOBS * PERIOD));
  59 +	ASSERT( fabs(JOBS * PERIOD - actual_delta_ms) <= ACCEPTABLE_MARGIN);
  60 +}
  61 +
  62 +TESTCASE(jobs_are_rate_limited_synch, LITMUS,
  63 +	 "periodic jobs are rate-limited (w/ synchronous release)")
  64 +{
  65 +	struct rt_task params;
  66 +	double start, end, actual_delta_ms;
  67 +	int i;
  68 +	int child, status, waiters;
  69 +	lt_t delay = ms2ns(100);
  70 +
  71 +	child = FORK_TASK(
  72 +		init_rt_task_param(&params);
  73 +		params.cpu        = 0;
  74 +		params.exec_cost  = ms2ns(5);
  75 +		params.period     = ms2ns(PERIOD);
  76 +		params.release_policy = TASK_PERIODIC;
  77 +
  78 +		SYSCALL( set_rt_task_param(gettid(), &params) );
  79 +		SYSCALL( be_migrate_to_cpu(params.cpu) );
  80 +		SYSCALL( task_mode(LITMUS_RT_TASK) );
  81 +
  82 +		SYSCALL(  wait_for_ts_release() );
  83 +
  84 +		start = wctime();
  85 +		for (i = 0; i < JOBS; i++)
  86 +			SYSCALL( sleep_next_period() );
  87 +		end  = wctime();
  88 +
  89 +		SYSCALL( task_mode(BACKGROUND_TASK) );
  90 +
  91 +		actual_delta_ms = (end - start) * 1000.0;
  92 +		if (fabs(JOBS * PERIOD - actual_delta_ms) > ACCEPTABLE_MARGIN)
  93 +			fprintf(stderr, "actual_delta_ms:%.4f  expected:%.4f\n",
  94 +				actual_delta_ms, (double) (JOBS * PERIOD));
  95 +		ASSERT( fabs(JOBS * PERIOD - actual_delta_ms) <= ACCEPTABLE_MARGIN);
  96 +	);
  97 +
  98 +	do {
  99 +		waiters = get_nr_ts_release_waiters();
 100 +		ASSERT( waiters >= 0 );
 101 +	} while (waiters != 1);
 102 +
 103 +	waiters = release_ts(&delay);
 104 +
 105 +
 106 +	/* wait for child to exit */
 107 +	SYSCALL( waitpid(child, &status, 0) );
 108 +	ASSERT( status == 0 );
 109 +}
 110 -- 
 111 1.9.1
 112 
 113 
 114 From a83d1f59605a06fc22b399b38ce4b831d38b6442 Mon Sep 17 00:00:00 2001
 115 From: Bjoern Brandenburg <bbb@mpi-sws.org>
 116 Date: Thu, 17 Jul 2014 18:01:42 +0200
 117 Subject: [PATCH 2/7] Add reservation-related system calls
 118 
 119 ---
 120  include/litmus.h |  5 +++++
 121  src/syscalls.c   | 10 ++++++++++
 122  2 files changed, 15 insertions(+)
 123 
 124 diff --git a/include/litmus.h b/include/litmus.h
 125 index f99ccec..3bd6b92 100644
 126 --- a/include/litmus.h
 127 +++ b/include/litmus.h
 128 @@ -416,6 +416,11 @@ int null_call(cycles_t *timestamp);
 129   */
 130  struct control_page* get_ctrl_page(void);
 131  
 132 +int reservation_create(int rtype, void *config);
 133 +
 134 +int reservation_destroy(unsigned int reservation_id, int cpu);
 135 +
 136 +
 137  #ifdef __cplusplus
 138  }
 139  #endif
 140 diff --git a/src/syscalls.c b/src/syscalls.c
 141 index c68f15b..fbb8604 100644
 142 --- a/src/syscalls.c
 143 +++ b/src/syscalls.c
 144 @@ -86,3 +86,13 @@ int null_call(cycles_t *timestamp)
 145  {
 146  	return syscall(__NR_null_call, timestamp);
 147  }
 148 +
 149 +int reservation_create(int rtype, void *config)
 150 +{
 151 +	return syscall(__NR_reservation_create, rtype, config);
 152 +}
 153 +
 154 +int reservation_destroy(unsigned int reservation_id, int cpu)
 155 +{
 156 +	return syscall(__NR_reservation_destroy, reservation_id, cpu);
 157 +}
 158 -- 
 159 1.9.1
 160 
 161 
 162 From 8d323049edd004c25f370468aa30cdf1ba76e735 Mon Sep 17 00:00:00 2001
 163 From: Bjoern Brandenburg <bbb@mpi-sws.org>
 164 Date: Tue, 22 Jul 2014 07:46:57 +0200
 165 Subject: [PATCH 3/7] Add -r (reservation) and -v (verbose) flags to rtspin
 166 
 167 The -r flag allows specifying a "virtual CPU" (in addition to a
 168 physcial CPU to migrate to) that may be interpreted by a scheduler
 169 plugin to refer to a reservation to which the task should be added.
 170 
 171 The -v flag causes rtspin to output timing information on stdout and
 172 can be useful for early-stage plugin debugging (to see that something
 173 is happening at all).
 174 ---
 175  bin/rtspin.c | 35 ++++++++++++++++++++++++++++-------
 176  1 file changed, 28 insertions(+), 7 deletions(-)
 177 
 178 diff --git a/bin/rtspin.c b/bin/rtspin.c
 179 index b4156cc..ea7f192 100644
 180 --- a/bin/rtspin.c
 181 +++ b/bin/rtspin.c
 182 @@ -184,7 +184,7 @@ static int job(double exec_time, double program_end, int lock_od, double cs_leng
 183  	}
 184  }
 185  
 186 -#define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:"
 187 +#define OPTSTR "p:c:wlveo:f:s:q:r:X:L:Q:v"
 188  int main(int argc, char** argv)
 189  {
 190  	int ret;
 191 @@ -194,6 +194,7 @@ int main(int argc, char** argv)
 192  	unsigned int priority = LITMUS_LOWEST_PRIORITY;
 193  	int migrate = 0;
 194  	int cluster = 0;
 195 +	int reservation = -1;
 196  	int opt;
 197  	int wait = 0;
 198  	int test_loop = 0;
 199 @@ -207,6 +208,9 @@ int main(int argc, char** argv)
 200  	int cur_job = 0, num_jobs = 0;
 201  	struct rt_task param;
 202  
 203 +	int verbose = 0;
 204 +	unsigned int job_no;
 205 +
 206  	/* locking */
 207  	int lock_od = -1;
 208  	int resource_id = 0;
 209 @@ -225,6 +229,9 @@ int main(int argc, char** argv)
 210  			cluster = atoi(optarg);
 211  			migrate = 1;
 212  			break;
 213 +		case 'r':
 214 +			reservation = atoi(optarg);
 215 +			break;
 216  		case 'q':
 217  			priority = atoi(optarg);
 218  			if (!litmus_is_valid_fixed_prio(priority))
 219 @@ -265,6 +272,9 @@ int main(int argc, char** argv)
 220  			if (resource_id <= 0 && strcmp(optarg, "0"))
 221  				usage("Invalid resource ID.");
 222  			break;
 223 +		case 'v':
 224 +			verbose = 1;
 225 +			break;
 226  		case ':':
 227  			usage("Argument missing.");
 228  			break;
 229 @@ -334,14 +344,19 @@ int main(int argc, char** argv)
 230  	param.cls = class;
 231  	param.budget_policy = (want_enforcement) ?
 232  			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
 233 -	if (migrate)
 234 -		param.cpu = domain_to_first_cpu(cluster);
 235 +	if (migrate) {
 236 +		if (reservation >= 0)
 237 +			param.cpu = reservation;
 238 +		else
 239 +			param.cpu = domain_to_first_cpu(cluster);
 240 +	}
 241  	ret = set_rt_task_param(gettid(), &param);
 242  	if (ret < 0)
 243  		bail_out("could not setup rt task params");
 244  
 245  	init_litmus();
 246  
 247 +	start = wctime();
 248  	ret = task_mode(LITMUS_RT_TASK);
 249  	if (ret != 0)
 250  		bail_out("could not become RT task");
 251 @@ -355,14 +370,14 @@ int main(int argc, char** argv)
 252  		}
 253  	}
 254  
 255 +
 256  	if (wait) {
 257  		ret = wait_for_ts_release();
 258  		if (ret != 0)
 259  			bail_out("wait_for_ts_release()");
 260 +		start = wctime();
 261  	}
 262  
 263 -	start = wctime();
 264 -
 265  	if (file) {
 266  		/* use times read from the CSV file */
 267  		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
 268 @@ -372,8 +387,14 @@ int main(int argc, char** argv)
 269  			    lock_od, cs_length * 0.001);
 270  		}
 271  	} else {
 272 -		/* convert to seconds and scale */
 273 -		while (job(wcet_ms * 0.001 * scale, start + duration,
 274 +		do {
 275 +			if (verbose) {
 276 +				get_job_no(&job_no);
 277 +				printf("rtspin/%d:%u @ %.4fms\n", gettid(),
 278 +					job_no, (wctime() - start) * 1000);
 279 +			}
 280 +			/* convert to seconds and scale */
 281 +		} while (job(wcet_ms * 0.001 * scale, start + duration,
 282  			   lock_od, cs_length * 0.001));
 283  	}
 284  
 285 -- 
 286 1.9.1
 287 
 288 
 289 From a2675ecbfb665f5f9de5f541d7d22c6710b4ff97 Mon Sep 17 00:00:00 2001
 290 From: Bjoern Brandenburg <bbb@mpi-sws.org>
 291 Date: Tue, 22 Jul 2014 07:53:03 +0200
 292 Subject: [PATCH 4/7] Add resctrl, a tool for setting up reservations
 293 
 294 resctrl is a new tool intended to configure reservations in
 295 reservation-aware plugins. For now, it only supports the partitioned
 296 reservations (P-RES) plugin.
 297 
 298 (While at it, also update .gitignore)
 299 ---
 300  .gitignore    |   7 ++
 301  Makefile      |   5 +-
 302  bin/resctrl.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 303  3 files changed, 246 insertions(+), 1 deletion(-)
 304  create mode 100644 bin/resctrl.c
 305 
 306 diff --git a/.gitignore b/.gitignore
 307 index a52500b..f79d4fa 100644
 308 --- a/.gitignore
 309 +++ b/.gitignore
 310 @@ -3,10 +3,13 @@
 311  *.a
 312  
 313  
 314 +# editor backup files
 315 +*~
 316  
 317  # generated files
 318  tests/test_catalog.inc
 319  *.d
 320 +*.d.*
 321  docs/
 322  
 323  # executables
 324 @@ -23,6 +26,8 @@ showst
 325  rtspin
 326  cycles
 327  measure_syscall
 328 +uncache
 329 +resctrl
 330  
 331  # build system files
 332  .config
 333 @@ -32,3 +37,5 @@ test_catalog.inc
 334  # files copied in from the kernel tree
 335  include/litmus
 336  arch/*/include/asm
 337 +arch/x86/include/generated
 338 +arch/x86/include/uapi
 339 diff --git a/Makefile b/Makefile
 340 index 4742fd2..34c428f 100644
 341 --- a/Makefile
 342 +++ b/Makefile
 343 @@ -73,7 +73,7 @@ AR  := ${CROSS_COMPILE}${AR}
 344  
 345  all     = lib ${rt-apps}
 346  rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
 347 -	  base_mt_task uncache runtests
 348 +	  base_mt_task uncache runtests resctrl
 349  
 350  .PHONY: all lib clean dump-config TAGS tags cscope help doc
 351  
 352 @@ -234,6 +234,9 @@ obj-release_ts = release_ts.o
 353  obj-measure_syscall = null_call.o
 354  lib-measure_syscall = -lm
 355  
 356 +obj-resctrl = resctrl.o
 357 +
 358 +
 359  # ##############################################################################
 360  # Build everything that depends on liblitmus.
 361  
 362 diff --git a/bin/resctrl.c b/bin/resctrl.c
 363 new file mode 100644
 364 index 0000000..917f49a
 365 --- /dev/null
 366 +++ b/bin/resctrl.c
 367 @@ -0,0 +1,235 @@
 368 +#include <stdio.h>
 369 +#include <stdlib.h>
 370 +#include <string.h>
 371 +#include <unistd.h>
 372 +#include <limits.h>
 373 +#include <signal.h>
 374 +
 375 +#include <sched.h>
 376 +
 377 +#include "litmus.h"
 378 +#include "common.h"
 379 +
 380 +const char *usage_msg =
 381 +	"Usage: resctrl OPTIONS [INTERVAL-START,INTERVAL-END]*\n"
 382 +	"    -n ID             create new reservation with id ID\n"
 383 +	"    -a PID            attach already-running process PID to reservation\n"
 384 +	"    -r ID             specify which reservation to attach to (not needed with -n)\n"
 385 +	"    -t TYPE           type of reservation (polling-periodic, polling-sporadic, table-driven)\n"
 386 +	"    -c CPU            physical partition or cluster to assign to\n"
 387 +	"    -b BUDGET         polling reservation budget (in ms, default: 10ms)\n"
 388 +	"    -p PERIOD         polling reservation period (in ms, default: 100ms)\n"
 389 +	"    -d DEADLINE       relative deadline, implicit by default (in ms)\n"
 390 +	"    -o OFFSET         offset (also known as phase), zero by default (in ms)\n"
 391 +	"    -q PRIORITY       priority to use (EDF by default, max=0)\n"
 392 +	"    -m MAJOR-CYCLE    major cycle length (in ms, for table-driven reservations) \n"
 393 +	"\n";
 394 +
 395 +void usage(char *error) {
 396 +	fprintf(stderr, "%s\n%s", error, usage_msg);
 397 +	exit(1);
 398 +}
 399 +
 400 +
 401 +static void attach_task(int attach_pid, struct reservation_config *config)
 402 +{
 403 +	int ret;
 404 +	struct rt_task param;
 405 +	struct sched_param linux_param;
 406 +
 407 +	ret = be_migrate_thread_to_cpu(attach_pid, config->cpu);
 408 +	if (ret < 0) {
 409 +		fprintf(stderr, "failed to migrate task %d to CPU %d\n",
 410 +			attach_pid, config->cpu);
 411 +		exit(4);
 412 +	}
 413 +
 414 +	init_rt_task_param(&param);
 415 +	/* dummy values */
 416 +	param.exec_cost = ms2ns(100);
 417 +	param.period    = ms2ns(100);
 418 +	/* specify reservation as "virtual" CPU */
 419 +	param.cpu       = config->id;
 420 +
 421 +	ret = set_rt_task_param(attach_pid, &param);
 422 +	if (ret < 0) {
 423 +		fprintf(stderr, "failed to set RT task parameters for task %d (%m)\n",
 424 +			attach_pid);
 425 +		exit(2);
 426 +	}
 427 +
 428 +	linux_param.sched_priority = 0;
 429 +	ret = sched_setscheduler(attach_pid, SCHED_LITMUS, &linux_param);
 430 +	if (ret < 0) {
 431 +		fprintf(stderr, "failed to transition task %d to LITMUS^RT class (%m)\n",
 432 +			attach_pid);
 433 +		exit(3);
 434 +	}
 435 +}
 436 +
 437 +static struct lt_interval* parse_td_intervals(int argc, char** argv,
 438 +	unsigned int *num_intervals, lt_t major_cycle)
 439 +{
 440 +	int i, matched;
 441 +	struct lt_interval *slots = malloc(sizeof(slots[0]) * argc);
 442 +	double start, end;
 443 +
 444 +	*num_intervals = 0;
 445 +	for (i = 0; i < argc; i++) {
 446 +		matched = sscanf(argv[i], "[%lf,%lf]", &start, &end);
 447 +		if (matched != 2) {
 448 +			fprintf(stderr, "could not parse '%s' as interval\n", argv[i]);
 449 +			exit(5);
 450 +		}
 451 +		if (start < 0) {
 452 +			fprintf(stderr, "interval %s: must not start before zero\n", argv[i]);
 453 +			exit(5);
 454 +		}
 455 +		if (end <= start) {
 456 +			fprintf(stderr, "interval %s: end before start\n", argv[i]);
 457 +			exit(5);
 458 +		}
 459 +
 460 +		slots[i].start = ms2ns(start);
 461 +		slots[i].end   = ms2ns(end);
 462 +
 463 +		if (i > 0 && slots[i - 1].end >= slots[i].start) {
 464 +			fprintf(stderr, "interval %s: overlaps with previous interval\n", argv[i]);
 465 +			exit(5);
 466 +		}
 467 +
 468 +		if (slots[i].end >= major_cycle) {
 469 +			fprintf(stderr, "interval %s: exceeds major cycle length\n", argv[i]);
 470 +			exit(5);
 471 +		}
 472 +
 473 +		(*num_intervals)++;
 474 +	}
 475 +
 476 +	return slots;
 477 +}
 478 +
 479 +#define OPTSTR "n:a:r:t:c:b:p:d:o:q:m:h"
 480 +
 481 +int main(int argc, char** argv)
 482 +{
 483 +	int ret, opt;
 484 +	double budget_ms, period_ms, offset_ms, deadline_ms, major_cycle_ms;
 485 +	int create_new = 0;
 486 +	int attach_pid = 0;
 487 +	int res_type = SPORADIC_POLLING;
 488 +
 489 +	struct reservation_config config;
 490 +
 491 +	/* Reasonable defaults */
 492 +	offset_ms      =    0;
 493 +	deadline_ms    =    0;
 494 +	budget_ms      =   10;
 495 +	period_ms      =  100;
 496 +	major_cycle_ms = 1000;
 497 +
 498 +	config.id = 0;
 499 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
 500 +	config.cpu = 0;
 501 +
 502 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
 503 +		switch (opt) {
 504 +		case 'b':
 505 +			budget_ms = atof(optarg);
 506 +			break;
 507 +		case 'p':
 508 +			period_ms = atof(optarg);
 509 +			break;
 510 +		case 'd':
 511 +			deadline_ms = atof(optarg);
 512 +			if (deadline_ms <= 0) {
 513 +				usage("The relative deadline must be a positive"
 514 +					" number.");
 515 +			}
 516 +			break;
 517 +		case 'o':
 518 +			offset_ms = atof(optarg);
 519 +			break;
 520 +		case 'm':
 521 +			major_cycle_ms = atof(optarg);
 522 +			break;
 523 +
 524 +		case 'q':
 525 +			config.priority = atoi(optarg);
 526 +			break;
 527 +		case 'c':
 528 +			config.cpu = atoi(optarg);
 529 +			break;
 530 +
 531 +		case 'n':
 532 +			create_new = 1;
 533 +			config.id  = atoi(optarg);
 534 +			break;
 535 +		case 'a':
 536 +			attach_pid = atoi(optarg);
 537 +			if (!attach_pid)
 538 +				usage("-a: invalid PID");
 539 +			break;
 540 +
 541 +		case 'r':
 542 +			config.id  = atoi(optarg);
 543 +			break;
 544 +
 545 +		case 't':
 546 +			if (strcmp(optarg, "polling-periodic") == 0) {
 547 +				res_type = PERIODIC_POLLING;
 548 +			} else if (strcmp(optarg, "polling-sporadic") == 0) {
 549 +				res_type = SPORADIC_POLLING;
 550 +			}  else if (strcmp(optarg, "table-driven") == 0) {
 551 +				res_type = TABLE_DRIVEN;
 552 +			} else {
 553 +				usage("Unknown reservation type.");
 554 +			}
 555 +			break;
 556 +
 557 +		case 'h':
 558 +			usage("");
 559 +			break;
 560 +		case ':':
 561 +			usage("Argument missing.");
 562 +			break;
 563 +		case '?':
 564 +		default:
 565 +			usage("Bad argument.");
 566 +			break;
 567 +		}
 568 +	}
 569 +
 570 +	if (res_type != TABLE_DRIVEN) {
 571 +		config.polling_params.budget = ms2ns(budget_ms);
 572 +		config.polling_params.period = ms2ns(period_ms);
 573 +		config.polling_params.offset = ms2ns(offset_ms);
 574 +		config.polling_params.relative_deadline = ms2ns(deadline_ms);
 575 +		if (config.polling_params.budget > config.polling_params.period) {
 576 +			usage("The budget must not exceed the period.");
 577 +		}
 578 +	} else {
 579 +		config.table_driven_params.major_cycle_length = ms2ns(major_cycle_ms);
 580 +		argc -= optind;
 581 +		argv += optind;
 582 +		config.table_driven_params.intervals = parse_td_intervals(
 583 +			argc, argv, &config.table_driven_params.num_intervals,
 584 +			config.table_driven_params.major_cycle_length);
 585 +		if (!config.table_driven_params.num_intervals)
 586 +			usage("Table-driven reservations require at least one interval to be specified.");
 587 +	}
 588 +
 589 +	if (create_new) {
 590 +		ret = reservation_create(res_type, &config);
 591 +		if (ret < 0) {
 592 +			fprintf(stderr, "failed to create reservation %u (%m)\n",
 593 +				config.id);
 594 +			exit(1);
 595 +		}
 596 +	}
 597 +
 598 +	if (attach_pid)
 599 +		attach_task(attach_pid, &config);
 600 +
 601 +	return 0;
 602 +}
 603 -- 
 604 1.9.1
 605 
 606 
 607 From d7d397d028d6c755cff140f2ef54537f608d3e62 Mon Sep 17 00:00:00 2001
 608 From: Bjoern Brandenburg <bbb@mpi-sws.org>
 609 Date: Mon, 8 Sep 2014 17:42:49 +0200
 610 Subject: [PATCH 5/7] resctrl: default to max. priority for table-driven
 611  reservations
 612 
 613 Table-driven reservations should always have the maximum fixed
 614 priority. Thus default to this behavior, both for convenience and to
 615 avoid accidental misconfiguration.
 616 ---
 617  bin/resctrl.c | 9 ++++++++-
 618  1 file changed, 8 insertions(+), 1 deletion(-)
 619 
 620 diff --git a/bin/resctrl.c b/bin/resctrl.c
 621 index 917f49a..63b5054 100644
 622 --- a/bin/resctrl.c
 623 +++ b/bin/resctrl.c
 624 @@ -21,7 +21,7 @@ const char *usage_msg =
 625  	"    -p PERIOD         polling reservation period (in ms, default: 100ms)\n"
 626  	"    -d DEADLINE       relative deadline, implicit by default (in ms)\n"
 627  	"    -o OFFSET         offset (also known as phase), zero by default (in ms)\n"
 628 -	"    -q PRIORITY       priority to use (EDF by default, max=0)\n"
 629 +	"    -q PRIORITY       priority to use (EDF by default, highest priority = 1)\n"
 630  	"    -m MAJOR-CYCLE    major cycle length (in ms, for table-driven reservations) \n"
 631  	"\n";
 632  
 633 @@ -156,6 +156,8 @@ int main(int argc, char** argv)
 634  
 635  		case 'q':
 636  			config.priority = atoi(optarg);
 637 +			if (!config.priority)
 638 +				usage("-q: invalid priority");
 639  			break;
 640  		case 'c':
 641  			config.cpu = atoi(optarg);
 642 @@ -182,6 +184,11 @@ int main(int argc, char** argv)
 643  				res_type = SPORADIC_POLLING;
 644  			}  else if (strcmp(optarg, "table-driven") == 0) {
 645  				res_type = TABLE_DRIVEN;
 646 +				/* Default for table-driven reservations to
 647 +				 * maximum priority. EDF has not meaning for
 648 +				 * table-driven reservations. */
 649 +				if (config.priority == LITMUS_NO_PRIORITY)
 650 +					config.priority = LITMUS_HIGHEST_PRIORITY;
 651  			} else {
 652  				usage("Unknown reservation type.");
 653  			}
 654 -- 
 655 1.9.1
 656 
 657 
 658 From 5fd42b4dc877890668affe69f8cecc968e277148 Mon Sep 17 00:00:00 2001
 659 From: Namhoon Kim <namhoonk@cs.unc.edu>
 660 Date: Thu, 8 Jan 2015 14:04:12 -0500
 661 Subject: [PATCH 6/7] Added mc2spin
 662 
 663 ---
 664  Makefile         |   7 +-
 665  bin/mc2spin.c    | 541 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 666  include/litmus.h |   3 +
 667  mc2spin          | Bin 0 -> 102692 bytes
 668  src/syscalls.c   |   5 +
 669  5 files changed, 554 insertions(+), 2 deletions(-)
 670  create mode 100644 bin/mc2spin.c
 671  create mode 100755 mc2spin
 672 
 673 diff --git a/Makefile b/Makefile
 674 index 34c428f..70e79d4 100644
 675 --- a/Makefile
 676 +++ b/Makefile
 677 @@ -73,7 +73,7 @@ AR  := ${CROSS_COMPILE}${AR}
 678  
 679  all     = lib ${rt-apps}
 680  rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
 681 -	  base_mt_task uncache runtests resctrl
 682 +	  base_mt_task uncache runtests resctrl mc2spin
 683  
 684  .PHONY: all lib clean dump-config TAGS tags cscope help doc
 685  
 686 @@ -168,7 +168,8 @@ litmus-headers = \
 687  	include/litmus/rt_param.h \
 688  	include/litmus/fpmath.h \
 689  	include/litmus/unistd_32.h \
 690 -	include/litmus/unistd_64.h
 691 +	include/litmus/unistd_64.h \
 692 +	include/litmus/mc2_common.h
 693  
 694  unistd-headers = \
 695    $(foreach file,${unistd-${ARCH}},arch/${include-${ARCH}}/include/$(file))
 696 @@ -236,6 +237,8 @@ lib-measure_syscall = -lm
 697  
 698  obj-resctrl = resctrl.o
 699  
 700 +obj-mc2spin = mc2spin.o common.o
 701 +lib-mc2spin = -lrt
 702  
 703  # ##############################################################################
 704  # Build everything that depends on liblitmus.
 705 diff --git a/bin/mc2spin.c b/bin/mc2spin.c
 706 new file mode 100644
 707 index 0000000..1ef3082
 708 --- /dev/null
 709 +++ b/bin/mc2spin.c
 710 @@ -0,0 +1,541 @@
 711 +#include <sys/time.h>
 712 +
 713 +#include <stdio.h>
 714 +#include <stdlib.h>
 715 +#include <unistd.h>
 716 +#include <time.h>
 717 +#include <string.h>
 718 +#include <assert.h>
 719 +#include <limits.h>
 720 +
 721 +
 722 +#include "litmus.h"
 723 +#include "common.h"
 724 +
 725 +
 726 +
 727 +static void usage(char *error) {
 728 +	fprintf(stderr, "Error: %s\n", error);
 729 +	fprintf(stderr,
 730 +		"Usage:\n"
 731 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
 732 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
 733 +		"	rt_spin -l\n"
 734 +		"\n"
 735 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
 736 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
 737 +		"              [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
 738 +		"              [-i [start,end]:[start,end]...]\n"
 739 +		"\n"
 740 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n"
 741 +		"CRITICAL SECTION LENGTH is in milliseconds.\n");
 742 +	exit(EXIT_FAILURE);
 743 +}
 744 +
 745 +/*
 746 + * returns the character that made processing stop, newline or EOF
 747 + */
 748 +static int skip_to_next_line(FILE *fstream)
 749 +{
 750 +	int ch;
 751 +	for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
 752 +	return ch;
 753 +}
 754 +
 755 +static void skip_comments(FILE *fstream)
 756 +{
 757 +	int ch;
 758 +	for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
 759 +		skip_to_next_line(fstream);
 760 +	ungetc(ch, fstream);
 761 +}
 762 +
 763 +static void get_exec_times(const char *file, const int column,
 764 +			   int *num_jobs,    double **exec_times)
 765 +{
 766 +	FILE *fstream;
 767 +	int  cur_job, cur_col, ch;
 768 +	*num_jobs = 0;
 769 +
 770 +	fstream = fopen(file, "r");
 771 +	if (!fstream)
 772 +		bail_out("could not open execution time file");
 773 +
 774 +	/* figure out the number of jobs */
 775 +	do {
 776 +		skip_comments(fstream);
 777 +		ch = skip_to_next_line(fstream);
 778 +		if (ch != EOF)
 779 +			++(*num_jobs);
 780 +	} while (ch != EOF);
 781 +
 782 +	if (-1 == fseek(fstream, 0L, SEEK_SET))
 783 +		bail_out("rewinding file failed");
 784 +
 785 +	/* allocate space for exec times */
 786 +	*exec_times = calloc(*num_jobs, sizeof(*exec_times));
 787 +	if (!*exec_times)
 788 +		bail_out("couldn't allocate memory");
 789 +
 790 +	for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
 791 +
 792 +		skip_comments(fstream);
 793 +
 794 +		for (cur_col = 1; cur_col < column; ++cur_col) {
 795 +			/* discard input until we get to the column we want */
 796 +			int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
 797 +		}
 798 +
 799 +		/* get the desired exec. time */
 800 +		if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
 801 +			fprintf(stderr, "invalid execution time near line %d\n",
 802 +					cur_job);
 803 +			exit(EXIT_FAILURE);
 804 +		}
 805 +
 806 +		skip_to_next_line(fstream);
 807 +	}
 808 +
 809 +	assert(cur_job == *num_jobs);
 810 +	fclose(fstream);
 811 +}
 812 +
 813 +#define NUMS 4096
 814 +static int num[NUMS];
 815 +static char* progname;
 816 +
 817 +static int loop_once(void)
 818 +{
 819 +	int i, j = 0;
 820 +	for (i = 0; i < NUMS; i++)
 821 +		j += num[i]++;
 822 +	return j;
 823 +}
 824 +
 825 +static int loop_for(double exec_time, double emergency_exit)
 826 +{
 827 +	double last_loop = 0, loop_start;
 828 +	int tmp = 0;
 829 +
 830 +	double start = cputime();
 831 +	double now = cputime();
 832 +
 833 +	while (now + last_loop < start + exec_time) {
 834 +		loop_start = now;
 835 +		tmp += loop_once();
 836 +		now = cputime();
 837 +		last_loop = now - loop_start;
 838 +		if (emergency_exit && wctime() > emergency_exit) {
 839 +			/* Oops --- this should only be possible if the execution time tracking
 840 +			 * is broken in the LITMUS^RT kernel. */
 841 +			fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
 842 +			fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
 843 +			break;
 844 +		}
 845 +	}
 846 +
 847 +	return tmp;
 848 +}
 849 +
 850 +
 851 +static void debug_delay_loop(void)
 852 +{
 853 +	double start, end, delay;
 854 +
 855 +	while (1) {
 856 +		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
 857 +			start = wctime();
 858 +			loop_for(delay, 0);
 859 +			end = wctime();
 860 +			printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
 861 +			       delay,
 862 +			       end - start,
 863 +			       end - start - delay,
 864 +			       100 * (end - start - delay) / delay);
 865 +		}
 866 +	}
 867 +}
 868 +
 869 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
 870 +{
 871 +	double chunk1, chunk2;
 872 +
 873 +	if (wctime() > program_end)
 874 +		return 0;
 875 +	else {
 876 +		if (lock_od >= 0) {
 877 +			/* simulate critical section somewhere in the middle */
 878 +			chunk1 = drand48() * (exec_time - cs_length);
 879 +			chunk2 = exec_time - cs_length - chunk1;
 880 +
 881 +			/* non-critical section */
 882 +			loop_for(chunk1, program_end + 1);
 883 +
 884 +			/* critical section */
 885 +			litmus_lock(lock_od);
 886 +			loop_for(cs_length, program_end + 1);
 887 +			litmus_unlock(lock_od);
 888 +
 889 +			/* non-critical section */
 890 +			loop_for(chunk2, program_end + 2);
 891 +		} else {
 892 +			loop_for(exec_time, program_end + 1);
 893 +		}
 894 +		sleep_next_period();
 895 +		return 1;
 896 +	}
 897 +}
 898 +
 899 +struct lt_interval* parse_td_intervals(int num, char* optarg, unsigned int *num_intervals)
 900 +{
 901 +	int i, matched;
 902 +	struct lt_interval *slots = malloc(sizeof(slots[0]) * num);
 903 +	char** arg = (char**)malloc(sizeof(char*) * num);
 904 +	char *token, *saveptr;
 905 +	double start, end;
 906 +	
 907 +	for (i = 0; i < num; i++) {
 908 +		arg[i] = (char*)malloc(sizeof(char)*100);
 909 +	}
 910 +	
 911 +	i = 0;
 912 +	token = strtok_r(optarg, ":", &saveptr);
 913 +	while(token != NULL) {
 914 +		sprintf(arg[i++], "%s", token);
 915 +		token = strtok_r(NULL, ":", &saveptr);
 916 +	}
 917 +	
 918 +	*num_intervals = 0;
 919 +	
 920 +	for (i=0; i<num; i++) {
 921 +		matched = sscanf(arg[i], "[%lf,%lf]", &start, &end);
 922 +		if (matched != 2) {
 923 +			fprintf(stderr, "could not parse '%s' as interval\n", arg[i]);
 924 +			exit(5);
 925 +		}
 926 +		if (start < 0) {
 927 +			fprintf(stderr, "interval %s: must not start before zero\n", arg[i]);
 928 +			exit(5);
 929 +		}
 930 +		if (end <= start) {
 931 +			fprintf(stderr, "interval %s: end before start\n", arg[i]);
 932 +			exit(5);
 933 +		}
 934 +
 935 +		slots[i].start = ms2ns(start);
 936 +		slots[i].end   = ms2ns(end);
 937 +
 938 +		if (i > 0 && slots[i - 1].end >= slots[i].start) {
 939 +			fprintf(stderr, "interval %s: overlaps with previous interval\n", arg[i]);
 940 +			exit(5);
 941 +		}
 942 +
 943 +		(*num_intervals)++;
 944 +	}
 945 +	
 946 +	for (i=0; i<num; i++) {
 947 +		free(arg[i]);
 948 +	}
 949 +	free(arg);
 950 +	return slots;
 951 +}
 952 +
 953 +#define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:vh:m:i:b:"
 954 +int main(int argc, char** argv)
 955 +{
 956 +	int ret;
 957 +	lt_t wcet;
 958 +	lt_t period;
 959 +	lt_t hyperperiod;
 960 +	lt_t budget;
 961 +	double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
 962 +	unsigned int priority = LITMUS_LOWEST_PRIORITY;
 963 +	int migrate = 0;
 964 +	int cluster = 0;
 965 +	int opt;
 966 +	int wait = 0;
 967 +	int test_loop = 0;
 968 +	int column = 1;
 969 +	const char *file = NULL;
 970 +	int want_enforcement = 0;
 971 +	double duration = 0, start = 0;
 972 +	double *exec_times = NULL;
 973 +	double scale = 1.0;
 974 +	task_class_t class = RT_CLASS_HARD;
 975 +	int cur_job = 0, num_jobs = 0;
 976 +	struct rt_task param;
 977 +	struct mc2_task mc2_param;
 978 +	struct reservation_config config;
 979 +	int res_type = SPORADIC_POLLING;
 980 +	int n_str, num_int = 0;
 981 +
 982 +	int verbose = 0;
 983 +	unsigned int job_no;
 984 +
 985 +	/* locking */
 986 +	int lock_od = -1;
 987 +	int resource_id = 0;
 988 +	const char *lock_namespace = "./rtspin-locks";
 989 +	int protocol = -1;
 990 +	double cs_length = 1; /* millisecond */
 991 +
 992 +	progname = argv[0];
 993 +
 994 +	/* default for reservation */
 995 +	config.id = 0;
 996 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
 997 +	config.cpu = 0;
 998 +	
 999 +	mc2_param.crit = CRIT_LEVEL_C;
1000 +	
1001 +	hyperperiod_ms = 1000;
1002 +	budget_ms = 10;
1003 +	
1004 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1005 +		switch (opt) {
1006 +		case 'w':
1007 +			wait = 1;
1008 +			break;
1009 +		case 'p':
1010 +			cluster = atoi(optarg);
1011 +			migrate = 1;
1012 +			config.cpu = cluster;
1013 +			break;
1014 +		case 'q':
1015 +			priority = atoi(optarg);
1016 +			if (!litmus_is_valid_fixed_prio(priority))
1017 +				usage("Invalid priority.");
1018 +			break;
1019 +		case 'c':
1020 +			class = str2class(optarg);
1021 +			if (class == -1)
1022 +				usage("Unknown task class.");
1023 +			break;
1024 +		case 'e':
1025 +			want_enforcement = 1;
1026 +			break;
1027 +		case 'l':
1028 +			test_loop = 1;
1029 +			break;
1030 +		case 'o':
1031 +			column = atoi(optarg);
1032 +			break;
1033 +		case 'f':
1034 +			file = optarg;
1035 +			break;
1036 +		case 's':
1037 +			scale = atof(optarg);
1038 +			break;
1039 +		case 'X':
1040 +			protocol = lock_protocol_for_name(optarg);
1041 +			if (protocol < 0)
1042 +				usage("Unknown locking protocol specified.");
1043 +			break;
1044 +		case 'L':
1045 +			cs_length = atof(optarg);
1046 +			if (cs_length <= 0)
1047 +				usage("Invalid critical section length.");
1048 +			break;
1049 +		case 'Q':
1050 +			resource_id = atoi(optarg);
1051 +			if (resource_id <= 0 && strcmp(optarg, "0"))
1052 +				usage("Invalid resource ID.");
1053 +			break;
1054 +		case 'v':
1055 +			verbose = 1;
1056 +			break;
1057 +		case 'm':
1058 +			mc2_param.crit = atoi(optarg);
1059 +			if (mc2_param.crit == CRIT_LEVEL_A) {
1060 +				res_type = TABLE_DRIVEN;
1061 +			}
1062 +			else if (mc2_param.crit == CRIT_LEVEL_B) {
1063 +				res_type = PERIODIC_POLLING;
1064 +			}
1065 +			else
1066 +				usage("Invalid criticality level.");
1067 +			break;
1068 +		case 'h':
1069 +			hyperperiod_ms = atof(optarg);
1070 +			break;
1071 +		case 'b':
1072 +			budget_ms = atof(optarg);
1073 +			break;
1074 +		case 'i':
1075 +			n_str = strlen(optarg);
1076 +			while(n_str--) {
1077 +				if (optarg[n_str] == ',')
1078 +					num_int++;
1079 +			}
1080 +			if (!num_int)
1081 +				usage("Bad argument.");
1082 +			config.table_driven_params.intervals = parse_td_intervals(num_int, optarg, &config.table_driven_params.num_intervals);
1083 +			break;
1084 +		case ':':
1085 +			usage("Argument missing.");
1086 +			break;
1087 +		case '?':
1088 +		default:
1089 +			usage("Bad argument.");
1090 +			break;
1091 +		}
1092 +	}
1093 +
1094 +	if (test_loop) {
1095 +		debug_delay_loop();
1096 +		return 0;
1097 +	}
1098 +
1099 +	srand(getpid());
1100 +
1101 +	if (file) {
1102 +		get_exec_times(file, column, &num_jobs, &exec_times);
1103 +
1104 +		if (argc - optind < 2)
1105 +			usage("Arguments missing.");
1106 +
1107 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
1108 +			/* convert the execution time to seconds */
1109 +			duration += exec_times[cur_job] * 0.001;
1110 +		}
1111 +	} else {
1112 +		/*
1113 +		 * if we're not reading from the CSV file, then we need
1114 +		 * three parameters
1115 +		 */
1116 +		if (argc - optind < 3)
1117 +			usage("Arguments missing.");
1118 +	}
1119 +
1120 +	wcet_ms   = atof(argv[optind + 0]);
1121 +	period_ms = atof(argv[optind + 1]);
1122 +
1123 +	wcet   = ms2ns(wcet_ms);
1124 +	period = ms2ns(period_ms);
1125 +	budget = ms2ns(budget_ms);
1126 +	hyperperiod = ms2ns(hyperperiod_ms);
1127 +	
1128 +	if (wcet <= 0)
1129 +		usage("The worst-case execution time must be a "
1130 +				"positive number.");
1131 +	if (period <= 0)
1132 +		usage("The period must be a positive number.");
1133 +	if (!file && wcet > period) {
1134 +		usage("The worst-case execution time must not "
1135 +				"exceed the period.");
1136 +	}
1137 +
1138 +	if (!file)
1139 +		duration  = atof(argv[optind + 2]);
1140 +	else if (file && num_jobs > 1)
1141 +		duration += period_ms * 0.001 * (num_jobs - 1);
1142 +
1143 +	if (migrate) {
1144 +		ret = be_migrate_to_domain(cluster);
1145 +		if (ret < 0)
1146 +			bail_out("could not migrate to target partition or cluster.");
1147 +	}
1148 +
1149 +	/* reservation config */
1150 +	config.id = gettid();
1151 +	
1152 +	if (hyperperiod%period != 0 ) {
1153 +		bail_out("hyperperiod must be multiple of period");
1154 +	}
1155 +	
1156 +	if (mc2_param.crit == CRIT_LEVEL_A) {
1157 +		config.table_driven_params.major_cycle_length = period;
1158 +	}
1159 +	else if (mc2_param.crit == CRIT_LEVEL_B) {
1160 +		config.polling_params.budget = budget;
1161 +		config.polling_params.period = period;
1162 +		config.polling_params.offset = 0;
1163 +		config.polling_params.relative_deadline = 0;
1164 +		if (config.polling_params.budget > config.polling_params.period) {
1165 +			usage("The budget must not exceed the period.");
1166 +		}
1167 +	}
1168 +	
1169 +	/* create a reservation */
1170 +	ret = reservation_create(res_type, &config);
1171 +	if (ret < 0) {
1172 +		bail_out("failed to create reservation.");
1173 +	}
1174 +	
1175 +	init_rt_task_param(&param);
1176 +	param.exec_cost = wcet;
1177 +	param.period = period;
1178 +	param.priority = priority;
1179 +	param.cls = class;
1180 +	param.release_policy = TASK_PERIODIC;
1181 +	param.budget_policy = (want_enforcement) ?
1182 +			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
1183 +	if (migrate) {
1184 +		param.cpu = gettid();
1185 +	}
1186 +	ret = set_rt_task_param(gettid(), &param);
1187 +	if (ret < 0)
1188 +		bail_out("could not setup rt task params");
1189 +	
1190 +	mc2_param.pid = gettid();
1191 +	mc2_param.hyperperiod = hyperperiod;
1192 +	ret = set_mc2_task_param(gettid(), &mc2_param);
1193 +	if (ret < 0)
1194 +		bail_out("could not setup mc2 task params");
1195 +	init_litmus();
1196 +
1197 +	start = wctime();
1198 +	ret = task_mode(LITMUS_RT_TASK);
1199 +	if (ret != 0)
1200 +		bail_out("could not become RT task");
1201 +
1202 +	if (protocol >= 0) {
1203 +		/* open reference to semaphore */
1204 +		lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
1205 +		if (lock_od < 0) {
1206 +			perror("litmus_open_lock");
1207 +			usage("Could not open lock.");
1208 +		}
1209 +	}
1210 +
1211 +
1212 +	if (wait) {
1213 +		ret = wait_for_ts_release();
1214 +		if (ret != 0)
1215 +			bail_out("wait_for_ts_release()");
1216 +		start = wctime();
1217 +	}
1218 +
1219 +	if (file) {
1220 +		/* use times read from the CSV file */
1221 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
1222 +			/* convert job's length to seconds */
1223 +			job(exec_times[cur_job] * 0.001 * scale,
1224 +			    start + duration,
1225 +			    lock_od, cs_length * 0.001);
1226 +		}
1227 +	} else {
1228 +		do {
1229 +			if (verbose) {
1230 +				get_job_no(&job_no);
1231 +				printf("rtspin/%d:%u @ %.4fms\n", gettid(),
1232 +					job_no, (wctime() - start) * 1000);
1233 +			}
1234 +			/* convert to seconds and scale */
1235 +		} while (job(wcet_ms * 0.001 * scale, start + duration,
1236 +			   lock_od, cs_length * 0.001));
1237 +	}
1238 +
1239 +	ret = task_mode(BACKGROUND_TASK);
1240 +	if (ret != 0)
1241 +		bail_out("could not become regular task (huh?)");
1242 +
1243 +	if (file)
1244 +		free(exec_times);
1245 +
1246 +	reservation_destroy(gettid(), config.cpu);
1247 +	if (mc2_param.crit == CRIT_LEVEL_A) {
1248 +		free(config.table_driven_params.intervals);
1249 +	}
1250 +	return 0;
1251 +}
1252 diff --git a/include/litmus.h b/include/litmus.h
1253 index 3bd6b92..b90a83d 100644
1254 --- a/include/litmus.h
1255 +++ b/include/litmus.h
1256 @@ -40,6 +40,8 @@ extern "C" {
1257  
1258  #include "migration.h"
1259  
1260 +#include "litmus/mc2_common.h"
1261 +
1262  /**
1263   * @private
1264   * Number of semaphore protocol object types
1265 @@ -420,6 +422,7 @@ int reservation_create(int rtype, void *config);
1266  
1267  int reservation_destroy(unsigned int reservation_id, int cpu);
1268  
1269 +int set_mc2_task_param(pid_t pid, struct mc2_task* param);
1270  
1271  #ifdef __cplusplus
1272  }
1273 diff --git a/mc2spin b/mc2spin
1274 new file mode 100755
1275 index 0000000000000000000000000000000000000000..00b20c0223e92547cde52d2546b7ddbcb349c1a1
1276 GIT binary patch
1277 literal 102692
1278 zcmd?S33yc1{WpHkEXhm)nadvbfg~6b5)xzy0b~LJCK?tYAPNW}3q%8n$plbQq5)(K
1279 zDAc7?X~k+4TdUOCiWEuMacK)K)UApeoq!7k1Y9uh=X1`v!;q5y@AtmH|NA`u=lNfr
1280 z%sJovd%kDA=bn36F)n|+O$fufY{pdvq0-(yiBi9Yaqy;#JU%1Ka2r0OpOIihfy;?M
1281 zi_fQXR(f8GS*Z)WyzKaM;4jNYh^dcBIPD=J!?04zI#b%ac=>czrH;u8v{J+HN(ANT
1282 zt1(4_Nav}HPB+paT)teDT5@!ca`9R&Uh`Y&QSF$OTIFNe_*bCIS77r2BJ5*gSZ1u0
1283 zyu70EC-bfNDVgwN*|E|oUj&LN=g<lrxjxBir317dR%+S17IHE!lKa2@F*VD;^0N6u
1284 z2M;VSPAe~4T(c}~S=P|Bp@Y+_E7Au^|H;SDOqeuXN?3990;27X_+!XPkNf;gpl(o8
1285 z&5uv`zL<93%v%<I_2KuV4Z@#QZ=0RSIr449U5UTJ_&Znl%gW)W>U#{@d#?RWVo1^-
1286 ze|@e!(3iaq0ed;(V5q$uz76=jm(g@bD|$X_1;4Wu{M=UT{<{_a*IMCsBCwb9|A|)g
1287 z{IL~1@3g|7)(ZbGTftw~3O>3O{Jd81ZCk;gZN<-PTH!z43O?A1p5CqSf7uHD)mHF_
1288 zTfy5}!6(BXFaBCy$AP$9{Vr}rPrp|1`&!YnrWO8@R`|!Y!vFhL_#0c{U*8J<{jK0P
1289 zwStdprTq^BzZZWkuPLqgQ`!oCB@|pP{?E3;e+~G(EsX+xvK9UsiEnGn8|0Hx)_nIc
1290 z@a>FlMrhhRiMPi2hX4`ZsPWb~{+`xTtMzn|QigHA)^oIl9s}cdRe<AlrZG3KVB*~3
1291 zlB$vgWz~U_s)C7Q%PSU_6co-cFEQrMU9hNP@!aY_VO3!6Tx0IlOXg11d}GTCtE)?@
1292 zmH1_ai^?mCZl1fKBoHWDR6>hIG&t0#4pbFY-fEOAD+?IaRfUU-jnazBlEp?vWuOc|
1293 zWl2?4MU}C*aB)R-c}YnnoTx5ZSW-N<sIsQ896AlCtSl>z#Fti;&{=u}M@tLK%4sD~
1294 zQLK`3W6`3*N<*o+wXCEZCQB+xjZ$bT(&*}vKw)WV+2XRmtwxcuQ?ppo7nLjm5$fUC
1295 z;)=QOpfFHYvDhfBE-AU$s46KerbqCe#uk^OB&8^Nb&0ZF1LI1aG7nWUQ&V12WmH!e
1296 z6)rAi$qTC%fFIRR1-%kk%+L(ZGD??Ll?6&@f^n=UEiSy(Sj5mmt5I56Rkk=#YE<6}
1297 zA;8K8cq42e+>01R)_|_cMTKRHjq1e_!WD31LVn(uv2zEd4@w^r&JPRcu1x2wYr{YF
1298 z%iQJv*)M~)WE`M5@yFEqXVH{qA@Tg>{Lg=eVdBq=znX4kZms}3lZZ=T6;X|pbY5M`
1299 z%Gz>;(HC^$0$s^(H@NO0tmJKB`SaJ#16Hl^ddi&ovHBO+nk=<-S^bFkp%xOU)lZ4%
1300 z`oy~8r_PgEuIpG1>+(k6bx|ZKIRbC>Z4xpf@U&rFSrPcib(}8(PutezkHA}F3Taa!
1301 z@CaD=ni+wQ31baoUIaci0>3Z<&oz{FRYu@ZLE&pz1U@c|HH_K_ye9&`CIWBOImzoI
1302 z@a-b_H%8zi$MMY(_zn^LTO#mWqgvP22z)0CiF8{8zH<b=F#>Om#Uvk$z{f}MABw<t
1303 zjljPff$tW9KN^AW9)S-<;H|lY<dYHj$aa1{0^ch_k1=hYgxGd^N8nu%cy9#WjKKGa
1304 zz{f}6`$pis5%`1%d~yUnF#?|vflrFSXGP%qMc{oA_$wmt{s=tRT-G%u0^i?4BApq5
1305 zPl>?Ki@*<vz%Puzr$yi^Bk<`F_+=6Jff4xH2z+J)-e32n%U|ytHO6cBS2YHlq1Q30
1306 z`0Mt%_9&+2A%j3_P8y6~5ANZclL#*)vFT_tuA~&g9EzF_Nw_az4na+g67ELWPI#+?
1307 z+Y{zc)U;W`F@!k;HLaJhjWCCvrdkPqp97f9rm0fGrwDVXX__bD<AgcHG)<B4r-V7Q
1308 zH2Ea_K4A_iO&Jn?lQ4&pCa;8FBg`SB$&~PJ!W=r93<+;1%ps%c<WE2(y+GI`d{n}}
1309 zCESkiAqoGQFo%YwMhQPcm_tI-Rtf)%Fo%Ms%@V$sFo%Gq^%B0DFuQ(Jt%PqQ%r4(l
1310 zDd8%@@r36|_$I>a;!RT|JfASTc9T!SHxOo*Zpx7GRKo1aO<oCKO_*J{$&~OI!tA<D
1311 zhJ>>Tv&%M}yuk7gBJ3r6RKh8Q*+rWUNw_azcFm?n33nr$KzOT!+Y@G2Y}zd07{cs=
1312 zP3t9WBh0SXR4d`{eSq2JnkprHif}UFc@jQOm|d)CiiAHU%&yhslkoe5Qwe8C_)Ws>
1313 zVohENzebo{tH}hMb6rlbIcG-Rf&Hxfoay5-zsf1d3!a(&iU7;B%n$r`eVK)<zdq`e
1314 z$8^2}!2>H3H-g3s*^?^AtTjQO^0doMO!fzzAH&o(>Xn!*e{f~uc_p<O3HuCnK2Dvv
1315 ziL!M{#)W{UfJkhBDY@ztS0&v7K40NsXeOXyLVjd?%pjeo(*m7lG((R4dHcz1pOGIt
1316 zmK$siZAE?8op1K6Tn1O_LfLiaM=kL*Y#!w^LceKC_FThgPTY6!DxXwI%O@J3JRoy_
1317 z^4E|0XtdYJJR6Gs(JJDJ$ACR3vD?`vL(384U~XbYT}X`ji9W2p4e@BWnnrvu0`^~k
1318 zT{1({M6km`0WBa}j587jwrLFHz<qNBcW)}+*OaU%*G5pBpsZ>P?uPJY=<uxMeQMot
1319 z;aO#eTd+_GtkLu}B9J3%y6H1yp}vjuJv8J8U80#yuStUQ^i^KNkCOPBUY3X<p8}ED
1320 zm>>MNKX~rcbD53)bBFWS<uvC8cTFq;@Lrxcd7}OL%r|ptmmAFkJP+>nBL?Cv|L}t~
1321 z$5(yeS@{6fta~ugglEBzLwgtuxEs&1&HxQg79(#o<w<*^s$efP3IhwA$ggWeQP{s5
1322 zW;2p!G2X%X$#m&#XxaDL`GrkwmF!T;w!@%>n4qP3g5M%O4V%#vLVr=B9i^zMvx6wS
1323 zWSru;{|zu=zW8>O*Qm|P@T|NBBXvV1ZQiW}KL7<b9k5yIx$aHX_DenKhdg($r;&p+
1324 zG6TE~&rvELIfh?O7!_a`x9Tg;s%0+22p#?owRs@)J~a93mZK?qRxZap;jc%2XScBs
1325 z{yQAQtmO~x@vQs<rU)pCXFa0RdU~&94k7$FG?Sho^&&<44n*bD?Gq=y$b2*NEYP{Z
1326 z^2GR1E>tmyD_zjzFIt`$zY{(fp>kTMiQL3xo|Usege&oIWiGP0!5xXU;L5KLBrb!|
1327 zT(}mWAAB-#4Una>ztHYN=vdY0S#`o8{m9wDY7Fg0!>hX>?(8Y~G8=cEMm)ftQ@2-y
1328 zN>KKk;a}E-*rHDD{6>*NlYp)}kE-rYFUh-4<kjtWg~mbIxZxLS*5}q+E-5c)f8+UP
1329 zG{f_$&fX)v=-0w?-<zm426|;4TtYQ9`s)i4mtk0Gn~#w+vr*PsJjVy%9B8SHB4_x%
1330 zQ=aR0o$|~?kQIH!r~V@6>myj-dG#arhD_K2=4FWi%gV%B6g01X`CeD(%sI9}v(t+h
1331 zxoJnG*FPv(&^!)%>bluM%J&R7MZUF?@A^ZE^f{WxDZgjH`y}0>NCk;A74cb3JU(&N
1332 zS<lL^*hJW$-e*R&n+F^7hJWO_CkmxriF&vZlpKcMo3m~lyt>{wL#j+Ug#7Nv5<<Md
1333 z@T~ePJd;6blNcI-7MA%YIwl8te=y`fcN$K$N%XIJ)3a(l80*y#!wN5gXa3-(L>DR?
1334 zO{3Dk?nNmUI)eEc3~Sc1MXcMAxD~oWyRhh}$IzG`d{H7OxeWx&BuA03(ZKB6NWhhk
1335 z?7J#keD2-4qc-U(kRJl+S#<`MGaEzqVckHZ)Q_(87(kkhf>}^20Yc(Q5HVZ@pH19?
1336 zT<8WZvsua9tX<uMqJ`2iWQ5AFcxs?GvK3^6$`r?{TVNAjcrk%+5s5xA1%>wd*R7S~
1337 z_VyCY8=;XH)-aar@vP|wC%`@r-gaV~kY^YFHS%bhfhCA)L1Ko#zC3YRPTf}m)l!fc
1338 zKWSa@S1#B^R`oA%O{XITiQdp5^lvl?w9lmjfp^ySL-{^NuG13aP`4QB@LQ0W3|u~2
1339 zF)&%7GWMmqeXjiBU({^PY!3YbHO$&`hrJ5KaL`#6YChB4T)#<9KL}qY7HPo)!H+`8
1340 z5UAUc$bcC&ZT;wh9JE7+!R^0mFINkhjkD(D%+8sUb7RijJ*Pag5BpiMylUC3kNY$C
1341 zHC=_l?>|ZJ`!n}6Mg1p<{Uk4Qf72mMwd~TXHc1}SIW0*Sbs<8r%TqT4rJ#*Q|L{GW
1342 zPdL3;ZPJgX<ps=(dAiNZQ#T3P8n%o?h5ZhlrG9pzSFSGQDDvJgj3Vc4p8M9asxrUg
1343 zI%65dIFQIT5#RI~hSS^;7+715N1l~8f%Nh=AC?|PklA@2Lt8@>o5r<>SM4%^Hn0GL
1344 zMblFl>q^&$u0fPp8!O<Or?(M0fu+7`culX;$$W|~0a7j(Q7w;PZH;msg7T*C5S@lv
1345 z7NbClp`SL*1`buU5p?K5kM0kFRd5_cPp}gu{FLY$mJr05oUP($C!`{co{F{^h#W3X
1346 zWV6}16Rl>~oFMCBWn!%~_8%?p8*~AbZRI`Ch$cUgL%}AnhK|6ckbtqw#@zZRB@Vti
1347 z5<{<GzK0D*VsL+M@Y9B^DEu~78X6A#L4$VQ44a|-r<$8XyIfXx@T@Mzl1Q$18&0xp
1348 z<3ValXR!_u97ga2>ZKu_(M%>-La>pA?n<x;V|&9Rq{a}e!a4#rclo!&I4{|b8~vGw
1349 znjS=9Fbn)~h*!=F%lDcp%%}b>XMi?|vi9PeHe*(7m@)zyx1j?z`Dow>?L9;AVSs2`
1350 zO(W3?8UnO?>NIkzn2X0y)NquNam;OI&cR%FQom=ntsgZD_H%>BcP;}Jtzs`CA_uL|
1351 zap=J;u=0CqcCq*eA<?jkrgtKT@Fu1Am8o;6N;~yJTIxxD<CJIjUV+TfQcuCbQqS~H
1352 zOFc6_L3t7rL(||jL=zLy3tm-41moV&2vkpKD2RX#Hkj~6a&1G^v)1G=WcJ+GM>6aM
1353 z(_vuWMonU_yYa)&k0)i+5)rl8Nl$~TiB*~TRbKG$jsD=L{<_akPASMc(71V+4_$bd
1354 zDU$<@?NOKw2>6+8k4>9rO!ud4MB=YIALkE#vD7waj~sq@!+&N@14+$CJ-usLkJ|`Y
1355 z{JYNE!S4_5_U}4A+Aj|IgZur5f2x7JtaeO!VfjzBeC?>FE4>&7+f9dL=uY@LXTS3Z
1356 zP~!9+t|$C;qe2705a=Fuq22Tba|*l*e$jkrPSfpdsY~#q#&_Ov)qUwhK=V0l<NhWq
1357 zv;{+w%w~jsi7W$)n4<k7^dHFnn1$c>6pKYk-?L;f#*gj3f_Z3{P`;AIHR@x;-|BXW
1358 zV2r<Rx5Ize_r3?`88ycR=5!b|L!+cAOco}ryo*09NI1yNhIU|+F~%OetyfJCP+n7(
1359 zXc^c&OCQ26iZA%?ER6T<I<nEvhQ2iEFQzC?LByKCF4-0O;%ju8`cY2}@*2V2I}f53
1360 z(PmB5y}!Qg1|YW&g0DN-(;Gq{hK8VSE&Zjq(yj8y{hZ+U&~*dEb`C+ShNk`BNKF%f
1361 zYVc-Z=zSBaq`J@v7*QSLFmmgs`GY^4@Lbf#^>SM-B2UA^y7MtLU(ebTX^;G&e@I$F
1362 zO_$R3WZj0^W7??DffN4VN5KQLnl{6WX~7@hV#X?r9tf}(znG3aYkq^0A)kv7-K1JP
1363 z;-bQxi~u4^V8sxJu+8i_uNRrQHe^RkeqF^DbacmLtl!uj_hJ-+3lp(%qk@cIh?70E
1364 zMbWNRH0cHUEi|`{gJ!Vo4Xpx8Xe$<E2y%uTVP~QF=1OH!U}oF*d!l2{A>W!y`7Wss
1365 z>?h2~nVuK?Hm4vb_~Uec(Kr6!H`DyP{^jro-$Eq(q1#yX>qdTs2%rzZ$IwDx#;y9C
1366 zfcMTZTmfOBnw!|1zi#<Hm+of`#b6IzMcLpuy?nV))0E@+^EhK<c1<U%J>=mIK_dgF
1367 zIqcO#ZsNK-gw_LE^vcFS+q}910&*vF_D^UwCSo!wm3H%kU+epr`a6tJ?=Nvz0)hPC
1368 zPvG^a{=8p!{v0(jJMb;kWct^Qhi1gd^JjDAo1T^H(9U@GQ2Tv$&6oRq%|>4E0M}an
1369 zRcC9Sr98@c07Ewf?&C=5$I{lDkHuE<xXiPtvbJk`sHnu}1^1npQo3F)Wk7J=3_@No
1370 z8tq`WTIjq0C8Qq83ts0Mx9V&lCU3-q^Pbh?p*E*(zo@h0R%xFL1vSSFKZb=S`19%)
1371 zVSSvRnB`xGwI=SteCRJ|Kv>QPzX_RNvB}$D4J(6HXTXonk2_j5)ZmWxo+Gr$b!rxT
1372 z*zKu%O2XGW|AzfG>DAr&=nH6>mzyYug0!Bru-6x7)4a^<TusB+j~I|~>n1f{y>9kF
1373 z7y1`&)Z+d1*`ey=Al6~6>+%nuofuzpj7wB+Xg1N1Nk+r<M=UzS?IC!e>2_`cU}~I_
1374 z?c+?DneOEn@#_;92rxWhK14N>?gjnCN6eicj@;YKRTB5w#qojTP3SrZgibYKU6pn2
1375 z<4_P#czgvtzJV3&4;~Bs9VRg6#5Ba`U<~U6J`_DAKhcF+Y<s+$tiKdTB3#GXeC96n
1376 zI5eIw<9VC@uTWo<%wmU>10DAIwy!`af*s`vp7(E`cEh8a2X4!i!v0+$Hx!)v6mwXt
1377 zKiDzRU-qW)+9M<U{r}+)E>Cn(^-FM_TK1H#&ndvfbpf-E?jQc(yJ!meMW6Y19d-EY
1378 zx2_oj&lkWIl%u=9ZjbQS{oty3Z`K?Rdd)er;d3oYYs|{q^|@nC4sHf(A#oAEsyWbi
1379 z`+A_{pi;Vicy^!%`Uhqov+lgB=H#|4gl11>qg7x2jmmH>4Z}ZwaCYKRKejC7&OmYE
1380 z$$aF`2QMH_*kSxfPVmh3T8`~w;6q;Uuc1xS)!?3GLxW!j599}%uxt#S!^$%Fad2NK
1381 z9R<fNEY|mU2vDAA=GPZv1A_w&!ja7Qzrtdj_#j-L^^?8+`s-Y{U#uV2um!$0-4H@`
1382 zUz~q}Kjm!8f^py3{i3GOclLm-=4SjlYVN>JSZ3p{CVS4=M#pLY?*cIguqtBp9dH0;
1383 z3%E;(0BFmpJ1PS9{n5sO@yRF*lEh}D2gY;T7D)yZH6Hud-6{4*897^r(Ny4}2pu6C
1384 z?FQD!@krUqsS7!1Pd-Y}<5ZWr?-vHVb>COlWY?|`RW)g~D{O(9D{5ERjha5PmKX;~
1385 zYA;D`Bq=Jhk$73{r}xwyY_9u$e$831mDHRBo9NnDchrtMGtQQg^E2x2B<t@yYHTJZ
1386 zPqaUO@Y~Q{^hw@?_rS<gp6Cj_%}@l7;immKbEqLdYiJ7UWhPWc#M^2Q!FTe5R(pW%
1387 zg?YgX!GB=qI+O<mn8t&90ym)1_CkY}il~zHJ(Kl44|*4}JnRlx@C9u?H~_m0#qcE_
1388 zqXOq53=*TlZgIUE+;id&)_gREU3wDQ0!EaN`(wpI#LlDmf!O$ep%JZ?^F_G*w(9RM
1389 zqW(AiUBmf2!e2gJ(*CZ4E)~Wnkc;&9diwh-_yvCl(qAGhe;+<(`8zFiHTUUc_+q)5
1390 zv&tJk2J$y5`EQaTPlP2u1M*}pT|Z3@ejz6qm6Fb(XV9bE?_wLTYvZ{?;F0aH;THN6
1391 zr}RBWeMDILqM$Ey3*@BI$o6!4&&9SN<Gbsa9UGgCIWM#0V7wT9BzSm9`~3RoJkJvc
1392 ztKAcW2lL)Kn(uDJh=Wn*dtc2zq2i*BY1<Jeqrn*KLr?tDMC=YY5`i&FahH#{?$1q(
1393 zGD1<f2VB*7XZFjIc_f*G$4);bJA>!vyF5SJopm_i(VO^eQmej@Bdi&YpJYAp<$4%#
1394 zH55R9s4vQhR_Kx)CfvSruFGu9!?-ph2LlV%QGb1TJ($%anQ3?ya~?kV57_8o-hpvU
1395 zFrl+OufqZoBR2*bj3a-D!Fm+g&^p9$6c27}N2b|xe{V!-To8lkC)<0V6g#I-KKL=3
1396 z>;s=QH*c?{_TblC%yvL~=Mx0aeJ8-P^DasGMn5MC?E|;J=-utZ@B1t(_-;<{!*j=j
1397 z@9sL^`|$VucjxqfJ7?GDwuwcb=OYp)K5uT$!)jwR7B8IG4q#r2^6&c8o)?^s^(6Ix
1398 zIx~M=e$Vr`_X!pxV#((-@`g9%1;5-5&y9(mv7cm~r7jPnx~fqw-vi@iJIeR$Xw0jx
1399 z0aNb&oONyD{b&#VqQm~-r>fiK)eobwyx@0vZ+(*QZgT`9vOoBf|E*(r!IOFC4(0c0
1400 ztZA5t<<PmhJ>L8gn3t>9WWI?lECxAvC}K5nvAu9U3USCf$(`zAIjkiIFJRpH3nLur
1401 zfw83Syl-hYF0(M%e!6oY;*7;r0tnm)4D?h35*9V6F%C#xJ@?e2tQh$QB>J(H2+?ms
1402 zz0uK;<^{16QiMpI*emD5|0nz07Q58`FlGM<5dL@VKZYF>%l>DdO8e7fd1P171q|g$
1403 z&A4l-+k3IShdM~CzkXz*49uPB{(1%kFhacR6T7wE82(yyf<Jh~zw7HLfBoQde$Nv}
1404 zs@n(O3RS}%HL5WPopZMserUxZsqDlj;rW?$fOyPKL?b-IdO6Ak0vdQgRSmYt*EAxo
1405 z7$JfeLU*D-7?wOMe-Bj7@V%aOPcr63(C`hG>7)I-zKY6UH(1@9?D`@qlm;)@_D-?k
1406 z2KR)1e-y2`Xs>^GsA?Q{ZD-~}F!+9c@NDQ)kkE0k%GmY^1}>~JFt=f<aj}k3(byd1
1407 za}!nDVgIpQi`tG(iM^Xo{BM2gcX!+ay)|3VBX`k9+y!i6e|Uwh>%=qbaX%S6XVn4r
1408 znz5h4{$qyr{J{FHxnk7^fmAM<O}3(VbmXh)7uL!qrU+N42YkbF*@e)0IbMfm!3ySy
1409 zH*|djf68obdKzst621qvHQa<HZF9u<*>nQ+90`9wI6R!G@oqb8pg=x)qDH(h1II&u
1410 z@Kk1F@TZ2kh(oA*m`V2UNcud|fB4u^5~ep4f&l$T!=#H2P(Cks5c&@XPr=4~>Ub&4
1411 zDE&j38ykv9_*Iw?UXMav()lbhbZ6`I64GzHEFEJG4Df_(Xq3h9ANm)N+{+?gY#%Z{
1412 zhv7fH=Ufo_?js!mIsaMyZ6N6*i*$*6!$Rmrd>X^lOXH*bE29Iyv{)kjQ*^$-61wB^
1413 zbX9*hlVg^}0T*)7x9FcDmy<lwB3u1mmQOJ(B13nJLCH@?$uCTUmiW*g(6WNKRZ#mG
1414 z2STEmojFR+*Lc9Z^357A{zl?aSIsaEy_~Jl1GfDn0~SAP&Ytz?TOWdiDer7(^F@3(
1415 zUZL(E;?c8#yNG5rW$(WjE5<u#2IuFqnP+pRb5eeL`m|7gc#J^>T{Ym#{9xj$&uiMB
1416 z@Q33kPUH>$a7k8v@YB3?gL`qf=>LA`2#m<5tov4c1XSo@34ayn>OZgtmYYwQmOQD;
1417 zNX0m)AE|J`aIybj=+o=#yS`k5^5SmJA3QCeHDHa>Fm|lZ2u*-Wm|NDxA8f*CwR0hm
1418 zSfwD8J^u;HMr@SYI2|qX*FT$B3niWh8!-)1o#)Sum)b*3_}2vz+xXYvW-@dKG|Qz0
1419 zw)Mwh>PGjD4<3qGqj5++&+++W1NNHO9O6UCG|Fep`)a(!{sWGr^UwmKk@<m|8!>kA
1420 z4vlxH*rVWLr(p)m(SSg34qG;ST;{7-r(`1NjW3hF-HxBo^Y243ssfq=<59&QghqYP
1421 z++6Gr4v;2JJYKr~5_?z*C-%b9^CXn-+=w4Uq#hDYHE>9^KMd$6Lg%3OqLx=Li9gzJ
1422 zvA@2fG{6nw9{zgUI=`s5-G!01c|{WZs&yX>+T_3&`U*`BqjYRo<isKDcs|w>P9%U+
1423 zZc)x`I0#po#-OnDw_e2u0Slz~>&<h!sW#9X*>(3aTW=~$cYP{Ny|(Jrpc!yskt_S3
1424 z=ed&?Rn!~LkSFkI(>Rn!(k~LBKh|GwU_$DR+ff7_OMjm+4GcYW;XVks*$gFKuV>cR
1425 zd=+Lmfjx0FtMbHmIVm6YuS@$^yw}KIm-H?YHi1K&nnRqLF+VSt^K({y|1WR=2|dcc
1426 z>jIX9@1V}Ef0xbUt3Wr}&kr8Q<ciZeIn5nEl=~0EPt+V&?E_P4#2q{**JN&`Wgyg9
1427 z)_u$AJ+jfUF<D3a5Q2-BIwfrwefsqARt2gn%N7qzD)yEvDydpfvbgA0FVEQb!5z`G
1428 zibW-Xg=LEuc+0B2I3r(HQBz%ht9NNt#o`5hytx(L#T5Z>*@DFtRV7~VRi{IS*YxVb
1429 z1tr-rZXBwoa__9MlP6A`JSlDRl!9q<yw{B#SKys8Zff4-TyO65sTffvPil=ft<*a{
1430 zFMphOR$7I3?Bx9E6DM6Fe^D&0JSHZ>igy%5md?RXwRhUsocwWfV!W4Jv(hTPQ*x#j
1431 z<k9-TvH8=d6^xq-_S?Kxep=oQ<K|F95l}hP;P|YxMc%PfApwPX1=oA?$ITd*|DTFy
1432 zdh;iby(VwcgtRGBCl^eH+Z4?Yi+ZPx8%wK@pERMsPvW)SspF<io<4Q#xU{_7|I}FK
1433 zoh9F;7*MjfcusaiK0Q5sPE3ppC{F!bK`lgeEGjE6FRLyos#siHJs=!rRgV&x9%B`y
1434 zg+Js$okc3J>b0n%ro32IdSzi%b&2<ir0OfYg=EJYAWI6%b@dw->`ki9_AaWa4oDeU
1435 z1n>NkQZ|>{N~$U>_DlIuMvF;Gfa?-{6-!F0$_p#2y-Uji3%!+9B}>>WFY#ge;+q#&
1436 zEM4s7>ke$al~omiilT~gZ*^r!QCVqONpZStr+JIvbXl>t2(L<%6%~SBQp9&Oym%X9
1437 zL13X`0%v7*QTEdEB_$QvrP<Zlw`9-E&d<I!d&$D=McHN9^Rtblq3MH5QPlDZypdAu
1438 zMFG7@nHlL>r3ig-NqL}fR8nT90_9sOqmqU}ASuZTz{R-ojTUsjlA;>v2VdRrmX_g_
1439 z8hMpze_JptE-9??;*H7@Z&I;TS+KCgyR@RJI*?XWh-zxVE-PeyiMP;OSy7FGFDdaZ
1440 zu30p{q$*rq%Hw^SvWj9=d#y45H|%hPC|Ooig0KX_S}j8t%e|;<K~-S@qez99@3fQz
1441 zyl7zoIETtWG>gj7h%P#~@K$)&!ofu~<$<!w@)B=FsrDW3&BEgRnqsO8x5CRgbI}jH
1442 zW>Zs%F%e!=-%KA07gZZZOZuXsL6<OGq|Zl>LzUshrkZk8iqw+4ux8=t{>C`IpOlR*
1443 z5o63sDlZ*?zd4500`W>s1sdV4>4w#IrDze~mP!wERh3j%)KnFfc=K{EBCW;?X|&rV
1444 zCFSYHn8IQ&qFA%2WN{$f$k91;>FR29hjhGrw6tt-F?$BvmX|L+l@zN|F1{k*mG2#~
1445 zHt-5lMb)haJT;P1ss|YJF;SrG9MjW_jG~&Vxi?kJ_l_FnO+f=<zB+8I`l2<Zo>g0f
1446 zx1OLD#o%zk%1w`mt&ZK)0vR?VeW03}(%6fu@gi6NbvTzDgzr+_Y>W*LMzYfomu@UA
1447 zEW?Xj6;*Qs)pM&#%1hAvllvRtIW9Y?#_RJYq4O<5H5e(KeX?I2?(qMO^rue$JwNvS
1448 zH~CtY>xutExt4k?_+G7VK?}V%X!uyiOUv_D4WDa)xAg7S_%$u)i#6=iX}cEmA6luu
1449 ze{1}|bc%ssE(gQ899Pk=)pc^T&iI(tu1wES@X@g<P4vmscfU%FqniJE-|ZcroAAkP
1450 zD@XtM%)j59IDg9MOJ7|yjE9c&3&p0lyK3E6f7*O*|JJKUPM>tmq{-J!y2_YeGFK0I
1451 za|0D~i!1nM9UAJTXg%ryZ@svO?D&cKQ;ca-rx+8bj8#8#XH1ho8q!=MbH{^)7sfF)
1452 zgkdcv%Ux7a9msYkm6zAVxYhWX?baY(lLST0AJ-LDEyn1O?Y-E?_=aN{Cd=DOyjc58
1453 zoIdTwsRaWtnCZbotq^W5sajl8?j4zSmA3|69Mf$f1}iyxm#UmrqTYm*KK@UBmgo4S
1454 zxX?=O(y-hq25yyx?V5gX3;1Um#?Gg_9?>u!g~;ns4fB?o*JBzUhy_IvK4!oXX`miv
1455 z<}NDa6lGjOORC1g+ECS7Z6L(e#-zz}$4;4kDI3-~fofx5amf-(X;Gl69Q9XHSe_==
1456 z0Gth~v49=LDW30+-YQoa+O|R)2A5lS36yiL923Je<;9XOP=y6hB^Ku1<fKLY<vIb=
1457 zLrK-##g&kXq*ER*zG5lEn*dy_{JE-f=a#W1ffL>BBa#tlY<C!Myx!a#Kz_&Hnwy`r
1458 z8^(OxPUZs6$KBi}q|0&d`v&PqdCK=oq&&;j1DgnmNZWke++2Y4OWZx4A&d>kHmH<*
1459 zq<kK+9O+1;JCGJ2?SXA!o~oUV^hu;2B7Fntk4Qg9`Yg8Je?-~?Tjw27ndL|aBkh5w
1460 z53`ZJfpjI(Hh2>AB<V=^B3+L3L!>*9o<TYQPr7=b^7D}nM*1b5q^?9-j-8Tc2_t<Q
1461 z>2mB3I`HVA91pt(AbkUA0n!hVmLvTV=}M$OBHe_v4bB|Ah_naNH;|4*`Z?0sNPk4S
1462 z9BD^9ec6O`0MZ>ubCG_CbT-l-kp__Vz{!xcNJk=l66tKDJCH6%`Zm%{NWVn71E~X#
1463 zgFi&t1L==Q2P5r)vpV@mM<OjoIveS7q+cR^5$STA(m6vIX-71L9ypLR0O^lN^O4TR
1464 zc{?upcOYGf^h2bZkha0;yB$b3A^jX_M>Zl{;<l-VSZ0duZK7T4MYKsgPIwrd-)nA8
1465 zA%ngy&u<uspp$>ftIf?P(T<Ebb9`L<)t=a;u3BSsw-G5<CibNYK0(gK-xlai;NXxG
1466 zXV%%q$4#+qi-|MG#<_B0ZL?(tG+eY7z~2^Z5XiwjH;&I>q^-3`4*^fxO3(Z_gj8Pi
1467 z<yrh41wDfpY3HUeoqoK5zmuSU7N(Dn^Vxn6KgP$o#>c`9q@>}>$KQ|m+lu~kgykC(
1468 zXWnlc6BmD<eN3Eponu^F@>*wZT*m6C32|9<(bvS)3j1tZOk7q@Tt-e@GI+oXnK5y$
1469 zJRFmj`tnhJ6aDk4HkQ6|)R%XuzVXzT7kAQTPj^Az*#FR%Lw$_XCg?kf{@Vq4L&u5u
1470 z7lA(y{3wO@22d*E-vHi=e$H5c-&>^dp97x-{8hwX8|N(telW5>0zVJ<>xoBM*4lF7
1471 z;#b=tS?9PVCN3T!o)G8q#{xSp&b(U2j&=qkUTZ9Ul*Pq5%Ljfd@Jor9QRiIkSZiO0
1472 zwvb_)5)<djWwBKKgU^L=s524zqF$bVHi7@0g+xmHlfZ8Qetra=?O_M-2DbCZ5kDzz
1473 zUY&ilZHe?!`ST&@8K6H)`qlJjN?avfstUU!{pR?%?Z4ooy#e6!Vce8)l<jXa6!~LI
1474 zV3YKG(C2|ZjrJsc9_SNdZvvg=C<lEr=ycn<h+hf(M&O57NTiJCCg2-^uOMFPn-u3|
1475 zEX^F6C06R)3qBXd>kdSqolJr~w(k#tH-YE3DpdQP!1g$f?eXex`_5r|oDjD)#$F;W
1476 z*Bq%-`7^+Q@?qRxLB#a9j5^0^`&yfAtPBEixac?Mjcxx0AKU11@R^uD?xCP8AG*qP
1477 zt9Z6NHGrsgL%q*}zY_f4kpJqnj=HEB=%CJZ_WNwMhvCH42nqS#245EDA=$2_-idJ;
1478 zcPhPORoG<QIB!*g55sQwVtsHPTX-4#0O02Vk0gANKNpCZm%(%Xn{pX^0C+#}ou~!%
1479 zHAT0NwVEGiuq1xE#&h1J{+9S1z|)_Wdfo<}{&Pc|`mfh|z674-wZ@aF8t=foy6iG|
1480 z&d0Tv!E=6I1AM&JKTYe&2Y&r!`1t{=jli>y(4Xrx|8n3rUxxod;I{zZvRqsTYz4lh
1481 z-MzqXyA1wA;2VK&8MiaQ9|XRu_NPGm(+2B-LoN6RgC`OAcY(i~{Af?BZ5Y?<FivLJ
1482 z#;9Qu{c%ieK{$_wI1;S0A(z4R59Khv-e=2;i(kk2WvwGOE_t;Rb4gv4?WVZooQUa!
1483 z%xXU5`lS}~#Y9{iw;o3>SKDlp;jQZTJLoUy{Yb~CJr@+lm}i|rz`srWv^ei-Tb;ce
1484 z{eu$=>1ROSf_2x8q@zB{B&{^8m+PSr=zMf*U2NxEA7yZzW+9O>&-GFk@M*-${x%gF
1485 z$H|_S2vjlXe$a!YU%fhNt+O=FR~Nm`ai9Hun{8&;F4tFE!529`Qsn>7m)Gl4#kW!&
1486 z3=ZkMTBg>mb{j=Dwt9Rr*H*(%4pXpf`@~I|$6uqn{Jr?yI@xD{b7{I&=cpoiefyJ|
1487 zmNwda62{OXuk+D9nWBry>yXVSQ!Gv8WqnUj55tD+%b>`<u6dYX>QdL#c`~)y#1xF#
1488 zyx1Ojp()Etj%movi}gv^!W$a4{GKPN2ELD|F3bK;dYauF<CBDD4O@1xESJ-8hNf%r
1489 z|LckM9mAG}j_G<mtJ5gcCs{h{w4Y9g>U6wLXXvz4r%QCYTBi@|^eLVGS*QDTdPJwk
1490 zbb3~&QSG#So%Yk|P@Rs~=?tBg>U4=tSL^g)oj#@0KkIbAPLJsHm`=~?G^)L}uhV`y
1491 z9jepuI-Q}@Qk^c*>1v%mtkb7-`e&WW;70sR7&|uGo19xRzpQYvcX0Z!^efXcGy1EX
1492 zaT(%pi#8HURHIT&a*FQQ59=PpSB-edn+Tb^^oI*4oAGR4tE-+&@<|4(16<0jZqRJT
1493 zRLl{|p4m_FKi85`!%F{OQ!V~R&HsY#crC>g|H|POe{HJL|By8zv=C7Iy(U@w-b}@x
1494 zZS}Ov@*kaH@z1+b@!#Eo&jOYHD$HG~yeBn(&+v$1ajJ9+BB@Nf#6M6*(Tt&kGo!rg
1495 zy_8o%HkYFv1Z=M87XjOZs|+Qz*`mk6fXxy8vP4GRERoKwNbC+L_T?bp%*1Fd!{}UF
1496 z1~x|-^f=eaEZ@O$-Z!7ZuIMpfa=M~io0YCA&>Yv}ZYk=WEQ;L>OVJsxARD~^*>_!M
1497 zS3;4CpE`7%lPVGn7YA(DkB?A8g3Hwb8eJC@WV(L9=<NDQLGi8;2$ZW?L0<PyRAmSS
1498 zCcCeppwM83`vGdTX)w$E4NclL=yO-X8<$gqe)m2^(iNq_DQ-8xXbsMEcSWgOZm}Eo
1499 zYzgz+8Ppsr`0k)BVWFFc?p<w#Dov$(JDJ;QFyL-Wmph0`S-NHJAIRKAj0b2>s1<IW
1500 zM{>oB0tw$O+`LhCbrpYuZhJzVaC1T8>M1^w@EYN6N4TH3UGlFN?ksvbP;8X&M&TY!
1501 zI77pmg?l{VObu@l?ump4X?Uw}b3@8?rFdG(ZxikpF}u2kNbl_ljlx|)`Y^%$IeWrh
1502 zVZ=PmC_ftgAQ17c#~BjW5!TVKnYE!dm(#;1RB&9bXh!4d`A~05FpVfzJ-DJ=Y!I=V
1503 z@xyYp*?<hOY#I`K#=>?0mM?X--7FdA;}>mn0Akiw<)fdMgkGr4ILF7}bi3Oj?{T=}
1504 z*~rZVxNn%X@L8Bgfxx%o-XvF#6vfqx4b<datzn*)Tn|D5T$KRaeWxg{D>jfT6M}}h
1505 z8wC>PACU*w5diMNOBC0{m&o-UP=@()$<<lvie8HNnC@w`?`n(2?k?z!EMnCTPqhvA
1506 zbOpJL_Fnh=J`C?nx>%%{T$#|~F4j!0f6-)#f=pL?1lwJzpm?Kwyt|Bdw5|{=x^J=+
1507 zfX8s(JQ2U_UzrpsC!4Afdfmb6F1!_(j&muvfSz_dPA3-8A0xUW5LxcoF9B$Wk0rY2
1508 zC}oCgH=2w4M(tZWY-Jnnx$~tVv(pXIM7$B*MoL$Yf#<GY0_hG|p2>pNXmM4vB?>ZK
1509 zkE52|OBEEaR4-Fzy~^yZ3QBBOR9<bkZ<B*sLbB@$SaaXbdbK4CaMdz+%UOT6gbbr|
1510 z0m|oyaV>x==6?8TnEcwMFh8Kr=GXYO8_`RFGGjcyqQAVsjxp&v>x*BCjA^F|=x}kK
1511 ziD|FBN1Ka%^f2{yfDOYu3B$r%jJ(a{xh=cNPeC|LH-4Qa?^mM?M_=&AK1oAe?t?N%
1512 ztPp3ZVhH>-%&SpT!ic|#$<4A$if)kWT4snv^r7obI%9OhQ&vMfrg&(x`*N5Rk7a_Z
1513 zyC1O5&V^p_7-hSAVNYRutS0Z{<n6I8oHcq1zKvmf&>@FG`wIYi;p>^iaK!CB3_r+k
1514 zW}e&5$dkv*?SI?Dk_Ww)tUbjP6w1+ANdN5bf~)tJEN*APo^JFJV?nof6Li6T7Ub?E
1515 z+q+3>-xwf7wUo71Ak}?*U{#kG3*!m0ywz0j0{#;C;<}Jv6TrmlS=bs<y$FAgbZV4f
1516 zQUG7G6ieoV!mY|gc2BX4jEV3p3Fk!&aVx=D0Q<3Swt9U4@iv4`#T~r2y`m*LIT|+l
1517 zoA~)BB=Jyrq2|95TOBFYk-%G#K!PsW7_yDfz_kEUr)Yq$!1h4#28aT;ov#baEA3`Y
1518 zUIFp|G2LzF%fh_CCo%_!Yi+JUhLIiuMzj;Pn!7=#X!eG9mw`OXTsu}<7ILYNXa-vS
1519 zg=Lkm7W0Bu`)M)VNd1%MqVc_w3l8vYW5uN$u*cxl<21|SZ<U{{^S%$zW<OcOjat*^
1520 zI_1zT2D;(cThJx?F?$HOq@sm}NS+T|57ceiKQ%i~R-*K_Y7nAaYzpb4ZIDY7CpCw+
1521 zuMb$mn93&cW>|3=75@r2sdyk2UjUT)U4-I#uxRC}uD(97a7AMnPekC&zCNN2I`Wr`
1522 z_<@#L@vii+K*r6;V1Kqq_5>w*C0dz?!(C@)DyUxo${dOeKev>bgP&)Z;RaSOG`#-T
1523 zA+wyB`N%wmOv?DaO3ztXN?mIKpx%Hx+W}&JyAAWsx-!pj9^iFybYCO&fxbTG4QFpW
1524 zUzBVzhN)Zn`iM5zDc4DSp>xARh#RTT_w|ut^n}Q7B1B&A>myo<ydm)|EgHVQM#`bS
1525 zK5`jDAf9@<ua9{tW1!@h_cG;tUmv-oj4?>?V-?~R!KuvDu{)NeICditBB3olpo%jn
1526 zU}AlCM0F%&vf5u^^R6by7>HNM*Z?pIBWnX$d%^F-5v&IZt|xeyl8rR>CBP(pV^{3r
1527 zh?fY56Zv^4v734;0QT@xR)T6s*~2kp8z@Pf@^PdT;3<HEIapt(od?bkueEK10&?gb
1528 z!Z+A5@50XjpoVhQ+5b0y<^$4_pJ>T>K#0Fi1|gG@&oV>lGt5v!I!ZWnJ-DQXdjTQp
1529 zL$&l+Q~|&2gSPEhVhm0+QvDH>x-jKRP^uy*k1C4IRcxeKp3G)-9!m7lfN=+a4>Z#f
1530 zsK<cCx2$<_=-9Az#Q-tYzG2%6BW01UxJ{H_83EYfD;?Xgc}0|wvQtwy9Hkx9fHjm1
1531 zVV|D}<-_)&$YPxkGa=kVj_LO^;$3C%Wwyr#){x8^!~PtN{174D1$*}@4*^a+-Fdeq
1532 zhH&}PJ&78Ja=)+pc5)9TZx1;pWpU`}v5eT^Y&<=l7FM<^M=6QSDgg2fWCV>3?~%gR
1533 zG=uDP`Xdmc(5bBTFF?5}jx*YRj{G2TAEGGEs1dTgk3!-9R^x3deYPhWb0d8`L!JFl
1534 zhJ^d+(HXYTJ54maDtvZYoF(;0J2cqM$cS@Xy!^90K(55Zd4g3P0CH&~z9ZNT+gFKP
1535 zf{O16?gp6cqoE(@u6=2($eznkN>CIg-Vg?MV52N?F7--Ud)yT!a=j>ioCryN=Q1%w
1536 zy%*@y>j1OI!4vTlLHmX+cP8;G*rJ(W8nz5ZJjAdXG6qWsXVFKsrg)yPtSy_QUyr@A
1537 z5warfa*2_QJ;V{ef&0QC=|RHPbj>Lj9lHt3cB0_3-2lsajuNb!IxGuDz(YesOaA8(
1538 z?h(%rb_uRKooJ3DWD9Uh{iTFulTok@t$JiE?ZpT#qU{?R?;IITI96~iimq_yNH6_s
1539 zBe)K?Z>U`{;uy=T?kn&0Lf;`qHcsl_L-=0Sf`X3`ewwf;=`;EOZo~Mr6Abn?!gHy=
1540 zqohao1^gr7P7>~x0RR3>SS`u$fbA+D<S?U*=z!5qbdhX#fNg|aIL6B`d<=LLmvh!p
1541 zD^EuyB_@c!qRkCC4qBR9BmaOPU<`0<ICKZlqqgD4I<l2$$z_TdG|nNfQ_e#EEkX{%
1542 zhRD{!*14}~mhb>EAuMbmTNAbpkJVYiIbvm4_%4lXP1rh#_NXO1TkHx8Tgb}^Ggj7d
1543 zw@)nL1>!pj%UFG&ku73HIqO*6uR7@%-y|~8UzFTNjl5LuD#qA47TAc|#8U7k%E<V>
1544 zt7R_Z=;+Ti?Tp0(Deq@&P}AjJ!H7d_oGL#g5$oTU0weCBx#@CXS_B4pDhTj=pq~J2
1545 z7+0}S*4f6B<en^S7<*KK+I04j$!Jj^4(RhW$x9d3h(BPM$y^Qmaj4C_9huch$W$WJ
1546 zw;wVk$ZSAn=z8$?-vB7)3S>4R^B6NvBXgXY7m(?bY#6>B$hhs>e9D6yjw?^WvE<i*
1547 zPrIgzLZ6halB*;+ukj0x>Po#u`{(hZvLPpDFSL2d*KMrkOWmm1hG6#iLa}k#nz~uz
1548 zxw5<vf#0F=X;9m*qg1Pm%MOK(;Y7!J&|##$tr@3)F<&vpZrB2n%bV!(_JbQD%Sesa
1549 z<yZ`^;;=d+HC^NB*76Aa{D^Wt9mdNteWS|`A8dD`1h;EemY^ZbYNT$|_<LaT9})P`
1550 zJ$weQ$GkZ7(@B=hZRdC4cu5QVQk(*C8&iZu!^P?`QvcCY5qEphcr5Wot3Fb*dR-(J
1551 zSY&>DOkSxIBFNPinI9ul<V~8)1;<87#v+Cv7URVN-+?yqlxETk5$A^5J5dp6;{DNL
1552 z?&$0zuaSXfB<>P9ozWEMA>V%}h`DHQ{d166&P+Zsk0FzCK`Z24U}~q{N&(m4T_BCc
1553 zacp??4#g?mGy}QQ3N&!Us{_gJj_FHwxo^8Dcs>1jMASf|>T*WBBDCmo?55G0)JT~}
1554 z#qS}L$?+-#XVZFIR&Eq;ZEo+TRIbsf5VkH|Aj`X#cKwmz{mgh~c!yKQ4DWgFL*|N>
1555 zvdO&DN#<QnO08DM0%J0urF(TF*sN30)^?X=>9l2OVv4p@#|$mKg3J{yWg{%zuhnTw
1556 zj73{rH|aVRzZb92662ASig@(WgiGU?+SozG;-nXGg8=U&SFm~8ma`$b?fe|Gyiz~V
1557 ztlZg%j@R|LIou|#iI3!d7MY(>R?-tYsT^-1$0@QLD6rt(jFon^Cim=vwq;E!RCSA`
1558 zir*2ISIYC6cPM$SiG;krw0Qa9V0oolLpjMiEOMo#D%CnwPx1#AnO_7}(t~v`A^CfY
1559 z{G277GFg+k6OuAR1C!uY$``uz7170%u1en$0AsPHLyT2tM3}jzGEzrtjt9XpTXAqP
1560 zW~BT~6QrKUHSip`?v`8-C)d^pu9W=|K<YahcpV~tvP8B*<Wo)f285J<X+U=Da~ik+
1561 z%JE2Vjnu?$svw>FVixPB3$hhsI11w2a8zc{WUN)1yp7s&r;+-SmgC08QYly1b;H&>
1562 z)cwA7AidXygT(a0KoW(C0a><1PGm*xH*9OkY@{C0O6lj%EN9eQ^NA+$w(VI(a%@<0
1563 zC+^g~(G(fa^BNe1;vAN21)S?rJl$0><z3%98ekK+pme$I{1B<UQl|G%xmnPWQlbGF
1564 z$J;c(31Db<-CgppQtU>`YE71&Y>MEWZ}IXoq4G+3Nt17ak<`CM@ZM+f@&lprO8qo~
1565 z{CkURT1_@Jv!`NYRoHsaD^$h$JO5`@akW-@H~i}^l}@*BcowZ}vL-MfDMcEPCALPl
1566 zBVOzPDG|4wUk~NQ8EiR<`dcl*5Z-DroeUTC<p}adi+m_dJ{UoM$s+T6qVh^T7C}B@
1567 zk@-PUMZU3@$~}TIeQS~V-A_ecsL5;=9ee89<;Or3xhjHurA6i!LKS&=1bM1O=4V3{
1568 zd36N&7K_Ypi7N882=aQ1%nygkD{XfK8C}S2=a)p)h0RCsw;c^Ac0PU%0vfXcnP!hM
1569 zR_;kHd<iIQh!o5N7B|0Zczaj&2(oUwp^>>oSVlx|;lnf`a`)K*Jfnd+OgGWL)c|+3
1570 z+GJA}Y-I%eG%Cb6kuBiC1R?L&06rfLaAFud53p^(CRUSsym$?UqKnl%wcuv%1nzB2
1571 z;AV*5$P>@QW}Lw<|6m1)AFg*M#KWrz1l7+*<czCD0&2_A3;!J`H$o@S8DqS-lLhFY
1572 zZqemNs8kQa&sdn9n!tTaDWRz2L>olLu}b@Vjkq1UV&9i{5`vqLO8YgUkVQMH@Z42Y
1573 z_<S)D-p78U@Z$y60*2$TkWWAbcdI5mP3Q8&Qdo&I?qV&-KyveH0&}wXaIz1B^9LOq
1574 zj#!eQgLAdW!VRzEQ*20Z-k%`Da1GX1Kt8F0&-*MT!aW(|8nK(imqZx=!P|+8L@Qv!
1575 z8JB0YN#0LH*2j3<{D5o<xj!y=UvSYQ_}h=vuXIqSgoSC&(!T{EbG)U4!8-vN3>A^_
1576 zm^-0hq+Lbs9!minpUHasO5q<1<0pzV2zbT|v70zH8uc^L&^cqGhzHheD+EU)Nrj`Y
1577 zGq5-5QgV4D34R#54@GG6b7iP~9}wnKmCVU!Ls71HVB4~m#*5$JH?{-XJiHTJu_*o5
1578 zhzTV8PHEwqLE*2K549c3P-7e?C(uh{l30u1c5P@!a24T);^zhAf1~~5!a=zqt9YV#
1579 zhs|!75L-y#4|ejn$8(JsL%Gq)E|&#LOtOp@JHZlbRc%w4${ZAMQz&2XRA}tCO2K&X
1580 z6DYAU+6^uYR4ra3u18;seN(Y<hMmC2kjj{>1nKB_@dn}&`?QwlEGmnvl#COP*+5O!
1581 z)N8PBgfL_)ot$heTQ0hNOyN0TPvG9UF<E@eCNaq_gbJ?lYrr<+T5#*LDtE)l8^LNF
1582 z0*dbE1B6uye6{h!h)tdtv8%Hxc6C<8uFk61)mat0kY`owHhEUXq0Xw<)masIk8QKH
1583 zY}_`URk6#nD$r&fP<e=S5yb;4>L`liEWgn&kD@rv&8M6`isJb3ehI0gD2@vXQb$o7
1584 zKPgBZMR7DMNF7CSU_V(3s-q|lp+R*N#bMK+I*Q`3Yfv3UaX2-oj-oiCG^mcEIHEPE
1585 zj-oi+;&HfcOHfBq@YMKe396$gj!TcCI4(Vk;<)rEilfC*6i17rD2}e;_s|_aisI-g
1586 zUXidqisEQ-6vZ)6tYe@P^idQ?hK4t*qbQC{4eO&QjzJpMM^PMCiZm&&kD@qQ97S;q
1587 z6MLk6>nMstA4PFI&XCBXD2`vN=%}M8jwe)b)KL`2)AMB&@hHko5QuVZ0vyZ6!E&`(
1588 zjSR7D8WQ`Kh2>F{_W-mdZ<K33e$n)J6a|g!c|dV;Y{Ld|%N9NfH-+Ll^aszPYCJQF
1589 zrpnd8ncpS(Acq?-&_?2~otQ2k3%37B6IKJ+-s&h10x&voLEzlNA_>uf3j*ge3g{@i
1590 zpp#vYVx4Hk=q&C>w~HDi&ktb}m$Py-XXQ@xUw1xZ75aqkrK8=dmzuhF?$qgYj70yp
1591 zd#R0|-M2p|yYO^oAC}oGncYNxoi5up6u`cX_$b#d{I=-P_oL94?a_Y$uXVW0aX~>=
1592 zk5-V?qZJhH(FzRrXa$CQv;xCDT7lsnt-x@PR$#bCD=^%n{|eV_7kf0T&pKT8|8|dN
1593 zGmh-hO%iUsM?c3vNAzd~U+mEezSyG`{NL}<-$?ua*`pZ}-J?}>tRAg`^PfHXVF*OI
1594 z4#M47HV&36+@skvB$m(cB$hqeiLTO?ywRy>W~Q^(l|Z<*pp`kj9LP8)oFLSPlPFq{
1595 z5zSX4&8TIwEyk$ZEXK`XjJkcR#rPUPS9I1YGR8tEI(xp>_!cP9BNT-HyOdk4QL~-^
1596 zQ4b}0V6lA+S6%M)P!K2A@xm?m;;Yp;C+g1GzyXE?58f9Ru`GgZ!#tD!{i~2Gnb-js
1597 zT>5Bk{?8Mf#oJ>y{>t{)ep-rQWuPW@z)%2!+s@B4tIMtqk;che2RuKbp(&buxlYqz
1598 zKr92n6Ig<0NHNNT4mWCYveF7muqQHDoaYe&(Os@1YBiTN*4##A??73{ZU~I%{wrwP
1599 z4_qht$hN00UWb>p*tIQ{cjg%B-oi#AL}!kX?q?LxMVw|8&Csiywvdcx^~5uW)<D%=
1600 z<v8l*I7+wU*<6fn;v-g>U#)w_5iftPQF1JAl#4B*i{O9V5j9C$s352O(H3feXiGE3
1601 zAKRjqjIS}S>Y+CXK`xN2Q_NMVK0t=?0M?h6Ke}rj>-{fI@Y>c=tvtbNTgPm~vE6$K
1602 zs#TFZwrhW9jAW1#Ta@b=0MU|1&2jQPuOp)oXqP<C>pXi8;^Tf5)1dR*brem&;Yy^=
1603 zA6H7q<>q-_=LH3sZl33L{-mIIH_!7r<x5Al1aHhwP~|j)A|}W1Jg-w|FeByxYPD%F
1604 zE9M)Tv}@28!}GjOrw08oJkRTl(%_UBp67K&Yj9=^&+|InVjt|;66VFAK^o3jc^iTu
1605 zH>Q@F+X_{h${3#Kb+*%BAcp68ogGApEZwpgp67LT5rYBRah^A3A>nwDC*iwA%qZ&a
1606 zDh|UGhuj#R=XLfJpGbHOo^}%MCyxi)6V{8EEP6Un+%4rdikQ)aGc>$e#PB>X4reR+
1607 z77@eqyv{)y-YQ~vp4WM$;7)@*VVj8Id0yub>AfB2d1H8<*Evl5OWMbf8_V;&&PQDj
1608 z0uk?gd><0`5!TVKnPqMAJg@T!-lJjob4N28PpjB)5p^H%QLaXqYr}TJa<#o38DiNq
1609 zB=($z?O@15x>0UU5pj;Fcpi24$V0lGS~wy+JbJ1R=|=Ui0RUI8vE-76bUpHrt|#J<
1610 zZdBi7#dSp)xiVqO@a%?{!t+Pu^&#D;!IMCB$&;v2)y>Gec@i}$K-XAGo_~m{QIO01
1611 zFUUtNQIP58Nz|yN3W_&*$Te!&2$(^eb@M<&)U66iG<gy=>NXb2mXPe`Nz|y@={!!N
1612 zx_J^cYB`<cNz^z;^rM5|fk&Pe^~lqr9v%j=d3M4TyT=8i4v(A7$rEu}H2O(8-_8{6
1613 z3n6XdJgVqm^}Flglj!(_^bDto<$bT{E9>4GRJvZ_0~xze9Ag>F4pOKug-&4Q-4Q3C
1614 z5~*)qItJWB{d~w`BGqYU`2_e1Hm=U{0kF(=vB-sO(1x&+yac}mo@$&VvacEA12gup
1615 zQ8Emz&KQ_Y6SU^lp4_NY+ftVpgs^vGk<#dbm`-m7GP@Gqpg_FQ6<M-C^R(DMbozI2
1616 zh)%H5L7rC_&e#qd2(Ssms>r62Ckg%q(Gw%+fF0ewLna*>c{jkx06Uh#_EqG4j!=aK
1617 zodeYUL2c=7l#=JZQBthduSHR9t}*dA&cuPE`!kwrGq`ZVSH`27@sLsBW^25d%7=zs
1618 zUeKHebkwjPZuAg;pu1O#qndbDr;JV^)b$MDxa!r+rDfunnne~zl@jci=lGz9SClJ&
1619 zvi6Ys6F4<tB>N=#cRHoUpIaKQrN&ZdL>>JGzhaSKBi^cc+xJ(pl-Y}B+ztOXJ$M*J
1620 zF}*j>t?+$R)jBHJI=r%V$gI5&57GC%hrAUO7Sj`w(ZWRq<GhJBjl^x*(5pHv539R{
1621 z>Jp?nnH?|)?Xo3%g4BKswHJe~^xs1Lj{t<gIjz^J3!+@DzUZpV+Wv!2xm_LUb~V+e
1622 zTuHSE@oO*{jedj1S;U&VT{cdyHdCV0d%!Mcqw#j&5lnGAhmyB}>tKXIFJ_Rwv5d<d
1623 ztTsNX>poJ8FF@sFLz;bSDIPNBYy9`9^e!_r&=%_nHZw55nI2TUS~^py8G5AnK*Fp2
1624 zuq5t=v&xy(bmnisDQ6^@HU!`bmS;6fyB1(ad3<aQ!4m+Lt3l=J`W4-Ou8pL?i!ZdR
1625 zOVDW!YCMZ@;bIZGzpL?Mz~2dm)UaVBeWvj&TKBIsz@lYKCRx1hHeHe%fWKY|yX|9g
1626 zeDDodmu{L|0Wu=uwjb3bbkYbuMCmF<X``w#E%b(^dnia-Kvz-P$SCaqPDM$A-G>2`
1627 zN7gnnEVltvQF?^ndjM6G9t}rnf>zEb#X`3(b@yc&&nP8m{89v9jm9%dBQEkMJ)rS2
1628 zO25<qqcl%4sVKdm@r=?6CG56eACA&%ntb^vh4~Prf3qR{Sw`uQ7K%&tp@`TW%>rpq
1629 ztX1%BEcg!Kl8$J`2VuPXsR&QpU`DZVgE7VjW?Wrjw6e>466S*^+z%DcN>5BJRHReq
1630 zaF9-iJ$a6v+zMO*&-Drkh5&Z&uK9lr$JQxd#Fa+U6&lSN?><HYjNHqXzqeSC>wbeK
1631 z)88*7xn&y*^Cr!W&};M)Jaa4>M5V@BOMH&2ZAM|n@}k+x<x{lLSI%Rdh5+NX*N*X_
1632 zJQ!+BfLHMT#<7JfG9j+u{f*-p4e+6m<F^V(7VpAZ8{<>jWH<z8uKrITCx46-5ya}k
1633 z^)p4}gr$h&O$Bue1fyS4R8CU;N$AgsRpssmhzE!XSOK{Uh2rBpB&i_K4F|UMrENA<
1634 zsXo<6lY8tjZ6uzpmd3bO9z9y|vU?~KoR&c3W^_!pBC;<i3n^kRJdDXxcvhCer^`Dy
1635 z2k+omMXIm^<g+aYo^469_mLof7>`tp<bOgsP&~|F{Z{d0h-=XrVk;D+bQ=$M#1hST
1636 z5^VamZ2=0#n=0#N(oUH^Ksd?{7P(_)|DW$`J1*{PJLJB$ZHp7Jy>CA3gtxeDGdctJ
1637 zr!wH8T)!hFa<|)g_EuDf+#7RVvfJ(akrTePH|D&cAhkE<{7FG-Z_L@OAhkD!8#M*0
1638 zy)oRVDNyZ=;YLk?YHtiTY6?_)W4KXMpxPV5jhX`0-WYDw6sY#baHIATT(>2t-EQ2d
1639 zai`YW8^etnqhL!=FJ9tCO@ZpgOWdecN~(JC5;tn&85rxuOWddxNLaski5oSwyR2Wl
1640 z#Elv^4(thfZwxnTw@ZHg;w5g>xGfak8^ev7f;X$(ZrrFTSnrMDMoqzbZwxnTX;NPA
1641 zcH>5k-t$IHzIcfnHMLh~?TtD0ZnyJshD7d-Ie)F9qxQy}PpIIiy)kFRZg(vN)EhCe
1642 zY#c0C_{B>$4T+UIW?U6<Z;ab=ZOLn!iIx>r%BO6XZh716ap<*6vp|TejlOdrh9Xzr
1643 zE<n{Xi`yzAwk<NF@h5G04BOvLkniF%W4tey$L$#N<4%w_zr_htVSdyBa%MOD+RX)B
1644 z(Vop3jId7gGl)f*e*-?+d=`DzWiG(4+q@RmV$74k$C~vXm@yv!e_Qic=(%y`W59UK
1645 zJoHf0+zp;~<|*iDZ~g>o2lIh=%v<Jru-nP}6Y`zSc_?QW^XK4+H+OWyV%Y2fE8WZo
1646 zprN~Y1-gC@b2Vgpnt^s$eVaSrVQ(`U{9ZE`vVF{Ff$wY9!K(x_1Hnl&vmu*gx**%n
1647 zT#Mf;%wEu(Y<7iIfAc$VrkE4qL#o*WaTs9!9iF6_P0*8W-T>KwW>-)%%vX@lG<(6y
1648 zAoDx?UTJm$&tUUc$PY1>p>#vdl_>i#^E+^6nf;-8xaorr*=8B?Bg}H>8EKY*XQUYm
1649 zE2GS-5TC2e6ktZ1r-5lS%=e*gmtnSnzTJlTGeCO`b22#g8s-kD*=Lv!q15{g^BAB5
1650 zhPeQo2N7Qwebq3ZfsNM;b1#zD4Ko1FHw^PNB!4x`qp<cj!+Ze&{5!;v95T$gNDjjg
1651 z;{2vz{t5wl%P<cE`L<zR0l9Y!(}8jxG0dr8`G;Y?iYUEnn6Dsw?-}M>h~@iu<r2Pp
1652 zV3?!e%ZG+}C6NC#%qQT|M~3+_1U@#*FCc!@Fyj!APYm-7&^|RxzMS%zVID{FxnbT5
1653 z@h=SXHn1GS7B6)E%P{`{TF5Z}2+x`f^Lv!xxM6NXTuvC~K<NC^FzeyxSB7~GEMKD`
1654 z1Nn_%j)nM1xCHC}MrjejQ+Tfv$kT=yLU_&?W>*M&i}#K}JBzTw>vM*A9g_2g`82BI
1655 zJH!Q%_}(z@0rCgK6!7Io!`uh!7Ys8QzWju@L}8)XF#is-wZa?^&bx$}hcetP%oU*3
1656 z2{RSRN@4zh@~skPAJ|(h%yn?$9${{W+!|p%2U<{=HvoCBFzrxXFU$jo{90kY0cf2t
1657 zmxJ>@VV;23_Y3m~bgma>CS2Me%%x!YnJ`Zy5)TNo7;+B^a|8@MB+RRTd{~$%u<&zX
1658 z1`vXc!u%Z^{Dm;DgR)12`3%G#73NK-)J?*C56Lfuc@IMHD`CC@WsgA%tZx?P>(KeQ
1659 zFmHzSU&9czJR!`EKt3r<2Mqm2n5788Q^HI_QJxlNPawCzdFXsbm`gzWtuTKJ<nM$z
1660 z2WFoY<{oJIy)fHC;5lKs5#8s7$(OaZ3Uec@{{aH<`UPRW1L%*!yd9h`3Ue5o|C2D&
1661 zAn<2lK855ZVSWK++l1+agD(s70YKY@IT_afBFvv71UrQJBFw%5KOw#o@dRgsFsHz!
1662 zMqxey&RxRH0d2Q1C&JzyB#_%H%yWSD3G*%_`-Qm(;W;48D`4S-FmnNYDNG)>{t9IW
1663 z%h$q;LCn4p=5RnKg*g~3{}$#36y=mKV-bnd!t4xR&cH07Z-qGu*3SyF8bvuL%tzqa
1664 zd4b20e0|quy}sK43!C;|VigDs=L@65J#azH5>Xh`tyR#UQhlI+2P@n45a^f)t6~<j
1665 zVtS|Q+mKHKIW`-^uAAa>D4h$i3-)|&oDbUV0OHqcJ)3pfc>_EYg_L~^bWUlUUAl^;
1666 z=qMtVa*djG-~b;Pj4!|^N<r@C=!RU|CCIw%{Ey3cb)R2TinnM;$1{`8yipP!s#%0R
1667 zy)N>mSHADP9bgYmS8cS~?m876M?<D(6iRjyJiRP@9_p;OykYOnXCA%Piz~g3YwvDR
1668 zWE}O<j(`jI?qnOPCu2G)r_Cs%E&b~%PBT(n>0O4lK31n4MuPGuF!j1hV;<1<T?Lq(
1669 zj-l#BFS)pwqUp!de9&VUb1C^UdU2<+;$>i>_D$He?sFUpL@(BG2w*3C105h42VX@H
1670 zRoJTmP%R)8r@j<@1E7j&!ah*(V$+gtE2*j95eXix>0Cr-lDWj|G8%vQs=gumQ+6J}
1671 z&ZX#E3ald)ts#Z9mjLvwsDTgHy{SD<s71~HfNt8k5ba#Z<7Xd$EnzG09|GS6@5kp;
1672 zxW5ko3OA8J5J2Kdu&A~)iEYV|gCC>UEn4%lI(ExZAG+=!l=OrS-R+2TzrSjLYm(6@
1673 z8tb~6{5IDV)S}zY|5T1wZ|wI`(M-M@(eIyHjP+l9iP#eGa1+sC^!q_GodOeIzoc%G
1674 z3+yp>ft;k><d;(U4kpRV;r>{SPX^v{JZkyqp-ERJvZJu`MY&|R`yKpZeaQV=Sd@#u
1675 zV?fCEHrYrPpJO-@WwOPb)M_izeJqdh6oMrh5%NB3AtA~b)Tl84Wk)U}<#vGGWS3t|
1676 ztF{eOy0F1i(D?hHsRmO?$@XIr*^XMZjBJ_)*qk4LvT*6$cK!!)ybvkbS*F@H%ryEH
1677 zY5|T+zY7Z(y%uSFo{R@W$N+GlNfz;OaD9a=U!`XIMyIpjk=P7+CvNqN74-5iz^U@B
1678 zVEHm~t@5pmEZ-`Y?|#r!`Bqc%0KlXNwQ5<u-)n&7tA?3~^6@{Y<8^8IKG6a!Uwv4>
1679 z==GJxN0u*H-V}?6RLyCIr2~~(a~w*x$z#>rL-g-$;8a!pToq+rcUIL#7R9z<Av@qN
1680 z$k!HkPMtTib4oCi;2iekM@U@&P!(F9)HndJzfW78snf|Ytoq!ORDK*hM!#rHWH9am
1681 z1A>8F_33E7m#yuEMp92L!B{5E(Evk$T746VcutnRR#Pf6d>~<sJOQM?VD{(~;1h=D
1682 z==DRu^|?#R5RCT2!J%yUTN#Q{fU?>CAq~XmNi1N2Um)*!66N&pM}pn+Fz#eHxFEL*
1683 zxtCJc0&gU}pnZ`pf2INU-hQVwz%F|WMA;VPC?aPJIby`=0?Yx+Lz?9dFcyHyc2W&B
1684 z@tTKW_<dN7ku+E1?*$&=S=t8fA6AWCQ(o2SD{xe-$3j7c=P(O3?rN*0Nbqrhs>pAV
1685 z`V~MGt+yGiq1WhWy~A?f0I1(Ot($c_2dY)w7W_xuZkWe0a>GKS-&0zGWvx*XEML-#
1686 z8qe}2?bCoPREl^i7M`mUiH9`hJ)Ls(aTID)9Ur6Dcfzq$i!S>DykfBR7a7!MlQ<!R
1687 zbX4nUiqMzQ-U`YI>U)j)EV^u8E%gn9fH<xCqt^3nguZ*JPwpb0roPVk0B^*?OGt1s
1688 zz*LJ}mPG||I=96Rb4_(#YBn-`5XPOdPFeEL!<x@i^O~?`3GSk1i(L+P5t>6-0E!Dz
1689 zv#B*&`&!gIumhZw&j;kY+uu`_MZZ+l0Pa;rZQ-Vb5CgbZ8TE_;(&X`Hn?C-0Gc=}i
1690 zt&uKs^cO=l*9d815rzeveBn`6!Bvgo+Xz}Zn;LfQW@Auv-E0$OfCMM+bg3W>$3HNL
1691 z{Y4#C=S1Do#6V#OHtKGDT!Zs%I*m%jk~stFr^5mF&xD{g+-z8Cr13P7fH5KZZ*r9@
1692 z*o~D_nc@|MUvBpZ!DgE-9j0ID8}Ng7`qR)+qyH`h8+$st5X$-%N)l5e120w(znTKH
1693 zlui&aS%su6*SuHCZPYgMfDg~q>~x{5#)>uwh59;NeRs7p>CN;(5`FSYm0k;$|I-5{
1694 z`sj!QA6An`X#qbE)%v4cP99jYxod!la@gXZK^iR|?nh&dfs>C%;kM0izDceg_bIMk
1695 ze<zoGxF0Pa?nkSK`%Zp=%hvZr#dXEE<dP5fqvgZ>X!UU4$tSV4!S92r9`4(!>ji3y
1696 z5BF_>I-sqG`?eYdsfYWvB??jx_ialR6d%JG-*(BveVg@gKZXzYZMU&d*28_<?R4IH
1697 zxNlodC;4#Sc^yJ;@4`65$}dhiTz`RA(fffgqU9H-qCX&S^w;>c8?L3Gnhwt?y3Q|7
1698 zIZS>C8?MLji&Ktv*O58F;eG+da<tb4L5!V`CLxy5@(e+=JVWrms(TaosE#9lyhjg2
1699 zgE$7nX|OE=w()@^4%_&^9w7t>bPUo+ARGJ`q>+%3G_qy{#xaM%cAVWD5GTKQa{xKl
1700 z$=Z&0b8ei2WOH~EXTvX>dvlO1_9na8U3?_=ZnE+3TisQ!-@F;&__x3R|M&k7AJo<L
1701 zs;aB2tE>BUy*D$#JVStYDIj-(d4^zud4^zueTHECLP#I~0cvQn@t@c<bG$7+at-^+
1702 zie`-0ZU~uD%b34_drigaq(4KfbX<>T!AP%!xEGfPiIt8Qr;+ZlnMCsq;Nlg)#b(l#
1703 zIV}*}Q7G7(<m1Z>Ocb7qeeer(GK+^}jG{YW&e%ND+79Nro6By9iq(12+B|CQqrlnL
1704 z=22_Eqt-^Ft?ejkZL)b&1h+{f;}Fxooy+yDXlFm#nQ}BLDQ$G5Y)Nd9;XTO|pXc%+
1705 z;*DeIrqS~Si%9&>fQtV!8F3Mf;8jUf=TR@s)xA`$LSwN-10enzRHyuPwAr1J4ot;Y
1706 zso;5psdzi%g;*O6QWXhYVpKZC+~4PN+Gbp$CrGBzLk>$wrQ3j-^6h9V-O>sPd>zQ}
1707 z_y$p*VZxWV{BsgW?r8*?=Qmy;fzL+;_Jjq}D?72}Mxa`rfLQnjm$#q`F%RBq1TLpG
1708 z{}iYxGx$3Dqc;g(1uu*D<QP5J7`x60tYX4dTz;Pf(km_T$%cr)MeUHdA}X=hNt~{4
1709 zM8lI~tH_i$8Mz52-@;`UGGdPfa&IDrCrNHwRBoS>J2_TP66=h_9ZYx+mlNRnu`A2b
1710 zbu)wNsPFB-#UCVdnd%9u(z8dgIwJfRRHy7MY_CioEu2s6AT+H=;^f#1bRM$KsBnmR
1711 z-@)Z|9k_IFpu#$0I0D?1w?-Q|7P9^cn&F#_z>`e(2`;}y0zU_VQ=TZ4;F(9}Cdclk
1712 z&Lj=*DW>=Vm-9PuX&U+-H&1{j3G4%I%HKyt^*aks*Ayl(r%7&yk$Z;8U*_^-B)5;`
1713 z{)#NoLEtMS_l2n3JHm2lfthSx3X0uo<f;`3G=<wJE;qqi=CPaj{nYraWW0CakDb!D
1714 z(v<#3RHw{h`oNWUOEW<PoNV6OiTS3TDyF}l%bKl_z8Y~keg(DT-w46418$nRZ}q9!
1715 zuc10+Wwf1v67A6YNU<K%PJ-!W!$8l7#Xg93tUvaUU>`UeV|(bzU!XdrBihbjQ9IMk
1716 zLO3Hf0)@+0jf>q5QL#$;I}?Y?P@zmcI3?J@yc1M(Z3hef1(#hQDSjJ4UI=>iSBK8~
1717 z&XCEidT+)-lFO}@>yuQqdmbD)nrq>gKjf97!<Yg50s;|X1vlSrJFei{ZO0XSyY0Aw
1718 zZ?_#+@a?wa?7N7x-=L>q@k-G<jnv=;1X~SWK(N)|1q53SUO=$b-~|L*4PHPv1=Y(I
1719 z1+Nr+)l`F5ifnIek`=EM*{V&ljw?*E;*}z-_AbeaSBh>kbxyM4m7=F1JNyE|k4=5-
1720 z7Z7Oc93)xsN|CLf3|=X+b@u{-t&jZzf*C(avf`DZUzqkK$?9GyB9rh72-Z6C0)jP;
1721 zyntYhK~KZJ0Sx8(NvK<K5`U;)L6VhR!(g8mY^9p;L3sGM@r{%v)t>=8ev=i3*<`*D
1722 z6yIk|PmxYFUkEzYej(^I^Clp^8Hz}wQ{yF?tJC2t@lQZp%)Eg7(yfU3X7@FX+Qw<z
1723 zjKK_cB*cI4HXPuab!9qL|ADH1Nt`pNx_BEVW|n8&RggOKu5jfbS8m3YS&wj~6O}X2
1724 zdA2#qn2iI}YiFC|IyLK5h{OY#BdKMQncroSBe<;Q*t<uvb}Tl>-aXpNT(fzdIGL1;
1725 zQS<Zgj6SVr6IL6u#7K+z58x{BwA4<x-s0&c1%sbYtn;ag5j%il0omq4^TO1m<*`2p
1726 zKBkUOgSpgX{N;P9w=S>|NxrIk%5@14Dz#@S2upsy_J8{!{c-eMN7*MR4wmb;<8Sfv
1727 z`r{};KW^|ox>#^SHeuZ4#(pfi+T_@^$+2sbW7j6fu1$_zn;g3~Id*Mw?AqkmwaKw-
1728 zlVjH=$F5C|U7H-cHaT`}a_rjV*tN;AYm;NwCdaN#j$NA^yEZv?ZF20|<k+>zv1^lK
1729 z*CxlVO^#hZfCHlowaKw-lVjH=$F5C|U7H-cJ~9W}H*Iq4+T_@^$+2sbW7j6fuII&Z
1730 z45>|yU7H-cHaT`}a_rjV*tN;AYm;NwCdaN#j$NA^yEZv?ZF20|<k+>zv1^lK*CxlV
1731 z6Bzp&w8^n+lVjH=$F5C|U7H-cHaT`}bL`sY*tN~EYnx-&Hpi}Qj$PXvyS6!YZFB6}
1732 z=Ge8(v1^-S*EYwlZH`^r9J{tTcKs~ucv@+jW7jsvu5FH8+Z?;LId;6_LpgSBbL`sY
1733 z*tN~EYnx-&Hpi}Qj$PXvyS6!YZFB6}=Ge8(vFoRC&hQJRZH`^r9J{tTc5QR)+UD4`
1734 z&9Q5nW7jsvu5FH8*I=#xwbC}nu5FH8+Z?;DhYy@n+UD4`&9Q5nW7jsvu5FH8+Z?;L
1735 zId*Mx?Aqqowau|>n`6g=c$8z;Hpi}Qj$PXvyZ#n*ITX`2$F6OTUE3VHwmEifbL`sY
1736 z*tN~EYnx-&Hpi}Qj$PXvyS6!YZFB6}=Ge8(v1^-S*EYwlZH`^r9J{tTc5QR)+UD4`
1737 z&9Q5nW7jsvu5FH8+Z?;LId=U+OpW)%w9T<=n`75D$F6OTUE3VHwmEifbL`sY*tN~E
1738 zYnx-&Hpi}Qj$PXvyS6!YZFB6}=Ge8(v1^-S*EYwlZH`^r9J{tTc5QR)+UD4`&9Q5n
1739 zW7jsvu5FH8+Z?;LId*Mx?Aqqowau|>n`75D$F6OTUE3VHwmEifbL`sY*!8`b4_}RG
1740 zn`75D$F6OTUE3VHwmEifbL`sY*tN~EYnx-&Hpi}Qj$PXvyS6!YZFB6JbL{5Ds`0gX
1741 z#OjHCSUi7F{#$xCY7)IzRW2`9O~T@%%H{3!N%Ue>xxAe|iC(NKm$%a=5p%h`onApN
1742 zR+TG$hkQu|Z6(Wtx6>;gBB{aK>G-A$RD-wED~6#>dGL061-)2R9=x4iK`&O72XCiW
1743 z(2G^&6Jz_(dfB2K6}2R}B6iSJcU2rB$-#?N74%|NdGKOY1-)2R9=uppK`&O7yBDh}
1744 z=*6mX_hMBAy;xN~FLpn;Xe(JkFIJUb7<;>^KNzc^7puzMi&Yi$VpX|&v8sYztSWae
1745 zR#ni8Rpsu*stS6s3NKC{Ml;@`Ct?-!VpaKy*t<>r)3FMAv8vp?SXDtUR+V2DdzWb+
1746 zTgl1vVpaLOCYl$k%HK;SnM5yEmA}tgM@^y^tIFSRjiV>gi&f>J7pvCLRZR|I-Z-az
1747 zO?@32CoGMw!J0cq!qW44e+ld~+8~VkXWH<rxRJnrfX__0ZVkZrIDPL+Aenv-Q2NLx
1748 z0gk&khC7t$cM{@$gNV^Bi<&`S0W?k@oQE^5%8~S5r4P~7%AsMUA9xy&nz#iNRr(#b
1749 zgJROt#Q#nL>BO><YVV=9A@ES?q<g9M-Y<d&zcw%_Mz#0Z+FUi0)R{@OS@ywOdz&8n
1750 z2zY0kw^z5&t>&Dw;EHXf4bYsc2<)OknfnuT@-v_`tkxV<HAb4Qrjd|&*ATgNvDgGG
1751 zh8KL>AjoVNe9(Xf`zr&!n;I}*e_lz=&ZfgUb9xEeQj7C#CSr-%8_EVSzcPVK&}180
1752 zdIe1^Fi$%yp(Z}G9orc5e902x{~4+aHd0edsHv;ap^K=EE2*`;RKtT1SN%CEk5Q#B
1753 zi-#SqCdx@Za%U5`AqwjBlzNp-lvbG+YA?Qlul_Bre%oHfOGdaj{(#D<g;n@=$a?@R
1754 zP#14x%3p)>p94yD$*vF{vgs8i^!OVva_mNPDsYGi&T?4?tzw@+@@>Ip>eGz`z8Sa+
1755 z@k8-k{Sm4QjR97l!d36sxdRuO$31SQUS75X-TE*~n*vqd2pTj!(W|dd;5t?4nHVUK
1756 zFMU*({0)<i$99}Fq$|i0?+S=17g~i(;vTS;n=>vmNlrto@rrJA=&wju`^fk?mN)yF
1757 z1U06%?ZBm_SpFB84$&zNWxyAj{%~#J5|62AtVxSwyGYApIMi9Z3ocj1mtW-a5fb`U
1758 z>>Dn<8&`E2!2JMH1W?ZB2>_S93jn_Vk2`WXy|S>1`6&w$>!pQx$+OIN#XkU;^n6(c
1759 z`qAggGoZPY-qP5<6Tt5Qd=9`Br-{t#WT_`EzLQ0g2c1JVjj81_IuTp0E<VOIi(%u1
1760 zXcRQDTI%2)fSY40VBXmBDm=?VmhM8@>8kfL2l>-gzY10GFe@44bBsE}Wvt_`Aa`jL
1761 zT}|exCexTySi~fke3!W?6=z2MVeS^Ra+ZTJE)m1sZM`JcLJ7i`$&E*2>e>VuOx@1q
1762 zE!}vOBlZz;i3716jC_(yN_1ADQ_BPqdk7+tx9cJLKQVLS6x04V#4|s3ArZVSwhPQ>
1763 z_=4Ogehe*|3s?OYUm+X8TPf5ox`Y_piEk4A+s~O5bQ3)O5n3l=u@!U^JpRL6q1Qde
1764 zf5cW+nzuQSrrZL)7{!5WC<a|a)oaytvEQKq9JSgTTN*5L<r)f1*SwpWx-Ld<a!isp
1765 zIcSy{5?r{X4DH~XuZ(DN4J(@DU#nKeUI1Uk^=7Fwxl$+8wn1zbGA?_ac@<;4yo!-0
1766 zdFGFmSFY)f^*WQ(orI(=#eHLXtIev|&9KsxgjI&3`=wJWE4-=mr*>d7(H5hh+$dYD
1767 zDk^RU5;2ECs5)-8@}}NUabpENnuqRHATE?sLG=lhF>h)`1znDzs;30Bt1!_ga&>%T
1768 zB~>ShB=j5E-Adw^e2HqTtbxcWmjOV;xeR(w8y9mj<4YiuZg!_bnzo9Nv>BBlqRKg;
1769 z%1oyP*2pQ4OZ2nH6{tEVsE#K+=2qh>3BP=DV`Y`;%)FIBdsz2y-8Am5&mSLj7SSBU
1770 zft4<-j@>fZRL48=i$G2iU<?Fs<~5Zn<~5Z|0^X1+3&Yw?kIjfB%HOeOGU>g@DN%+Y
1771 zT<p}K>ZPs=RK4uN*s@Au-&)aSx_Eg79AQQbQF5hP25DDNL6ld%;V?bHO1P^4f@+x=
1772 zuB-n9__9gI*1(`k<pP3_)2~3g8cXu_HIqqFZ8bL^XuoVcx3|2o*9AiG!yYp3q}odA
1773 zL|d$*Tsm<L3Bi=A01h+2sbYt56`7>5a^>U&@ayX<(AgV8MnXSs<SNWh@^1=Nadmab
1774 zX2w%)4z+I(w^$?6Xe5mNz*R@e5N3_>Z){TQA(p+j3<PVP4!2Cc3Cl`DHJ*obK0~N=
1775 zfl-Vb-DC!Q{dhA^Hq6C5X$%M|UZ0psu4ZXA26!-9)TRJs+{z-Gf;JhcRCAclQnfgg
1776 zG|(ELOal~ZTtK10GvP$0J2|`r6pX<*7hC?H4<~`5=wX3ZO)K=OxHvNn+Vqf@&%gzq
1777 z36;??n;A$C>^#d3&+KB$&M74R|B1~SO}q#u?6g8Jj)$t4I@7~OoDni&rCh*`OJTs8
1778 z<!nmRVz#T=X;EM`alg6N$ny#<N+X9b&9f-v<|Uo;e`Bq)D-?c}Fudf+8i(c3tZ{`)
1779 zUWLp7%6;;ZH$|4bso`aAnk;ki!ewrHc$u3~*u4UW#&;0O3PfRSX5rAxl1Lx2Fz(yj
1780 zxXcX=mou!fqG@IlFE|&3<_!jHzDOYJF9@qwz;$7W3(8$&xp-Z;Sc0W2gs|lTYzZ#0
1781 z5q+Wa338D|p(;czcG34zNad+|S$O^hn&8Q8$87y;iBq{CgkE7?>`Hgph1aVn_Ff%a
1782 z2?gh+0TNxX(GyFfi|ZCu6IPDs%+grsxBnjw4`GKKW2YAGvuvkkuz#9ePNiF=Il_p4
1783 zh2sN88}T$)HZj^E?<FUnQ|RP##mPes90_0-I0qnSnjaE?>VnW>Z#GEqTe~4*kEM;q
1784 z#i5x}Rn!mJm|eo%g(Hxr3ny_u=%wsM;_z@@+OvcmH$0y%m(4@SOUVrj=KU3J0z|wu
1785 z@Ozq@yp7{2ceOKvod+S$b&g(bCqYf&a9Ss>rAe^NULlT^ywNDw$yw4B0l%3QW4Lzd
1786 zfNbwK#!DEbtweb^Y)+7{`RZXgbnj3RZ2rwCPj(6xnRki|2<}Zn10UT!6pr?Exj%9N
1787 zo1+Ad1FcbKlKo1qOyR!%zrJk>3}d#oQ^mT|&SRl?r0>qPXok%Q%`munXb)vpDHpP5
1788 ziJ{3`XNOEplbmm@tgqr;O@gIF*?DBml8Zm?(#UBR*v0$8;?P@i3`#p=cw~yUu3@j#
1789 zVz-Hfn+0S&q${*ps3_blOcwdL8<x$&RM{*{vmJ<sqc7bNvt=qOrc_L>F!#lC3ic<J
1790 zZaaZZ!8OJhvz!6R-|c-8g;t&-Hn0Y_vvX+x<PHj<)wbz4X-g0g&o7i+5ULh9LK^(&
1791 zrobscS1%6xLsiHhE|Cj}sv#EGGrToGb#c-CChmuAIKND8)GiO*&6!w$Z!feY*Z}~5
1792 zm@93NrU1&ji>sr{#8O#!s!1-6&cbeHO%Pe*3u5y!E1F~T@-TB~b;PslG!XU##Lk43
1793 zg~qnw7Wc#C@z>Inz}>LheaK{4RoDRSKU5C4sAY<>MX}iLrcS}%7+^*9o&7_qW;8ca
1794 z(?8TbFxr!;xog$6{<SNY4)hO=-nF!EXtZW$KfXaTOkyho{X1*=y1R?%S5{vq!c?_D
1795 zH3R+m!O@&U;APV8<+<Vhq3UkZ17DuiKh(FpdKdIWr3ccN_6}sz`7j1BPWtluhBLVU
1796 z-IM7BjMG3c^=B;wm<1fk`@`vx^dK(4258dn&JGS{hiu&{1sERLm&xO|^{jx=p?-+7
1797 z@J%~M`v>w%`-g6Z#Z)?%%ZxBpAPL-q{e2_pe7_NlDo)4Bl2r);l=p&)ExdZ;=N~)s
1798 z0q-vT)FWT>rX8($>^)75o4nlj+PrDct1`spJ%`H{&C<v82fWuG)EhUh)-~P~ef(oD
1799 z>V-e7y7|d_zutAR_pfT}>%4u{U)-f1*m=i+P0jCW{^6+Jv{yfI+rR4C+w|UNdlqik
1800 z({*pxwpH7_yYPec<I22=dIpvHV!+>-uvJ$!K6Kw>NA4SkV;;2m;k&k$A1^<KYu}u3
1801 z^qI!JO~)R4YjEk&cigZG-?&%p-T9O^E#GzTYK^fO7c1Xd?hPIH=4|x(A3avKu<}Pb
1802 z@lsiJrFWY?Yg(+O?v&}Jdrv~_;}i6wXy@~H9X{~=_q@}KAIFS?=S?g-HG^&QVl3vp
1803 ztn%K22lL+KYA=72H>KChZT03=d41L1rTH7Y-oxI-k3R10dvw=bUjJ5aPVfC6^>T;3
1804 zDTlo~d-r>lhrK%v@Au{(_R_ugzUkn-re9ZnMj!FMqYitI9z46pt37^XoacRMe>F6D
1805 zv`pVLZk(4Sc%H7_^nFw^$5EN3tMA=2idz3x)UMPU0d^Aj6{V|}9_v5mZGWl{Vt%rp
1806 zkWWL5w{7c_-V&H}DMl>s{ipiO&D8iGw%vzs0bRHCZ(cYC^0WI%__v7M-}>azO??pC
1807 zM5xue8el!?v3eu%mG_pv0EVv`hL4wh5Af6bH{$Zg%X&|EmmT-|j(ZEAdi!U+PwfB9
1808 zGdHgGzN>n@Cl2cBBS*UW_1m7gv8%uA=9xG5+<NleO`W&Hi-vFV;)lKAt=>$%(fd%@
1809 zVQND!DnE*{tXzMViZ|0AQo8J%H>Da49^RivgRhi53iw_F-|Oj(WlJjcN&VS}-l{JJ
1810 zZS1~2{p`m+d-Wcjcm{)@D<AmAh9mcXWc2a3cJArdUHAWB=@Gs9zFWJt^mX0;xIVVD
1811 zX7FRg^;z#X`;BLKZz|KrsZH;F`ycgwTJ}`ginupp>*)PQPU^lB-|&tc)HmsO>-Ttz
1812 z^>Od^qu%BEGpmjqdGg6V@0$mXdxv93y%!GXs_Wn4{qz7ioaa3sD_a@!-WSs|x*qq2
1813 zpZA8(dTDs=UWlpuTkmHIroX%F@>tpON^jrcO<&)lS8sVH<GpkLQ{ETL^j7cgv&8Yc
1814 zd(L`KcxSy29X#tz)yE<B-|rz?EY#0?@w3l*C%wZbyiXiF{w{CVaqsm0<N8+b>t)A}
1815 zc%MCZ+*@$md+UM2Wmi<5cuU{0W7|^OzTNW4H<rzSqyGrAzYO0Ta=x(pM}^UF^eqm!
1816 z#Q|DzXyVY?V}m3jtHe%(Q3;Zv&<PM3<{^%vHVPvM0!{HuzQTRprmnK7=pFrtN|~Y;
1817 zX^Iw=+(`FpSR`I+@6J!3+ZS48WZ6;O1KIA~IazC7%^>;y!HkXm48a5pVHF9jDG2ql
1818 z?y!~Qd#JsMvF5+sbV6@x+|<%!irZ#=rMc<q$DTP-HXau9F&bs+mh)Qgk64mlv-`Le
1819 zSZoul(FKcqv73=$;Wf03TRVy~*%jOR7#u5PkdTjsj0O{i7vA3Pq5Ob#vtZqYF(WJL
1820 z;9!~-Z9Gs?xFC~f$``qM3uF1W)TLYXjk}k2eYp9;``<hJEu)Q}@0x$ooAms9uX?`!
1821 zUAJ^Ct*L!xY0a(r%ihH2EA>C)UB{csHq9Iz9sL_`Vp#%rClul+u#|7b-|@ZpgV5YZ
1822 zm^TrkTrdM&sN(fU{JEa4TKe)n{h{yOa{VpauG)0#Gx{NYG;w93>&BWIZ{kMpZvE8#
1823 zS8wWiE3qIxJ?c#<TM|1z#XL|f0)H*>e1!g#Eu85M_bxgCnO(;SanNFo;zp$!Z}Qo)
1824 zGPu|l<6=|)7#I6LJ6oMcg+@_g5qtvU81Wf#C5*fHjHNL9I0CzOWoSbNg1|`(1#KHy
1825 z9+LpwogL~ON}D+x@g(>jd5nA|i}w%s=GdAQX4_DnFF*EGY#DU*rGM6Xy<T=J8MfRm
1826 z&SwbThDGcCGFrV~*?-o%>nX3|Fedn-<yStP@}_=o)Ehl~TgOA*q{H6Gac}C@0e$R+
1827 zr8WKD^ut~@e?&k2*p{2OJo#Sj>zZ3SMw>Ql+GNCk27kSBO{3?Xx&6L9%f0FPDR1I&
1828 zZ*TQcZ_?H+@71f9)~wW@(3LlCdc#=w%e=d{Cco}Y-RO-zb!(<e<8@8isOcHyD{gD7
1829 z@%A2V^rk$oe|`UnhaT#Cas91_ZYDqR?!WB^H`Lxnq~0jpi~zl?i<Zy}4sUO7eWs;Z
1830 z&(w>sXkzljYJL=}`AOw(@y|pr>=H4AAA&7Q#{R$oT#QMNbnl{=65J4^bAv7x6@(s)
1831 z_P$&<o-pA!6AB$Pw)?sV%>EytreHshYe85Ey9p0@)v^SQJ-$Ucw&}^=Y+U{QkJ5hw
1832 z>Pz-+ta<W>!T;4yeuLmmy5=EM5;;)jKiF!%|2eQ4JIph7_&10xX$P}Xz2*>I9D0ja
1833 z_`t$gn9{l3f9%30)2J{^3)aj&6W{IKQs|xrMhtBYXbQ<o7T%QD!mIa;e*fl?Tbkec
1834 zE8NF4ed*sHE1Lj=OvH$ksWpF0{5fBj{}0%Ymag!w!8x8dsM?(w8OjX!{k`e#%z2l$
1835 zP^glX&Mav5mJ=Xhhv*g&aL9GBRgjeq7lI%Ln3pzKKNPoMI~f*`nEe;O1>!A<t+=A@
1836 zinn*&xSHndGK2<{Ww<fZZ#~kkXTM(W)idtUmvrenHhpb%ZuK{sp81@fd$P01`@+Gk
1837 z-WTz!I$t<=6K;>Hy+;l{<()zK!Gn4R?qh0d^xM`YYQ0=FZU?+?sIB@T@2?J)Es8Cz
1838 zp_*5rdpCVw_fw-OeT%NV_zPyyDgR#i<8P_S=-Y75`hLbdT3)l`k{=P}8+DCYjC?=a
1839 z+w12Qe&)}Ic`_q=(s*^8rg=vBjjjGjCf(x?<14fWG4ZqA%J1Hl#?gfD=Q6{}&+W>N
1840 z<msU~+Q#|ABiVemJ3HX_W=DLA^QvZ7b}&-|a91`vw7X{ao<R)kP8$w5D)_`o@|Mx9
1841 zK7HQ_H4B;k&U7xL_IBgDoNx-Uyn6um_-JRSugd%x9m@6h4P|<&ptY)RYfSk~4V?{5
1842 zex2$Cc_uv=M%Js*T)Ho#S~{A2N84`Zs6UwP$*8r-`lR39(5!Z5e7nWT`1!2glO3e)
1843 z_U1B~-J!;*O}w~BdryTgoATjLG~Ml)20D{$Ye=QK{B<2I^{K|z7T;I?o_u=eK!&VM
1844 z-%dplk~oy#+mELVv#K{cjPI7RhaGBfy5Dp<j~AYYcaa&oM@Mi%GN48>IOo`7PBi>(
1845 z^fHh3^CNj&@p}i-eK|7Za-W`CblvpV5SvdEB(QB}2zF+nqk}_6A9En1da|R?Q|(Om
1846 z5BT&QRyp{>P%q>{#^^v^rRv%@`R&Qpwz{>A^(wc!f7l$|WQK4Wl^e)phW(+;T{zvz
1847 zjPyhMoufVIlRrp`q3hSKgsb(8+9Mg2xhvD{8yj}-8XelbOqpW2QF1Unf~jvTVcaR7
1848 zg8~B?vW3y0p{}i|OEuG|b+(&<>mA0PBj0Ps)OZWp8o<D)+(;VTwf65B>EDwXvI7OB
1849 z;A(qE`tup%;yj9lM#h$<zfbxxoE_-z-lx{o)o)tg*4ojs)+c3@nFdt_9@&dK8|Z50
1850 z1?)f#t!r#*FhDN7Cu6<47slyUEv<e-%evOK`iAC)mXx(Ae9zbs=Y5z2>7l%z8N#&c
1851 z&J4oRRxHi1+%V!Ig*F<huygce;1}6_sx9T$H`TSb`)eB7Q+~rbG?P*ooRRDZ(Pu{?
1852 z(#NEuQMx0$(}ybt)1I89J4fEsm*0iZIGW4!C>+M6NBUGA@-cO@!z$N*cP8*HYfNIq
1853 zbQJ;$yu{ZJG&_VfB*rGtuf26$isG`FM>HjI(KtwVHkUU#8C&MnF8J{XyBEzpnMyqQ
1854 zasyd-;`)}3s`@G%c~-BWDY48<3Ev;0NVd77t|f&)5VpBLoXx2o@{^UTR5v_A`PKt-
1855 zD!cOzGk2hm@7r@mzZbIu5iw6&Tb0gddlii-2}h-0^=5zx=}G<{cn1RL2qc-~%l;uB
1856 z!_+;zPa$^pnUL9&8A$I_GQs?0Yg1EW%X%>2{d)3cinu1`*$KbgPKRVeTVpFtNFxv<
1857 zYo-c%Mg9slAP_X*c0Gva#;1fMXn_WkrkYyU++;)H+I0-j;sEEM@C%w893YR7XyO9J
1858 zXX+m5kMmr3DSQU@gTeP?1{4%PYke}`%zULNi+L%l4S6p;K+h`>3}q$-MvVg7ZhypI
1859 z)~)trMt0JCa(3%AuBPCN-Kr<EbF>d#gXOGGnz^I;he!{5z&)701B;T`q>4iaer^^T
1860 zs+oyNJxJB9X=?D-wl#J(v^W>tP}jDW9hk-=-LuRVh*(r3PeZZN7S|{!k2q}G_eY29
1861 zI%j9maud*D(#S|rclIc(9`%jw4FwKL`)(}1d%I1%q}duoPaDQ|rn`5K4%@I|Ixcg`
1862 zhIL-kRC}8pTS%ZUY(Sc!1`~)6{Qc}ekE~D#G$VbPA$U*bE=&hV$ze+N1j7~%p2mPp
1863 zjj862b{`Yk#6<2lEo*j(H@=e{Lb$>_#1cW<2iiK23c<OU@0;x`ahOF;<@fkQxlA{e
1864 zRKRb{A_EzGGlDwy1aNUO%-vZ;%lzGbPYyc?tj*{pmD%1N%qfUK1nahEPCj2!L+PQc
1865 z6$!pUWLFT`_9D0$c@$NBvqW(N*c}03POa>89O<qJ&akMd+%Q^za@10Gs0Yig$_-~n
1866 z(mnm%e&0ZLC-}*p;+8OLzMt|FSfsjn(~E7c8Nl$?S7k9UFy&no0QS;;!wxIH)onSJ
1867 zY}%yIcBQv}1W}j1Qo&6W3NVAicFDkq2fne3wss23bq+Qd%$QY{d^Fg`ImH7l5$$L%
1868 z+|Lu*Q6NW^!{!m!2T2CKhL9o2etW&2+R)Zew-$RM%&=rzYpS6hft~}@AXW)1^F-F!
1869 z(AJK<l7U;A{Fdgrtp;xIYN_AQ*4ol|Yr|Sh(x^!6{JOxtp<!)@4U`bof@bO)+S^;(
1870 z+Wpp+CMz?nMq|qc1k99?)!fkB+SVnSi3X|0=7!deRJ$QrQ`e4_8-kOKjecu;qhH_3
1871 zSDIT}T2s)i9;<9?{id*T?RD!Kf*qih)7aYS2i;1+D$PNaB)3CCgH?)*1qG$gg_}|{
1872 zzGSg${l=!`isgRmx^*iMgn;5s2Fpi#LmTXBF12sK)NF3F#^|s$HZjbdYS@|*)mX?{
1873 z>=@cQ>Qk+4eq*Ykt&VoGwjasHq_xMIdVg)B>qK*1GKoQ=jgBQ;?$`Tk8e7&H?{+7L
1874 z-37aB<A|ZnHua-<v)`I*XbH@-)zsQIG@Gt8wxB1h`*NSQH2&I#PIJi;ZcVPY_6Vvg
1875 z3a=ta^Ke2|Lt6`*z4JQ1DTz%g40^34S=-Q5*G10I7PQ#B2DchcwNkdOgE?_WLOPl~
1876 zt!WM8-9(c7_Qv%sbxqbn(7Ul7s3b!EI=GP?tH4){8~g28c^cLlA?<aYG!52T?s~te
1877 zu4TR7-jT$HJjKjg*R)@QZmelsPyIk)7-=ZNQw&q4j{8Ib1KS<C8-Y=l`yCivLIw9f
1878 zIdh>g*?Fx2FzPfT0)x;V#ayt~mVTP!B18*wslBT`)zIv(t;5nvytbc#4rmU0xqNmM
1879 zfrFGV_j1ep#`-$UY#;mA)_Q}dNP?l*g1Lc$rkpiIdslN)YirV|WbV(gTIAEcy%g>C
1880 z8O~H&9qioHy54LwvO}~9qK@0XvBB$;9W+8A2Iw91(-=0Gabj4Sx#C3r+VyR9&2&pP
1881 zME79UoXIuqKDE9HQ4crMbi-$^&@}PuQmMAaH61CQFm)2`TCtRJuv<qs!_n5TzF}+9
1882 zfNY?(Q3FN%$<T7=s42fa1x4BsSFDs)c+VORgxHt)E%@U)+_1T$v6Jr~%zX2$ZDF?F
1883 zk&NvH&rB1|>{t|z9fER0(4Of)fg3LO$vk!S^|+f#*^Mrw8|CV-UdSvrGU39;9STI+
1884 z_QkWoOCyg}mu%m@p@BU!b!$r<W}b*c%qQRR+c0~qCF(kp8!*(#y7fWm0!3X@!`g;*
1885 zMixRt(a@W45t(O3(-o|#b6hjnb`ltIrlDXM=;UH$5l=Y2i?<<mZ0>02a9wFn)@`vd
1886 zorj*i2FxX5fY>RRW729cM2PuVm+VMV%#gs^fu+Q!o8Bb$cm?r0i~W#U{Y}ScZ~{Ba
1887 zd>S$*rPOGL9aOA@hI&IQ?n(=WrZA-8e#TB!L(Pu7sevcuU}g}59lm7TJ6Pr5%yr2P
1888 zt!+G{9pQDOenVr^TBB%gh))hkzZ7PjTclgK!{RsX@K8)z-d>o7t^d`xbtO}#UNHUz
1889 zo=PV|1zn}cu{G7GOisiwn|LVmk>?Rl@nC?=Mgu1vP1r}tZiW5X$k^Dr2K$qiR2#mJ
1890 zm3ma)w8>8)`0U-)-@VIV%yMQ&cuiefTO&4J29LPjPA(q|Uq=(g2kAW4WV45px{0WU
1891 zv7pa^qV37XmQaW;>`q`AI!(ZYl}S%JAR>mE4R7YqFFPB}Nb+7LJTtKk3h$MIt%ZnR
1892 zhaq3zY)7h{G!1&k>hX#bbfOKnfgN^TA!F99?QF!hvI`M^o!yESY@~SU4R#PbF?>2B
1893 zF_wxfg9cZ)YVsD&jtDz^TkDz*%#(s0G--qRNsBm^Lc1?Y(m{_5&$>p|u&&LGq3NZ>
1894 zQPW9tmpy7%T^o$C;?{3Uw!*|lJ>Foob?`RYtfL56*n=Ucp>5kSEFPV8O%j;=9Cew)
1895 zFa`3a#&&pXpj?TLh4<w4vb6zbiD|(u;9;sQt!-<A)vIuE=It=eFxsy-)BUTx(V|_A
1896 zc*AnPeM=DF>|TU@%8p4#OC#<<{2+L-IHOKSuy>)6;N28+^X|RqzQj&i!;T#%)Zb)Q
1897 zJn$FpFl|?@jSC`%3F?7&QN!ySQtR7%tn1>-;&O#|gP_FL2lKH&95xeeK9*;<o2DKH
1898 zn;E+l(A_MZbCK0J2S6RhD$tN@3I?>TZVTVPw3`hUh;z!^j@lhCo#vR18xNFKCx`;Z
1899 zhM{e7Gw$B76k|QcET!WwG>N;E=JxgC-gZyy^W9tPnvDpD)?sL1?3riKS+nsPOb_F^
1900 z#y%rU9HYL8nNnSJ=TbtNnG=@BZ4l5q+GZGZa|d?y1xrG~By(GUf*Ts10PN_28Cz~`
1901 zXtQwz1Do6u9#}GgouF(S(|TJ9JA#0nrMjJ7-P*Nnq4NPVDkR8kM`#N~#>M$F7HT8T
1902 zdR|~RBCW^n-rv&DxPC**1s6L%8d^5^jmuWqz+h2L4eRUbyNoQ17u}u6fQ2>?=CbVz
1903 zZL(5!3kLf3hTtX?H3TkUwt5*6c3Q{<iY+EC;zli17Z}1Sv$eh>*le1^nS2^2A=aC*
1904 z=onyh0Ot=Dg%NcqI`+kJ3C>;YNq+cn9e7I7m?IN9G?&c85N=<5I;rDqIN~3zZ8)t7
1905 zWrz6O3O57xj25TWBj)^^PJlugcB&E^j)Sav_QZ#d=uE~+rX@BnSsb|Tvv(JK?1nR1
1906 z$n}Hs2V|f|ao~!x0_2`B5frir86@e3RsYDH?kLTi>=LFsJBl=eS(x)912}9#@{HyW
1907 z!ay1l(l{xm+Ze0ZzW&Sr4t~;i(LE1MwS9C-g!BV5j%4l}#fcht5tN2;<1jdkgd;>C
1908 zW2KPT2~P4%^VIL~(HHuk?&%q^$7WENlo}fGT|&sGvB->2){>6nO+t;5kJMq4a3byP
1909 z5-iXDZmvpD@)l|Ey;|Tc4i^`A+9j6GQ+rP<smx#`nBxLhI-C|b8)lZuh$D;(oO3w5
1910 z`d|1Fjr&-;m`V%i*zj`%kxwz(&Jt`}BV0<@?&a1dspEl0g8S1zlO6%zQ-b_gjC;wE
1911 z|Bk`&+~1h$5nC;EsIhd~%iLwE_JqJ<{+MbPP$b4wQb4gYs00+-fhyYG5VtcDD4rHj
1912 zxXRSA9Z@z>X}@C=@Y?}u=g%2@CP1YHbcX5{LrDi>YNvqCP~A}tKF%^-bEzoFAvW`U
1913 zT$29_`~`=@_pKFvgzwEv6H^@m{#k(9ETBjlhac_gI8i7Gzj?(BUv%whf&bCr;sT#_
1914 zxWE@hrpWp#(?Bl)g&l(~phzmMmoR=ekd^!igTh$CTh1}bb6k=|1)je!VHBl6A#jz$
1915 z74=4By&P!JA)v6MHv(SFl42?)pa?JB!T(^f69UF$oIw##qJtvy5+<b%3VgZ4#RdKj
1916 z;}9}WDXIJ@L@4kXhtmT8KFlnYvPB6+A2OrBp2HQHv1(z0$W_C_1QmFVB`x4TEKCpv
1917 z@0GmZ{bu^I6H<SEVS>;^DxkC=q~?0)PjM?dqpeVwkQSa@m@v$k$^uFYrJ_l(^bV0O
1918 z_Jb=3D2>>0mzvlLgaS&Fr5&WW(Qaupkg1OC5?Cx1Q{4iJd~|77$W{g%SeP*7pK=K{
1919 zQxE+)z?U3JCUn(+@kI$!&ft>VQQ(;l7Z-T8!_5_VzQa`se6hnV5%@BPs}*>e!>tnd
1920 zO_y4o;PQuJQh75Yq2MZk-{Nq!0v~g@B?3R>a8&}o-Qng6{0@hU3w+Yyw7}0Y&M0Wi
1921 z7y2U>y_9=~7%HIX6I0s+e3(U950aWR0K$-D1B&=-0`VyU9}H021r$LfK2@}I6wBHy
1922 zvTkR+;Oqj5awKc>38_g7AdIS-WPQ?H(oW+m41YU>yMA%Pu-?uk(Y=%5$GMED+mo!4
1923 z=mS)=MUjvRxRR$CygcYo@(~7~aHyvk{INqtW!JOD>$ya17f@{Asbh~EjPi*UwmCil
1924 z#V|3|DPTy{$s$ov<Hgi=vE!LQdTJ5(`0Bt2Mf(=9lMEshf8wB+C8WX=MJklw{B$YK
1925 zPZx0>WDP$YXu4fM=|oKVQR}^jsXxdi`G&x*gWIJe(g#>3D(UAeLAWNV=Rbn)=P;ir
1926 zd-&R`$?=rFA(#!)zCn(~`Rl*}zJQ(^D*;7M_*qoF65ER3vCLOOb`sc0N)<~g@(p=s
1927 z@k{*fBCQAlf6d|I0-tucxdMOJ;i?4wp~Ec^_-77REATHJZk52Z=O>IY5pd6yNo5`*
1928 zX+;qD0*9*=c!9$$5%?m9s}i`%;pPgw(Ba|&FLF37aPP$-1*79G7JanR5@AIUuxyT?
1929 zd;yO#3Ul)40jd0y+qBDs)PB!c%o_nK7FdCnP-?d@*2t7f3nRfT;5RP}b4%^Vj0K^9
1930 z)fa^crIunW2nBqgfKX~5Vyw|eDxWSOm6})<GF9YLY}b_7by8s0Z32oZ(dNS??V37K
1931 zY}ak2?3y}J!mbY=D7NdiQg%(9D7NdiQg%(9D7NdiQg%(9C}G!!50tWN>O`?!w?)jV
1932 zuAFBFcR7~`H}7Te!w&Ub27lsEFERLvLw)T6E9+ZaLRJU+-S)u$lEVz{bEr=-_)UlU
1933 z0fRqxsFUoP9}ZkJ`B4Tx?NFa*@M{hw27kt(qGnh-*QzeD0Q(J@?p?veyFJgK_ztL|
1934 zqYjibCnE}!jO0D+_CQ5P45+A5J}b2(uxGm{b#tIpyD0TThY}Nu5wTwr<B2~4^)GA=
1935 zr)T>v*3aqLUaV))-tQjPvm?;6Q<QR+>J&>kr8@tK2lu&PkUNX@>@2otXR$pyi}mar
1936 z%bsGqS?bu!`+uvKy|~QW2Oqkxy6&QvR-K6IJ_eceM=Ux9SycNm$f7+OgDl$1G037l
1937 zzlB$$AY{tfWa2Fe!To%uodSrNzuf;US0o}E<R2|nEe@m}pA|@bdH?&l5|aAz{;1Sw
1938 zq#vgyy%IYiS}t)~p4u;!s~CxZBVeeBQ?J?tZ8W8Uovwki`=v6($TGF;gutN|&K9@8
1939 z27fx(1|;idTT8TX31z>;)9vd)SV%^#@dw@^iF#pGLmHeb(%^iIUkdECUBGXKdMNON
1940 zfu`GK9={L-neD|(;C6{5tAqY*FJ6MSzj_y!1*35!(6sYG1|{0yMoOaLwSiWhGPh+C
1941 zgGzLl2@90WS(%(biS9BHfs!aFlMblj?sUF-cbs!Q&wapjI=x>iF9m%}3K$yM)30e{
1942 zLyRwu$@nyHn8F!~Uo-CCg3VM~K(QZ`eq_H?#F$|jf)nc+2C0at!wiDEg8juXL<b_w
1943 zAcG?#V;H0&!xUx^oQ#`ckct>9%rMqyKF`~nFs<Nz8*G8n0*Ys%y;J+8@?Cb*unfV8
1944 zT@8a&#GqjY!R_WX(=bRy7Ji(?3V1L~Cly(P!-54TE3gqP6&a~8gWzNzVHl($BNb*4
1945 zoa{0TgH&G2VEmW^69q$oe-Q+$q<~^ZwDaHrsmLaucuQ>UA1vD16QLMgoY_c}irB$u
1946 z6WLQ4Lh)z`i$o~!x*$|01r&caybtho@mYhEir9<<j^((raJYducZ=Yrxp4H<{^?v1
1947 zp=jx;F++$*pq2&R>z4W-@0ZHmjKpduV5or~kJ*64C~BaA_my{WNjMo!85zQr8W6F)
1948 z_#V-Tfh9N)?zNay)<xnI_)~%VZ5Qw>jDjH_*)Ns<a&!VpoHcY(=?eDJ+a-KRmvP=D
1949 z;Hx<EBm1L^G^s2mlL-%bvJn?+0VSX~Dsc+j8aVBC0mZ(i6H*aFL!9`r*xb-bMT`$R
1950 z0mVtE*;jLI+LehD3LoSjIuK=?&dxX|aLTPwlJjkw_6B3u9vuMOPDM=(RJ1cdy_WW#
1951 z<IN-ba^C@|{Em^-X@NtXzOSg$r`VIkjUesO12Xn9@CNw`FBKB>4RS1n<)+kA6JI$Y
1952 zmFmE2lLG!SKm|9i;(&%#DzaX|MgoeGhE6J?9Owj;0Bq=_A`21d1QfS4bW+(K_;OM}
1953 zS(3miptCS~JC;er2gzpz{;3O!XZHVrE8;3J@R|K$0M`VNuhxX=g0%4o*Txh3rSj##
1954 z$CCnvT6p4BTPU?&%ytp&)BCUFN=WLbi=>`qEu`n<wbFa(IN_rG{TJr@FV~AG8&;ID
1955 zxL#zg3N@_W7Spd>plcTtHLKMye!K-2iyGg_J(F0B48ainBn*9`TZZtp==u}BCgD`v
1956 zE_^K-8^hOZtL|?J-5x)WZo#z@x&_xt=oVZnp<8gxX=S0PZn$5HnhU6?CO}0M04mxp
1957 zP_Nb;X4C2Y(FP4N+N4278#Tyivj!P$Sk{64!FrGsP+SI~BdQ5dQ9XbXEv|E6NI-EF
1958 zP({@ODyo!hdgTb5g3#;uW=@X7vA#BOJ0iT)`dZCwE4ZWyx{2W=mnE{*C)pfNI<rKT
1959 zoP2S@pyFKOK1IM#7<r^9j9kR@w>ZA2XgNdqr@)XI0skdH?M$-(X)UITo|2fsr<wD)
1960 zoPap7V(~p{VYJ29@yaF(Y^6H(X+BQ;{fD3XcJt2UEf*EVmMBw+k&KeS2a7EtL<d=k
1961 zIqEl+bdVXejLkcaHZM9M1ft~yNdHE)6xwJHWkYcNg$Z-1WDoy@FUo3MlIYbW!wgY5
1962 zB`g!w$5<xHSJGTjPFUgS0ekdYWU;8g^U+58HHBU6LN4JvWhI?Q7{@U{nOA}5I9y!l
1963 zqNO~!h5Vv`!e-NfQ3k0?BjE;D@kQXO1YYfM(twCi(;2#m%Mwd*f-kM*lA05^&*7>B
1964 z9&os#=7#y&y&)QbA9J`Wfgg9cF=f4*X<$DAh3)+ID+>u1*mJnJz!My9uE1j3u$`|D
1965 z(FvSzxVXR@98L?|=x|j6w>aEffwwwbT;MK;D>4#aQurx3^MR2B6cw=^3s}cg)^1Xh
1966 zwm~SMG<kjlOG~9zrXAeW5SK)=m*M-lgfl+C;DaGD27}@xL!af698}=RF^dGQR^Yh9
1967 zX@TcBTrG<Uijxd|flJs>z<&);odQl_N!Bz{o5fhzP(W$2v<;=vr-K$!0(yb0Z30R&
1968 zBrA17YSKcf6`sX@EfBw1z`qYr9Ri9V62JKbUk{3t3<-5iwF#&LRksT$%8{(L5~^+w
1969 z<TCIBE`P}-yh6bL2vF@JR#Yt!$Yg|`3%HU3J|Ccp_NG<bg=IlkIt09yQKd&P!B;yR
1970 zqk#Vspi<m$P`tpGW^qIsr|x|C;0dW+#MlZoYVUaT$bu7sT<k8E*?Xn@f)j#V$``d7
1971 z_3XXUb&P4_(zX;R!obTBeah5|6H!jWy&4}TO_U9&vAF(=TZK+<I(R~Ap6j6Ny&&oP
1972 z9O(noxZVp=?04SYqa`cC{S}pOaW*=B@PyPFT$8L%X2A(TidoU5)u%}K4rU+XlH!)Y
1973 zA7C6FojRkW^1%?H)6qgAEYCDBu7K|fQ0)SWq|%-%vR)T3rUX10pgIK%%PM|Y^$BM9
1974 zI+xT*fq&09dOl1^g?>bVK13++HpUr3d)fV!7QPjz)*;}_0cyK||HUZVbE!!KxUF)6
1975 zEhOT<7syHp_(Fi%CZGr;@u?G1bK<wXy7<i^{#SwcP60(AiQim8d{OlJG0XTxAS)>{
1976 zCa_TvDFv(vQ0>bYtP4;{0bOs}qrKU|)OT}9gDCK$j5C8Ml_x@k0#D|RZOPG=77j8a
1977 z{9M3C0@QW^A7hjqZK+8EB}QAsKM=@D3Hbg1wM{?~Xh&OWPJGd57mMF4;{PlV-zlI7
1978 zw4*IGC%$O3-^eoF8puit*QXpxz@G)E_MbEOT!2an=$b1U?KltAbS`PM1+H?qxWG#s
1979 zP7B=ZaB+cK9Ij|XJD;yD;}YI0ps?e1Q$UeaVmFXv0h>dO34Eu+#Rb00;k3Z-bGW#`
1980 z?{~N&<#+J4UM``QfYJ<<AK|O_Iw}FB5l{&z?Um?a9}DPrf}#^v>P(^V8kK<8@HOk)
1981 zLKrQlGJ^K+S1>G`B~%jjFq`0{oW;OWE+?uxm9AQ>t1desC~0A$8j(xFEoFj%IxfjM
1982 z1#We?xWKYJgRV;8lOZ~RA8|M>@JAi4iou|eQ>k|`#+>&{<-LrAr34gNhAxo8z#Uv3
1983 zF6Mj8p%@B^H!>ux#?+SJ8Us&o`Ef4ES^|H`;o<`Sjl&gr`DwoP?GTN?KXkabz&~}k
1984 zxdQ*v;i?4wwZknDSoZYLw^ra69o;H{yLkP>n)1XXscd5;m{$qB-Qj8lreDLL59pQ%
1985 zoOZY>fx8`UuD}_GiwoTAaAO)zZcMSh3AiU_)xh(m0*WNNzS+y}uMEV(fH5WDg8^!r
1986 zfMHq1`?z9Rn?;s%3(tBB7?xFh!zi+zWmR#*D4>`UOS6DsS#2^igHDR9G<V2M8>!qK
1987 z^fD>iagi2Nn*$jPe3PmFDd6f7a2<~r?xY12fiWeAA%VODEZ|##prWNSN-{&`)b;aM
1988 zEXLoNGv{BlVBzw`MO_vBzQbZm9jiRY*KP_FP6{Y@E#*k1-K8!F?qXa=l0gp`n9NeH
1989 z52S4sP^4X@4nW?FCFQD8Cu(M>+SxOfU9e=LT6XE|MX}j6&%ILlKZaH96-#1jc4bkI
1990 z;w-l|kl!Ytv{MdUb86uUsY|=nuc2Myk9KViH@PTidb5C{LTGUjlxQ*8YQ?LPU`4l;
1991 zuT3|W64h{+HM^fn3dsUL<#4qEpLRGc@V`4;?O5_3Vj4sm0Y4U?ItBb&M%hRsweL7W
1992 z0j0^(AxSzVEn&YQ;Fkkg+XR$m>=s07(n5)2t*Ewm19xjwF~UV{@t54T@MAre*3JZK
1993 zB?WW}6wT{%Og)}A(llrSZ*aI;fs+oW1<pEL(V&U^N~Xb}3AiFabqd(XC_5HXOF2RT
1994 zrODERR@`Vx8eJR6+9sehV+T!Y(n5(ri)u>)6jiL$pvf(&@MF-VHM!3MN<gPT(Vz`;
1995 zC+_5u22EhOdj&2o@LL>RmB2?GE-vuH4yOf{J1xko68Nm6iwpcqhtmST<Zx9{50*a2
1996 z?IavSKw&FAxbI=1e;o)feoRYfe#|s5>oW|BaG;_p3D*yp)GW<Xk$&P%MnDl+LVC%~
1997 z@atLbyPZ~16{J(rDpq}I<<|k%W&x!yp1QO6D3E^Ki9T{OOHLy2C;1w1wE~}VI4$tM
1998 zJ6zGsR(x$4ml!|+9}ZC4KgHlL97@2m0V*k=v{!oMi(5=di;o1dwh1UL+i5K|X`#fl
1999 z9%31CJBwiz&~>O?1c}P<2Ww~dw^-2TVnMeT3%cEju+VbWXlKy7BA<PTFTKN&2<Vh9
2000 zI(ON_)Q23GfWkFV-6MCZqUo0%wSZ!U5OuT@=a}m`F3ArC{)5BC1-@y#l|a5J@M?#P
2001 z3!HE`EpVg575S^^@tdF*9Ri9-jOEQNVLg{X2`Iu#L=KVtpMmU@fRh739Ri9V>zPq|
2002 zO<{&v0b}wq23I(g=(*ORqJl(#kYY*N5v9S;QJYVQW>=IZ$uy~;sSW|R2B?&PU5qL{
2003 zg?I4Po`A7Kz+C|<C1C$~WexMye8AWt;OJ{)OqF6RzNb9IV()V;3V8o{TP$Wwm0~Pz
2004 z@hFRZn`=?Px1YB~8ANtSlbsNFCSSx1iwi7gSTs9@SIQ~|7IR570$=ZNae;4exG`nP
2005 z^u($m;7Vr07F$4(RN9%UnBgkND4+<y`YB*oR<WTIEMqN~)JK8kewpkg@U0;_27@BO
2006 zkOXV=QNR>mLLUVbNu~QJvNkzJ0Yw1%C}3DtaUXZEj2<qjj{@f%E-vt>!xfF=A-;BB
2007 zh(_S|I9y!d;|@2bthX@@>?PpC0V*Y+NGffwL(K3N$0(o(fV~6^%PO{)$a+&CYqNkN
2008 z04G5LhGi8WA&IO%4P><mC<0<?tAJry#YaddS;hyrq;VAZlMWXb_)`v7Wc!nR?J+K4
2009 zdjbD4K&1o}Nu_OniW$DlCFv#b_Z%)R@b?|ANUu|T?VDUeF9H8&fJzA{l1l4!h8fOs
2010 zNqPzVTZfAa{F1{J>2-#${VSKyOTgy>R7yaRR9Y`2FU)6La6X0y@feoJLZEA0;JG0>
2011 zZp#&Xjeeh&KF~|R838IKphzmMR~0iX=926suslLSdI@}8h|ad|{)()nff5}8%2O$b
2012 zg#wDC(t0IW#@bMO0^jCvae=ovT+uj+tTv{By#(wGP$>aL()smjc8mgw0K^;t!?KEF
2013 zj_9>1khNJr5rCK@U|3dh%-O**dbp%<6nKxr#RcB$a7FeKS%XXidkJ`FfJzA{l1kg_
2014 z5Hs8tYER&|Ib2-ew>w;sUMKn52SPLgf6C$F0)N`!#+3Cq)1Z$6{#AfV2`G|E_wf`n
2015 zd^yyfz~6VcxWGSfxFWqo*55G=^b+vf0V*Y+NGh$@8D=;eYER(*aJaa@|LJf=dWo!a
2016 zOar|Hd@(?!1Qbc<*DLg-nSdeyb4b9jtl~L@&93>3<C6Sd;JFSL7kHk-74=bMO=BAL
2017 zQNYRol@d@SmF}a+n&cP-6ana?fMHq1eXL>`i@7v0nqfKKrx-2p4Iw%goh>A?YMBOo
2018 z6mVsLN(m^EO7~G@UF8@B6ana?fMHq1eH1;}mtelV@=zwe3e<k6j{;9}xVZv1Ib5y4
2019 z%?>wLV0loO<OwXBc4}AP9>-fNaK_>03f${(ae;>&P78e4;c6KyD&*M%jEjJxV(1a)
2020 zR_3$gA~k6ngaY;z5K2uH0bx{u>5Qo45(gjxiurI%A}xvqfGU<<bXImT%Uthdiy+^j
2021 zM3CH>lsJO9nyGK%vYZ~mz#Dc_mj<RF`-cS9hL*)w&}C_CON348qC|u(s*tqCQi=+m
2022 z4aS89u3##1If17*++2ah{Gh86c!r}}BJe#9S1a&-hg%}>L5Hgn_+E#bEASDAiwk_8
2023 z!xe{0zBZdnxT}D|Ryt-dy^_c8u^|*t+QlOT0)}Oc9W$h51RDXRuQ>V@Ff6Nh|8yZM
2024 zwj}6KQb4g$i6`=;Hy1NNS#M!m;Uq~wkpl&|w19p<)hWWFr3fV9B6L;2Ry50w@}>83
2025 zNfAxpbBx22CP!mZc`-!DU{Hv#k2412Ea0;Ns#8FbRC?$|)<*-zlz=}CQ0)SSWfc$o
2026 zUo*qs1&qn>GWaWpV#pOS3y$NGOe63jhpQ6!GKbSnh=pqTT78H{;H<+{2|Vm@T433z
2027 z&}<(|elp;zJt2G_3*r8mVcEo$dhnu!X?!l>e<Etcp#*#+Ky`ke!EZWLRL`hvYF~tl
2028 zB*F>&SAnRcfYJ(<BLSsB;*=h~>^KFKPJ>fGv1!Sy-1(H1rm0DRMGY8Cv^cN)`&q@4
2029 zPE`RP4^Zs_O8+sb&eNdmgR#a6DBTBRbU5O?;>_fdTwLJQ4i^{rW{1-P_c&Z!V0reR
2030 z<VD+*6#R3JPYdjMmKuC<fwjYFfiHBpcvSwDMG1r2#pOXRzry8zm;UE0=kmq29r;df
2031 z`R3iI{MSnVm04Eq54ijhm-3|zQTg&M29sx7zBrfiy$Dfyc_Cij4nNBD56`ju(O1Ny
2032 z?}y9F;qtO}^fmDR+wHC5eyrhg9hdU5cvQcr9ps&Dc^mt`OaB{gU(L1loyeuU(jApQ
2033 zVGOzjjE~aGPrS&tX3JL<j-~&(n3W)5LGE=I^L&iTf35Vggvr^_Pr1FuG2}<-C2UEE
2034 z#?IJ$<l(=leo=Y}xtjST#>s1AQT|)US<LNR=D2(vm#4V=doH8=8@PXR7$>VnlJT;<
2035 zJ<4^7=dvt|eV^y+(f<73ZckO`_6_FKJ5lCGY`IGy{2)_iWLQ-XW%HTpx;2eU^Y{TM
2036 zTk9Jdt=>7>KhU!jKdx0xwO#4lE>+#LZwT^iiC>U2SN7n?p6Dmj!xbOb@QYe$Vqj=^
2037 zAg`+F2Y^*|9=|uQs_EB&aV^`E&Zkv%W|!YPLO*=I3qLLu)Ihs4m$Q6+dSnE@8*lgo
2038 zzM~t&Xd^w?-wg$_5Q{(6rY$Siu+tCP<0rO2n%Ozp2j=upUj|}rwSTBLD{y+}&XLR>
2039 zsnM?z3rxS5#|-#QbpcsYbeR7)>+``!jwF+9RapWxrB*RwfvLGa>~sNQ5uge9FZ`*p
2040 z1Zqm97*S<v?oV`5EW@QRf4(eXi1W<9*woygDF0eq`t2*PWTpLw%Myn8VMfTU45zqN
2041 zbbCR^A9Tws{HMzjs3~=t5lfh{960K`@XsY8eCWQ4HW$MG@`MCxO1(^-!bj|AYgUH9
2042 zRNjvNuY~lkos=N7s^w#+AyZRI^p|#|+>Psh2=Sj}{*%nVgZW8+;t~BBt?mXuHWhiQ
2043 zB4ID_Il>NG3)&Zc>HmGW9_HV{{5zOm-ZdiqC*yyV|INUWT}eOsJTWc7r76?}wg~=G
2044 zTj9?ePzm#&X8zODES2mYg-5o3Qob$1FRS4xJ`4H9V&Sx<@Co*v5&jQcmoS$;aGj-?
2045 zXp7))RR5E>Li&sSPci=~=3hfb3w;tHn7~KyKg>UFZGzBh+*(tpt3|M_nz3Tg6raT3
2046 zFn{g3gu&OYGllw&44AD3<HuEX3ILIK(y`<Y)bL5#BEnw8|5cDp#ed$QgKvjr{3H3l
2047 z4Qd){;n&PB$E>f`J{<^9|Ajx!{P91s{eJ{+d5C{5^Ur1eGb9`zqM?uI6Sr0MYn0*k
2048 zU*5dKTzPr3B@lXBbNqsT4j01ws%?iQZL`IL+`g?9^ZzF<g!vzA-(g4}Y_}Yur>!}D
2049 zsS`8lBKAAQ{0}q#p+rDwfJjx12S2r6TS%sa|N01?Xz3&6ROYu>_xFEt`$vV4FGZ^A
2050 z!ZG;M9hPAx1=!Fh%74We{G+EV({zp_A|lFv-5C52kYnR>Br*U|emWE)T-1IO$uaTy
2051 zx5xr6{8G~HQ(((s|GxB!Eh~G%*kanQG59C-SgG>JpGb+eH60hkcZ7z@Tl+0#UxXo2
2052 zHM&PaoDs7jZz*@M{VxS}BmT?0k@bt>bE)<pdBF1DBk3O_wYdL`E?IccZdF;L=$eOU
2053 zFZ-nMMGu<D{-+Q>PCZ<f2%`+_VO2g|5?_w}M=AOV*jJRoYjv_D9@eQSML$W&I<G<>
2054 z4?8JYze8yBYO<1bxez}^$$DFepQ>aXEyPb#vOX5#<5=$!VU&SAe8-clXW@&Uf>R`S
2055 zgi%aiIR<{Fl657_<f&Oo){8>?Y$fYJA%2dM_+E&IH%i<NUGUUACGj|fhCMG(5@!qX
2056 zw3{#fcq$SEn8Z_(mnh`%)J27efL<~Yg_k{5Rfq`aFBt>Bun14HZJc_JqmH{w+sHCC
2057 zCHP_5MRr=MnZU<jheT?JB~I9a<~7kDy2K)Gv1rpH!k=RNV#ZV4B>XwXOB}tK@l^{G
2058 zfRy@2^H-@xl+>=`b|s#)8T>T$=|sX%^7d2F@=>Z^dklTC{~Q6H^f`KQ0+9PW4AAHw
2059 z!T$y0RaL?f1NtKVlb+|=cNjdIO`SIQVt;-Kc#>Zgk>i0eri$kUy#ZUQUssKRUpWST
2060 zwUIwf9a@us21*?=f0bG{27Mdwr01cl5{B{`roWx#+*EJzeEX&DVEW|M7XLp`r_WxL
2061 zrSv~M2L26W;2#FQoZ<<8#2?-Vd<;9&bM*;xMJUGdhmRY2tcI<Yp2evz8GNyy(DhRK
2062 z{~hQR#w!}HerDtp$E9B~eKa2a&d?XfrRik~y`7>?@_h=b=5vX`b0t))VER*+B@9+F
2063 zlN%X-Xr;x=HiKS9H}aQRyhI{;y;^K&1o59EOs}rB^tUtqjlfqi94;O)_~N+wu`%R-
2064 zjpbLdKC@WZ-!cBo<q3nC&G;XWA&2fmsb9nFx2T%W@5i8zdrHL-{~zZ0%j9Yf@FeHl
2065 z(u6@B<O`P>yimFF2BxoCo-jy?kMwB(etKvf8E4U|i|G$B{T#**7<}=%Ji_#+uS^(9
2066 ziktMg*WfK2{`=4v_&*;5|G6>n-x&k{Z)4ymqJw0&M5JFA8GKkn3)2fzrTlH(82H=9
2067 zz|$LC)NU=uA4F2~IWPwOu`%#ZupAZ9|MQHmx+Y=de#eSer^k@<t1<Au8v{?T^^~&1
2068 zQiGqO;+NTWS9819j6qLtDv>`&_cNVi(BA<(`RAGT9Y(Um)dOSDKQspZkumU}0ltcL
2069 z4i|rG=n>!8&NAPBGKQSzfS+DAPaS1FMb;l!&LOss%!>&)2$+s_LH4mQyZOupp8P~D
2070 zNtimV>-4#T@#j_~O#MFdSE&_@-*LIc?`8a2p|7=gs9`?0GCt06`wfi0!{E6RDh`O8
2071 zOA`hwap3hLXOYFrH+H>~@d?&b&g~u>L;e><4#&fGZu^^K(EpO@cW|7)jp@%Z{tU-w
2072 z(ew9X$cbZP5QkqS-nN4!*kTs&rTo0s;1Rd06NXUY?JbOtX3f?yzKX|1#(g{EpWyM`
2073 z$*uPZJ=<*_<6p=41ounq`6h#BqEK;?=?~Q;4EEpo+Fy@B|6Sn84$<}H=Pc(m`_Dv{
2074 z^8(}JtdIEBI803P+fy@ayC357%886W$LsrLEN2np&+s@dWjy_QT`BvoXZqnQto%or
2075 zew*M~PuW-8#rPd;&%;cAcntY(WBMwV-@x=A7=!*(W8l9r2L252RV*`Hyf_BEhQUo7
2076 zh|Ht;j6cJ1N!Ia84L&T{!Z(PV$au9f{#0bXY#l?+9YW9JC3lhs1s~DpPsWgQoaw8s
2077 zOc(`a9RCt{il0$G{G7<Y%F<_Tx75?XS1}weo@M$StdHpVAB;c5{grrLfpZ<Q^O=aB
2078 zS26w^&-d4JBP$KQ_<Z9Arr*KxWu7)MKFRU_YL?S(@L|m@ybE|*?|#|7!yw=u_A}VM
2079 zJU84wRNbuxve{w3H#?$+MhDesF5Q<=x!wK4em?6DA-(CF)S<y}@-e6G$nLBjPLJfP
2080 zYt`^bwhu|mjPm_tTSF?<<*(~#sZTYww)lSa%9YoyP~9W>Tz<5-7ft#8#`-qDsj)rf
2081 z`>H21lIiQuA#>~J2mS7W><|)}B~ZTKllA)svOCiQeosC-lJnD}cPZ#HJdnv}daAEo
2082 zwrm+Bmmu;fF>4d7K9Z&*`;<-0_KXe=?gLAx=2JemfRs9$CHp|L?%g>uRDXVOlmPTO
2083 zpY6^LsKNfek#rs@V<H<K&1LfW?C8LNYH9WBlO5G7YnQD;kJ3H<V0swF?o+vax$gA9
2084 z013&bbGuRO&WsFY2K@fsba#fN<VOblVHyKJY{(VYUVlAd+UlAc{DzjbFrT%hzy<2}
2085 zD1U8NOI>qgJ*Yxga(RrI^4B-DuBmJCTi2~?Z%Fy6x;0G=ByOO8XSd&-8#Pvgr81dB
2086 zVtrHNntFeE_44X#;3wU?ed#(mjBm!>^v{~cM+5ns%J%r#;mpuokeL}78Or+LG*&8<
2087 zhY`Wh4-G57G1crlZ%8%QlP{#wI|nj~Qr{#NdLwP!J-n|_MjtGWynb$1cCSB@hvATT
2088 zC&GNTr;spn7lzkrslYVcAGz*lOp?7PJDBbtBG;$kRJ|DcT*M6E_Tm5jP*!D!^Zi2+
2089 zLAmZ-nI0cR1{fX4j3{eRGY-%(zl$uU2H_HgDh`j}F^1kkTyCfob|^iR%?)HS5dp>+
2090 zgPCk^PdZ{I-%saq88qIT?jI;@VQ(6Sp~0j+;X#K?I+sy{nL+q+Az?2(cPOe}eq?AM
2091 zGZZ0&9^Hi~L>50gM1jQGwS-x%-Oy^fmu77~)Poh(D|znuqeJ9{%GfeIbChM@*Pj`P
2092 zj0YLJP#N}g<5ZZK{SozZcn~7O0bj`XBgE0v%|^P0z*Fd=gOO2zlcY!b3RUPWHL4sN
2093 zB9s`;LX7YCAuicDfiMt^Up^NMpP2xWafY6`tiKC=!>k&}`^JAT^;#jR2QH7`)nn~S
2094 zK8o1HlgUi)-hN^-;m=HMn$f$}&WvvZV8%?Cfl-R(;Xp#eqy|eEZ71B&&yMC5CTtGe
2095 zJ&01^-IE^3DY$@-#VM@AD4ubNx|DGNp3uH;haclq7`CocX5J&lu<}OlTnSIc`p{z|
2096 zJ<VMj?Lw<VG<DL(hn(V&L;=uD9+DfxMhZa7y9Y4k5d1Oi_L$&@2nT$2pXp$sjeB#M
2097 z%<jVW!nQR5gJTlR8}v0|*z0f&&j_(<VF4zZk*)Lnv{;EK@_h=1{t#B+z<Yf1C_D&d
2098 zuDIoBkh+K#3)RdGXGhXK{oUj&Rye#U+;pJ3wVYY?{K0Hb2Ej8LI09jIu~)stB*R!x
2099 zvLg{4u%>3Ck;&h<$8Y29MLi7#_7><WCSxIUc!0X$>-h|}K?4ImO?A7Fj7GZLZT*~#
2100 z*xNsn%Tq+7CC|h(<8RRx?i|I)V^ILdFjm#U;XM4p1X`F~_3j;ky$g8)OK@W_s_$c6
2101 z<fUJ@2h(=O(fTPHr-Icp2&x7!i;<c4c4G%)_Gb%+OFUe;h0t}<Y$c3a6uR%;ZWA4Q
2102 RC~&S^73oPH3wvb1{udehT~z=8
2103 
2104 literal 0
2105 HcmV?d00001
2106 
2107 diff --git a/src/syscalls.c b/src/syscalls.c
2108 index fbb8604..b07d135 100644
2109 --- a/src/syscalls.c
2110 +++ b/src/syscalls.c
2111 @@ -96,3 +96,8 @@ int reservation_destroy(unsigned int reservation_id, int cpu)
2112  {
2113  	return syscall(__NR_reservation_destroy, reservation_id, cpu);
2114  }
2115 +
2116 +int set_mc2_task_param(pid_t pid, struct mc2_task *param)
2117 +{
2118 +	return syscall(__NR_set_mc2_task_param, pid, param);
2119 +}
2120 \ No newline at end of file
2121 -- 
2122 1.9.1
2123 
2124 
2125 From 67b3a5139287b153a4bd07899f3a17ea07810e98 Mon Sep 17 00:00:00 2001
2126 From: Namhoon Kim <namhoonk@cs.unc.edu>
2127 Date: Thu, 4 Jun 2015 21:03:19 +0000
2128 Subject: [PATCH 7/7] MC2 for imx6
2129 
2130 ---
2131  Makefile               |  30 ++-
2132  bin/mc2pollute.c       | 400 +++++++++++++++++++++++++++++++
2133  bin/mc2spin.c          | 119 ++++++----
2134  bin/mc2spin_td.c       | 585 +++++++++++++++++++++++++++++++++++++++++++++
2135  bin/mc2syn.c           | 575 +++++++++++++++++++++++++++++++++++++++++++++
2136  bin/mc2sys.c           | 557 +++++++++++++++++++++++++++++++++++++++++++
2137  bin/mc2thrash.c        | 272 +++++++++++++++++++++
2138  bin/mc2thrash2.c       | 626 +++++++++++++++++++++++++++++++++++++++++++++++++
2139  bin/memthrash.c        |  62 +++++
2140  bin/portab.h           |  41 ++++
2141  bin/resspin.c          | 576 +++++++++++++++++++++++++++++++++++++++++++++
2142  bin/rtspin.c           |   4 +-
2143  include/cache_common.h | 213 +++++++++++++++++
2144  include/litmus.h       |   2 +
2145  mc2spin                | Bin 102692 -> 0 bytes
2146  src/syscalls.c         |   7 +-
2147  16 files changed, 4020 insertions(+), 49 deletions(-)
2148  create mode 100644 bin/mc2pollute.c
2149  create mode 100644 bin/mc2spin_td.c
2150  create mode 100644 bin/mc2syn.c
2151  create mode 100644 bin/mc2sys.c
2152  create mode 100644 bin/mc2thrash.c
2153  create mode 100644 bin/mc2thrash2.c
2154  create mode 100644 bin/memthrash.c
2155  create mode 100644 bin/portab.h
2156  create mode 100644 bin/resspin.c
2157  create mode 100644 include/cache_common.h
2158  delete mode 100755 mc2spin
2159 
2160 diff --git a/Makefile b/Makefile
2161 index 70e79d4..0dfc121 100644
2162 --- a/Makefile
2163 +++ b/Makefile
2164 @@ -19,7 +19,7 @@ LITMUS_KERNEL ?= ../litmus-rt
2165  # Internal configuration.
2166  
2167  # compiler flags
2168 -flags-debug    = -O2 -Wall -Werror -g -Wdeclaration-after-statement
2169 +flags-debug    = -O0 -Wall -g -Wdeclaration-after-statement
2170  flags-api      = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE
2171  
2172  # architecture-specific flags
2173 @@ -73,7 +73,8 @@ AR  := ${CROSS_COMPILE}${AR}
2174  
2175  all     = lib ${rt-apps}
2176  rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
2177 -	  base_mt_task uncache runtests resctrl mc2spin
2178 +	  base_mt_task uncache runtests resctrl mc2spin mc2pollute  \
2179 +	  mc2syn memthrash mc2sys mc2thrash mc2thrash0 mc2thrash1 mc2thrash2
2180  
2181  .PHONY: all lib clean dump-config TAGS tags cscope help doc
2182  
2183 @@ -238,8 +239,31 @@ lib-measure_syscall = -lm
2184  obj-resctrl = resctrl.o
2185  
2186  obj-mc2spin = mc2spin.o common.o
2187 -lib-mc2spin = -lrt
2188 +lib-mc2spin = -lrt -static
2189  
2190 +obj-mc2pollute = mc2pollute.o common.o
2191 +lib-mc2pollute = -lrt -static
2192 +
2193 +obj-mc2sys = mc2sys.o common.o
2194 +lib-mc2sys = -lrt -static
2195 +
2196 +obj-mc2syn = mc2syn.o common.o
2197 +lib-mc2syn = -lrt -static
2198 +
2199 +obj-mc2thrash = mc2thrash.o common.o
2200 +lib-mc2thrash = -lrt -static
2201 +
2202 +obj-mc2thrash0 = mc2thrash.o common.o
2203 +lib-mc2thrash0 = -lrt -static
2204 +
2205 +obj-mc2thrash1 = mc2thrash.o common.o
2206 +lib-mc2thrash1 = -lrt -static
2207 +
2208 +obj-mc2thrash2 = mc2thrash.o common.o
2209 +lib-mc2thrash2 = -lrt -static
2210 +
2211 +obj-memthrash = memthrash.o
2212 +lib-memthrash = -lrt
2213  # ##############################################################################
2214  # Build everything that depends on liblitmus.
2215  
2216 diff --git a/bin/mc2pollute.c b/bin/mc2pollute.c
2217 new file mode 100644
2218 index 0000000..63d3503
2219 --- /dev/null
2220 +++ b/bin/mc2pollute.c
2221 @@ -0,0 +1,400 @@
2222 +#include <sys/time.h>
2223 +#include <sys/mman.h>
2224 +
2225 +#include <stdio.h>
2226 +#include <stdlib.h>
2227 +#include <unistd.h>
2228 +#include <time.h>
2229 +#include <string.h>
2230 +#include <assert.h>
2231 +#include <limits.h>
2232 +#include <fcntl.h>
2233 +
2234 +#include "litmus.h"
2235 +#include "common.h"
2236 +
2237 +#define PAGE_SIZE (4096)
2238 +#define CACHELINE_SIZE 32
2239 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
2240 +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
2241 +#define INTS_IN_1KB	(1024 / sizeof(int))
2242 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
2243 +
2244 +typedef struct cacheline
2245 +{
2246 +        int line[INTS_IN_CACHELINE];
2247 +} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
2248 +
2249 +static int loops = 10;
2250 +static cacheline_t* arena = NULL;
2251 +
2252 +struct timeval t1,t2;
2253 +
2254 +inline unsigned long get_cyclecount (void)
2255 +{
2256 +	unsigned long value;
2257 +	// Read CCNT Register
2258 +	asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
2259 +	return value;
2260 +}
2261 +
2262 +#if 1
2263 +#define UNCACHE_DEV "/dev/litmus/uncache"
2264 +
2265 +static cacheline_t* alloc_arena(size_t size, int use_huge_pages, int use_uncache_pages)
2266 +{
2267 +    int flags = MAP_PRIVATE | MAP_POPULATE;
2268 +    cacheline_t* arena = NULL;
2269 +    int fd;
2270 +
2271 +    if(use_huge_pages)
2272 +        flags |= MAP_HUGETLB;
2273 +
2274 +	if(use_uncache_pages) {
2275 +			fd = open(UNCACHE_DEV, O_RDWR|O_SYNC);
2276 +			if (fd == -1)
2277 +					bail_out("Failed to open uncache device. Are you running the LITMUS^RT kernel?");
2278 +	}
2279 +	else {
2280 +			fd = -1;
2281 +			flags |= MAP_ANONYMOUS;
2282 +	}
2283 +
2284 +    arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0);
2285 +	
2286 +    if(use_uncache_pages)
2287 +		close(fd);
2288 +
2289 +    assert(arena);
2290 +
2291 +        return arena;
2292 +}
2293 +#else
2294 +static cacheline_t* alloc_arena(size_t size)
2295 +{
2296 +    int flags = MAP_PRIVATE | MAP_POPULATE | MAP_ANONYMOUS;
2297 +    cacheline_t* arena = NULL;
2298 +    
2299 +    arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, -1, 0);
2300 +	
2301 +    assert(arena);
2302 +    return arena;
2303 +}
2304 +#endif
2305 +
2306 +static void dealloc_arena(cacheline_t* arena, size_t size)
2307 +{
2308 +		int ret = munmap((void*)arena, size);
2309 +        if(ret != 0)
2310 +                bail_out("munmap() error");
2311 +}
2312 +
2313 +static int randrange(int min, int max)
2314 +{
2315 +        /* generate a random number on the range [min, max) w/o skew */
2316 +        int limit = max - min;
2317 +        int devisor = RAND_MAX/limit;
2318 +        int retval;
2319 +
2320 +        do {
2321 +                retval = rand() / devisor;
2322 +        } while(retval == limit);
2323 +        retval += min;
2324 +
2325 +        return retval;
2326 +}
2327 +
2328 +static void init_arena(cacheline_t* arena, size_t size)
2329 +{
2330 +    int i;
2331 +        size_t num_arena_elem = size / sizeof(cacheline_t);
2332 +
2333 +        /* Generate a cycle among the cache lines using Sattolo's algorithm.
2334 +           Every int in the cache line points to the same cache line.
2335 +           Note: Sequential walk doesn't care about these values. */
2336 +        for (i = 0; i < num_arena_elem; i++) {
2337 +                int j;
2338 +                for(j = 0; j < INTS_IN_CACHELINE; ++j)
2339 +                        arena[i].line[j] = i;
2340 +        }
2341 +        while(1 < i--) {
2342 +                int j = randrange(0, i);
2343 +                cacheline_t temp = arena[j];
2344 +                arena[j] = arena[i];
2345 +                arena[i] = temp;
2346 +        }
2347 +}
2348 +
2349 +/* Random walk around the arena in cacheline-sized chunks.
2350 +   Cacheline-sized chucks ensures the same utilization of each
2351 +   hit line as sequential read. (Otherwise, our utilization
2352 +   would only be 1/INTS_IN_CACHELINE.) */
2353 +static int random_walk(cacheline_t *mem, int wss, int write_cycle)
2354 +{
2355 +	/* a random cycle among the cache lines was set up by init_arena(). */
2356 +	int sum, i, next;
2357 +
2358 +	int numlines = wss * CACHELINES_IN_1KB;
2359 +
2360 +	sum = 0;
2361 +
2362 +	/* contents of arena is structured s.t. offsets are all
2363 +	   w.r.t. to start of arena, so compute the initial offset */
2364 +	next = mem - arena;
2365 +
2366 +	if (write_cycle == 0) {
2367 +		for (i = 0; i < numlines; i++) {
2368 +			/* every element in the cacheline has the same value */
2369 +			next = arena[next].line[0];
2370 +			sum += next;
2371 +		}
2372 +	}
2373 +	
2374 +	else {
2375 +		int w, which_line;
2376 +		for (i = 0, w = 0; i < numlines; i++) {
2377 +			which_line = next;
2378 +			next = arena[next].line[0];
2379 +			if((w % write_cycle) != (write_cycle - 1)) {
2380 +				sum += next;
2381 +			}
2382 +			else {
2383 +				((volatile cacheline_t*)arena)[which_line].line[0] = next;
2384 +			}
2385 +		}
2386 +	}
2387 +	return sum;
2388 +}
2389 +
2390 +static cacheline_t* random_start(int wss)
2391 +{
2392 +	return arena + randrange(0, ((wss * 1024)/sizeof(cacheline_t)));
2393 +}
2394 +
2395 +static volatile int dont_optimize_me = 0;
2396 +
2397 +static void usage(char *error) {
2398 +	fprintf(stderr, "Error: %s\n", error);
2399 +	fprintf(stderr,
2400 +		"Usage:\n"
2401 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
2402 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
2403 +		"	rt_spin -l\n"
2404 +		"\n"
2405 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
2406 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-m CRITICALITY LEVEL]\n"
2407 +		"              [-k WSS] [-l LOOPS] [-b BUDGET]\n"
2408 +		"\n"
2409 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n");
2410 +	exit(EXIT_FAILURE);
2411 +}
2412 +
2413 +static int loop_once(int wss)
2414 +{
2415 +	cacheline_t *mem;
2416 +	int temp;
2417 +	
2418 +	mem = random_start(wss);
2419 +	temp = random_walk(mem, wss, 0);
2420 +    
2421 +	//mem = sequential_start(wss);
2422 +	//temp = sequential_walk(mem, wss, 0);
2423 +	dont_optimize_me = temp;
2424 +	
2425 +	return dont_optimize_me;
2426 +}
2427 +
2428 +static int job(int wss, double exec_time, double program_end)
2429 +{
2430 +	if (wctime() > program_end)
2431 +		return 0;
2432 +	else {
2433 +		//register unsigned long t;
2434 +		register unsigned int iter = 0;
2435 +		//t = get_cyclecount();
2436 +		//gettimeofday(&t1, NULL);
2437 +		while(iter++ < loops) {
2438 +			loop_once(wss);
2439 +		}
2440 +		//gettimeofday(&t2, NULL);
2441 +		//t = get_cyclecount() - t;
2442 +		//printf("%ld cycles\n", t);
2443 +		//printf("%ld us\n", ((t2.tv_sec * 1000000 + t2.tv_usec) - (t1.tv_sec * 1000000 + t1.tv_usec)));
2444 +   		sleep_next_period(); 
2445 +    	return 1;
2446 +	}
2447 +}
2448 +
2449 +#define OPTSTR "p:wl:m:i:b:k:"
2450 +int main(int argc, char** argv)
2451 +{
2452 +	int ret, i;
2453 +	lt_t wcet, period, budget;
2454 +	double wcet_ms, period_ms, budget_ms;
2455 +	unsigned int priority = LITMUS_NO_PRIORITY;
2456 +	int migrate = 0;
2457 +	int cluster = 0;
2458 +	int opt;
2459 +	int wait = 0;
2460 +	double duration = 0, start = 0;
2461 +	struct rt_task param;
2462 +	struct mc2_task mc2_param;
2463 +	struct reservation_config config;
2464 +	int res_type = PERIODIC_POLLING;
2465 +	size_t arena_sz;
2466 +	int wss;
2467 +
2468 +	/* default for reservation */
2469 +	config.id = 0;
2470 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
2471 +	config.cpu = -1;
2472 +	
2473 +	mc2_param.crit = CRIT_LEVEL_C;
2474 +	
2475 +	budget_ms = 1000;
2476 +	
2477 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
2478 +		switch (opt) {
2479 +		case 'w':
2480 +			wait = 1;
2481 +			break;
2482 +		case 'p':
2483 +			cluster = atoi(optarg);
2484 +			migrate = 1;
2485 +			config.cpu = cluster;
2486 +			break;
2487 +		case 'l':
2488 +			loops = atoi(optarg);
2489 +			break;
2490 +		case 'k':
2491 +			wss = atoi(optarg);
2492 +			break;
2493 +		case 'm':
2494 +			mc2_param.crit = atoi(optarg);
2495 +			if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
2496 +				res_type = PERIODIC_POLLING;
2497 +			}
2498 +			else
2499 +				usage("Invalid criticality level.");
2500 +			break;
2501 +		case 'b':
2502 +			budget_ms = atof(optarg);
2503 +			break;
2504 +		case 'i':
2505 +			config.priority = atoi(optarg);
2506 +			break;
2507 +		case ':':
2508 +			usage("Argument missing.");
2509 +			break;
2510 +		case '?':
2511 +		default:
2512 +			usage("Bad argument.");
2513 +			break;
2514 +		}
2515 +	}
2516 +	srand(getpid());
2517 +
2518 +	/*
2519 +	 * We need three parameters
2520 +	 */
2521 +	if (argc - optind < 3)
2522 +		usage("Arguments missing.");
2523 +
2524 +	wcet_ms   = atof(argv[optind + 0]);
2525 +	period_ms = atof(argv[optind + 1]);
2526 +
2527 +	wcet   = ms2ns(wcet_ms);
2528 +	period = ms2ns(period_ms);
2529 +	budget = ms2ns(budget_ms);
2530 +	if (wcet <= 0)
2531 +		usage("The worst-case execution time must be a "
2532 +				"positive number.");
2533 +	if (period <= 0)
2534 +		usage("The period must be a positive number.");
2535 +	if (wcet > period) {
2536 +		usage("The worst-case execution time must not "
2537 +				"exceed the period.");
2538 +	}
2539 +
2540 +	duration  = atof(argv[optind + 2]);
2541 +	
2542 +	if (migrate) {
2543 +		ret = be_migrate_to_domain(cluster);
2544 +		if (ret < 0)
2545 +			bail_out("could not migrate to target partition or cluster.");
2546 +	}
2547 +
2548 +	/* reservation config */
2549 +	config.id = gettid();
2550 +	config.polling_params.budget = budget;
2551 +	config.polling_params.period = period;
2552 +	config.polling_params.offset = 0;
2553 +	config.polling_params.relative_deadline = 0;
2554 +	
2555 +	if (config.polling_params.budget > config.polling_params.period) {
2556 +		usage("The budget must not exceed the period.");
2557 +	}
2558 +	
2559 +	/* create a reservation */
2560 +	ret = reservation_create(res_type, &config);
2561 +	if (ret < 0) {
2562 +		bail_out("failed to create reservation.");
2563 +	}
2564 +	
2565 +	init_rt_task_param(&param);
2566 +	param.exec_cost = wcet;
2567 +	param.period = period;
2568 +	param.priority = priority;
2569 +	param.cls = RT_CLASS_HARD;
2570 +	param.release_policy = TASK_PERIODIC;
2571 +	param.budget_policy = NO_ENFORCEMENT;
2572 +	if (migrate) {
2573 +		param.cpu = gettid();
2574 +	}
2575 +	ret = set_rt_task_param(gettid(), &param);
2576 +	if (ret < 0)
2577 +		bail_out("could not setup rt task params");
2578 +	
2579 +	mc2_param.res_id = gettid();
2580 +	ret = set_mc2_task_param(gettid(), &mc2_param);
2581 +	if (ret < 0)
2582 +		bail_out("could not setup mc2 task params");
2583 +	
2584 +	arena_sz = wss*1024;
2585 +	arena = alloc_arena(arena_sz, 0, 0);
2586 +	init_arena(arena, arena_sz);
2587 +	
2588 +	ret = init_litmus();
2589 +	if (ret != 0)
2590 +		bail_out("init_litmus() failed\n");
2591 +
2592 +	start = wctime();
2593 +	ret = task_mode(LITMUS_RT_TASK);
2594 +	if (ret != 0)
2595 +		bail_out("could not become RT task");
2596 +
2597 +	if (mc2_param.crit == CRIT_LEVEL_C)
2598 +		set_page_color(-1);
2599 +	else
2600 +		set_page_color(config.cpu);
2601 +
2602 +	mlockall(MCL_CURRENT | MCL_FUTURE);
2603 +	
2604 +	if (wait) {
2605 +		ret = wait_for_ts_release();
2606 +		if (ret != 0)
2607 +			bail_out("wait_for_ts_release()");
2608 +		start = wctime();
2609 +	}
2610 +
2611 +	while (job(wss, wcet_ms * 0.001, start + duration)) {};
2612 +
2613 +	ret = task_mode(BACKGROUND_TASK);
2614 +	if (ret != 0)
2615 +		bail_out("could not become regular task (huh?)");
2616 +
2617 +	reservation_destroy(gettid(), config.cpu);
2618 +	dealloc_arena(arena, arena_sz);
2619 +	printf("%s finished.\n", argv[0]);
2620 +	return 0;
2621 +}
2622 diff --git a/bin/mc2spin.c b/bin/mc2spin.c
2623 index 1ef3082..25b1c58 100644
2624 --- a/bin/mc2spin.c
2625 +++ b/bin/mc2spin.c
2626 @@ -1,4 +1,5 @@
2627  #include <sys/time.h>
2628 +#include <sys/mman.h>
2629  
2630  #include <stdio.h>
2631  #include <stdlib.h>
2632 @@ -12,7 +13,11 @@
2633  #include "litmus.h"
2634  #include "common.h"
2635  
2636 +#define PAGE_SIZE 4096
2637 +#define NUM_ITEMS 8192
2638  
2639 +int *pages;
2640 +unsigned long *access_order;
2641  
2642  static void usage(char *error) {
2643  	fprintf(stderr, "Error: %s\n", error);
2644 @@ -104,12 +109,42 @@ static void get_exec_times(const char *file, const int column,
2645  static int num[NUMS];
2646  static char* progname;
2647  
2648 +static int randrange(const int max)
2649 +{
2650 +	return (rand() / (RAND_MAX / max + 1));
2651 +}
2652 +
2653 +static void sattolo(unsigned long *items, const unsigned long len)
2654 +{
2655 +	unsigned long i;
2656 +	/* first set up 0, 1, ..., n - 1 */
2657 +	for (i = 0; i < len; i++)
2658 +		items[i] = i;
2659 +	/* note: i is now n */
2660 +	while (1 < i--) {
2661 +		/* 0 <= j < i */
2662 +		int t, j = randrange(i);
2663 +		t = items[i];
2664 +		items[i] = items[j];
2665 +		items[j] = t;
2666 +	}
2667 +}
2668 +
2669  static int loop_once(void)
2670  {
2671  	int i, j = 0;
2672  	for (i = 0; i < NUMS; i++)
2673  		j += num[i]++;
2674  	return j;
2675 +/*
2676 +	int i, tmp;
2677 +	for (i = 0; i < NUM_ITEMS; i++) {
2678 +		tmp = pages[access_order[i]];
2679 +		if (access_order[i] % 3 == 0)
2680 +			pages[access_order[i]] = i+tmp;
2681 +	}
2682 +	return 1;
2683 +*/
2684  }
2685  
2686  static int loop_for(double exec_time, double emergency_exit)
2687 @@ -138,11 +173,11 @@ static int loop_for(double exec_time, double emergency_exit)
2688  }
2689  
2690  
2691 -static void debug_delay_loop(void)
2692 +static void debug_delay_loop(int count)
2693  {
2694  	double start, end, delay;
2695  
2696 -	while (1) {
2697 +	while (count--) {
2698  		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
2699  			start = wctime();
2700  			loop_for(delay, 0);
2701 @@ -249,7 +284,7 @@ int main(int argc, char** argv)
2702  	lt_t hyperperiod;
2703  	lt_t budget;
2704  	double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
2705 -	unsigned int priority = LITMUS_LOWEST_PRIORITY;
2706 +	unsigned int priority = LITMUS_NO_PRIORITY;
2707  	int migrate = 0;
2708  	int cluster = 0;
2709  	int opt;
2710 @@ -266,7 +301,7 @@ int main(int argc, char** argv)
2711  	struct rt_task param;
2712  	struct mc2_task mc2_param;
2713  	struct reservation_config config;
2714 -	int res_type = SPORADIC_POLLING;
2715 +	int res_type = PERIODIC_POLLING;
2716  	int n_str, num_int = 0;
2717  
2718  	int verbose = 0;
2719 @@ -284,7 +319,7 @@ int main(int argc, char** argv)
2720  	/* default for reservation */
2721  	config.id = 0;
2722  	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
2723 -	config.cpu = 0;
2724 +	config.cpu = -1;
2725  	
2726  	mc2_param.crit = CRIT_LEVEL_C;
2727  	
2728 @@ -346,14 +381,10 @@ int main(int argc, char** argv)
2729  			break;
2730  		case 'm':
2731  			mc2_param.crit = atoi(optarg);
2732 -			if (mc2_param.crit == CRIT_LEVEL_A) {
2733 -				res_type = TABLE_DRIVEN;
2734 -			}
2735 -			else if (mc2_param.crit == CRIT_LEVEL_B) {
2736 -				res_type = PERIODIC_POLLING;
2737 -			}
2738 -			else
2739 +			if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
2740  				usage("Invalid criticality level.");
2741 +			}
2742 +			res_type = PERIODIC_POLLING;
2743  			break;
2744  		case 'h':
2745  			hyperperiod_ms = atof(optarg);
2746 @@ -362,14 +393,7 @@ int main(int argc, char** argv)
2747  			budget_ms = atof(optarg);
2748  			break;
2749  		case 'i':
2750 -			n_str = strlen(optarg);
2751 -			while(n_str--) {
2752 -				if (optarg[n_str] == ',')
2753 -					num_int++;
2754 -			}
2755 -			if (!num_int)
2756 -				usage("Bad argument.");
2757 -			config.table_driven_params.intervals = parse_td_intervals(num_int, optarg, &config.table_driven_params.num_intervals);
2758 +			config.priority = atoi(optarg);
2759  			break;
2760  		case ':':
2761  			usage("Argument missing.");
2762 @@ -382,10 +406,13 @@ int main(int argc, char** argv)
2763  	}
2764  
2765  	if (test_loop) {
2766 -		debug_delay_loop();
2767 +		debug_delay_loop(1);
2768  		return 0;
2769  	}
2770  
2771 +	if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
2772 +		usage("Bad criticailty level or priority");
2773 +
2774  	srand(getpid());
2775  
2776  	if (file) {
2777 @@ -440,20 +467,15 @@ int main(int argc, char** argv)
2778  	config.id = gettid();
2779  	
2780  	if (hyperperiod%period != 0 ) {
2781 -		bail_out("hyperperiod must be multiple of period");
2782 +		;//bail_out("hyperperiod must be multiple of period");
2783  	}
2784  	
2785 -	if (mc2_param.crit == CRIT_LEVEL_A) {
2786 -		config.table_driven_params.major_cycle_length = period;
2787 -	}
2788 -	else if (mc2_param.crit == CRIT_LEVEL_B) {
2789 -		config.polling_params.budget = budget;
2790 -		config.polling_params.period = period;
2791 -		config.polling_params.offset = 0;
2792 -		config.polling_params.relative_deadline = 0;
2793 -		if (config.polling_params.budget > config.polling_params.period) {
2794 -			usage("The budget must not exceed the period.");
2795 -		}
2796 +	config.polling_params.budget = budget;
2797 +	config.polling_params.period = period;
2798 +	config.polling_params.offset = 0;
2799 +	config.polling_params.relative_deadline = 0;
2800 +	if (config.polling_params.budget > config.polling_params.period) {
2801 +		usage("The budget must not exceed the period.");
2802  	}
2803  	
2804  	/* create a reservation */
2805 @@ -474,23 +496,33 @@ int main(int argc, char** argv)
2806  		param.cpu = gettid();
2807  	}
2808  	ret = set_rt_task_param(gettid(), &param);
2809 +//printf("SET_RT_TASK\n");
2810  	if (ret < 0)
2811  		bail_out("could not setup rt task params");
2812  	
2813 -	mc2_param.pid = gettid();
2814 -	mc2_param.hyperperiod = hyperperiod;
2815 +	mc2_param.res_id = gettid();
2816  	ret = set_mc2_task_param(gettid(), &mc2_param);
2817 +//printf("SET_MC2_TASK\n");
2818  	if (ret < 0)
2819  		bail_out("could not setup mc2 task params");
2820 +
2821 +	pages = (int*)malloc(sizeof(int)*NUM_ITEMS);
2822 +	access_order = (unsigned long*)malloc(sizeof(unsigned long)*NUM_ITEMS);
2823 +	sattolo(access_order, NUM_ITEMS);
2824 +
2825  	init_litmus();
2826 +printf("CALL\n");
2827 +	set_page_color(config.cpu);
2828 +printf("CALL\n");
2829  
2830 +//printf("INIT_LITMUS\n");
2831  	start = wctime();
2832  	ret = task_mode(LITMUS_RT_TASK);
2833 +//printf("TASK_MODE\n");
2834  	if (ret != 0)
2835  		bail_out("could not become RT task");
2836  
2837  	if (protocol >= 0) {
2838 -		/* open reference to semaphore */
2839  		lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
2840  		if (lock_od < 0) {
2841  			perror("litmus_open_lock");
2842 @@ -500,6 +532,7 @@ int main(int argc, char** argv)
2843  
2844  
2845  	if (wait) {
2846 +//printf("BEFORE WAIT\n");
2847  		ret = wait_for_ts_release();
2848  		if (ret != 0)
2849  			bail_out("wait_for_ts_release()");
2850 @@ -507,9 +540,7 @@ int main(int argc, char** argv)
2851  	}
2852  
2853  	if (file) {
2854 -		/* use times read from the CSV file */
2855  		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
2856 -			/* convert job's length to seconds */
2857  			job(exec_times[cur_job] * 0.001 * scale,
2858  			    start + duration,
2859  			    lock_od, cs_length * 0.001);
2860 @@ -521,11 +552,10 @@ int main(int argc, char** argv)
2861  				printf("rtspin/%d:%u @ %.4fms\n", gettid(),
2862  					job_no, (wctime() - start) * 1000);
2863  			}
2864 -			/* convert to seconds and scale */
2865  		} while (job(wcet_ms * 0.001 * scale, start + duration,
2866  			   lock_od, cs_length * 0.001));
2867  	}
2868 -
2869 +printf("BEFORE BACK_TASK\n");
2870  	ret = task_mode(BACKGROUND_TASK);
2871  	if (ret != 0)
2872  		bail_out("could not become regular task (huh?)");
2873 @@ -534,8 +564,11 @@ int main(int argc, char** argv)
2874  		free(exec_times);
2875  
2876  	reservation_destroy(gettid(), config.cpu);
2877 -	if (mc2_param.crit == CRIT_LEVEL_A) {
2878 -		free(config.table_driven_params.intervals);
2879 -	}
2880 +	
2881 +printf("CALL\n");
2882 +	set_page_color(config.cpu);
2883 +printf("CALL\n");
2884 +	free(pages);
2885 +	free(access_order);
2886  	return 0;
2887  }
2888 diff --git a/bin/mc2spin_td.c b/bin/mc2spin_td.c
2889 new file mode 100644
2890 index 0000000..79704a5
2891 --- /dev/null
2892 +++ b/bin/mc2spin_td.c
2893 @@ -0,0 +1,585 @@
2894 +#include <sys/time.h>
2895 +#include <sys/mman.h>
2896 +
2897 +#include <stdio.h>
2898 +#include <stdlib.h>
2899 +#include <unistd.h>
2900 +#include <time.h>
2901 +#include <string.h>
2902 +#include <assert.h>
2903 +#include <limits.h>
2904 +
2905 +
2906 +#include "litmus.h"
2907 +#include "common.h"
2908 +
2909 +#define PAGE_SIZE 4096
2910 +#define NUM_ITEMS 8192
2911 +
2912 +int *pages;
2913 +unsigned long *access_order;
2914 +
2915 +static void usage(char *error) {
2916 +	fprintf(stderr, "Error: %s\n", error);
2917 +	fprintf(stderr,
2918 +		"Usage:\n"
2919 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
2920 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
2921 +		"	rt_spin -l\n"
2922 +		"\n"
2923 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
2924 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
2925 +		"              [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
2926 +		"              [-i [start,end]:[start,end]...]\n"
2927 +		"\n"
2928 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n"
2929 +		"CRITICAL SECTION LENGTH is in milliseconds.\n");
2930 +	exit(EXIT_FAILURE);
2931 +}
2932 +
2933 +/*
2934 + * returns the character that made processing stop, newline or EOF
2935 + */
2936 +static int skip_to_next_line(FILE *fstream)
2937 +{
2938 +	int ch;
2939 +	for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
2940 +	return ch;
2941 +}
2942 +
2943 +static void skip_comments(FILE *fstream)
2944 +{
2945 +	int ch;
2946 +	for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
2947 +		skip_to_next_line(fstream);
2948 +	ungetc(ch, fstream);
2949 +}
2950 +
2951 +static void get_exec_times(const char *file, const int column,
2952 +			   int *num_jobs,    double **exec_times)
2953 +{
2954 +	FILE *fstream;
2955 +	int  cur_job, cur_col, ch;
2956 +	*num_jobs = 0;
2957 +
2958 +	fstream = fopen(file, "r");
2959 +	if (!fstream)
2960 +		bail_out("could not open execution time file");
2961 +
2962 +	/* figure out the number of jobs */
2963 +	do {
2964 +		skip_comments(fstream);
2965 +		ch = skip_to_next_line(fstream);
2966 +		if (ch != EOF)
2967 +			++(*num_jobs);
2968 +	} while (ch != EOF);
2969 +
2970 +	if (-1 == fseek(fstream, 0L, SEEK_SET))
2971 +		bail_out("rewinding file failed");
2972 +
2973 +	/* allocate space for exec times */
2974 +	*exec_times = calloc(*num_jobs, sizeof(*exec_times));
2975 +	if (!*exec_times)
2976 +		bail_out("couldn't allocate memory");
2977 +
2978 +	for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
2979 +
2980 +		skip_comments(fstream);
2981 +
2982 +		for (cur_col = 1; cur_col < column; ++cur_col) {
2983 +			/* discard input until we get to the column we want */
2984 +			int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
2985 +		}
2986 +
2987 +		/* get the desired exec. time */
2988 +		if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
2989 +			fprintf(stderr, "invalid execution time near line %d\n",
2990 +					cur_job);
2991 +			exit(EXIT_FAILURE);
2992 +		}
2993 +
2994 +		skip_to_next_line(fstream);
2995 +	}
2996 +
2997 +	assert(cur_job == *num_jobs);
2998 +	fclose(fstream);
2999 +}
3000 +
3001 +#define NUMS 4096
3002 +static int num[NUMS];
3003 +static char* progname;
3004 +
3005 +static int randrange(const int max)
3006 +{
3007 +	return (rand() / (RAND_MAX / max + 1));
3008 +}
3009 +
3010 +static void sattolo(unsigned long *items, const unsigned long len)
3011 +{
3012 +	unsigned long i;
3013 +	/* first set up 0, 1, ..., n - 1 */
3014 +	for (i = 0; i < len; i++)
3015 +		items[i] = i;
3016 +	/* note: i is now n */
3017 +	while (1 < i--) {
3018 +		/* 0 <= j < i */
3019 +		int t, j = randrange(i);
3020 +		t = items[i];
3021 +		items[i] = items[j];
3022 +		items[j] = t;
3023 +	}
3024 +}
3025 +
3026 +static int loop_once(void)
3027 +{
3028 +	int i, j = 0;
3029 +	for (i = 0; i < NUMS; i++)
3030 +		j += num[i]++;
3031 +	return j;
3032 +/*
3033 +	int i, tmp;
3034 +	for (i = 0; i < NUM_ITEMS; i++) {
3035 +		tmp = pages[access_order[i]];
3036 +		if (access_order[i] % 3 == 0)
3037 +			pages[access_order[i]] = i+tmp;
3038 +	}
3039 +	return 1;
3040 +*/
3041 +}
3042 +
3043 +static int loop_for(double exec_time, double emergency_exit)
3044 +{
3045 +	double last_loop = 0, loop_start;
3046 +	int tmp = 0;
3047 +
3048 +	double start = cputime();
3049 +	double now = cputime();
3050 +
3051 +	while (now + last_loop < start + exec_time) {
3052 +		loop_start = now;
3053 +		tmp += loop_once();
3054 +		now = cputime();
3055 +		last_loop = now - loop_start;
3056 +		if (emergency_exit && wctime() > emergency_exit) {
3057 +			/* Oops --- this should only be possible if the execution time tracking
3058 +			 * is broken in the LITMUS^RT kernel. */
3059 +			fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
3060 +			fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
3061 +			break;
3062 +		}
3063 +	}
3064 +
3065 +	return tmp;
3066 +}
3067 +
3068 +
3069 +static void debug_delay_loop(void)
3070 +{
3071 +	double start, end, delay;
3072 +
3073 +	while (1) {
3074 +		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
3075 +			start = wctime();
3076 +			loop_for(delay, 0);
3077 +			end = wctime();
3078 +			printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
3079 +			       delay,
3080 +			       end - start,
3081 +			       end - start - delay,
3082 +			       100 * (end - start - delay) / delay);
3083 +		}
3084 +	}
3085 +}
3086 +
3087 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
3088 +{
3089 +	double chunk1, chunk2;
3090 +
3091 +	if (wctime() > program_end)
3092 +		return 0;
3093 +	else {
3094 +		if (lock_od >= 0) {
3095 +			/* simulate critical section somewhere in the middle */
3096 +			chunk1 = drand48() * (exec_time - cs_length);
3097 +			chunk2 = exec_time - cs_length - chunk1;
3098 +
3099 +			/* non-critical section */
3100 +			loop_for(chunk1, program_end + 1);
3101 +
3102 +			/* critical section */
3103 +			litmus_lock(lock_od);
3104 +			loop_for(cs_length, program_end + 1);
3105 +			litmus_unlock(lock_od);
3106 +
3107 +			/* non-critical section */
3108 +			loop_for(chunk2, program_end + 2);
3109 +		} else {
3110 +			loop_for(exec_time, program_end + 1);
3111 +		}
3112 +		sleep_next_period();
3113 +		return 1;
3114 +	}
3115 +}
3116 +
3117 +struct lt_interval* parse_td_intervals(int num, char* optarg, unsigned int *num_intervals)
3118 +{
3119 +	int i, matched;
3120 +	struct lt_interval *slots = malloc(sizeof(slots[0]) * num);
3121 +	char** arg = (char**)malloc(sizeof(char*) * num);
3122 +	char *token, *saveptr;
3123 +	double start, end;
3124 +	
3125 +	for (i = 0; i < num; i++) {
3126 +		arg[i] = (char*)malloc(sizeof(char)*100);
3127 +	}
3128 +	
3129 +	i = 0;
3130 +	token = strtok_r(optarg, ":", &saveptr);
3131 +	while(token != NULL) {
3132 +		sprintf(arg[i++], "%s", token);
3133 +		token = strtok_r(NULL, ":", &saveptr);
3134 +	}
3135 +	
3136 +	*num_intervals = 0;
3137 +	
3138 +	for (i=0; i<num; i++) {
3139 +		matched = sscanf(arg[i], "[%lf,%lf]", &start, &end);
3140 +		if (matched != 2) {
3141 +			fprintf(stderr, "could not parse '%s' as interval\n", arg[i]);
3142 +			exit(5);
3143 +		}
3144 +		if (start < 0) {
3145 +			fprintf(stderr, "interval %s: must not start before zero\n", arg[i]);
3146 +			exit(5);
3147 +		}
3148 +		if (end <= start) {
3149 +			fprintf(stderr, "interval %s: end before start\n", arg[i]);
3150 +			exit(5);
3151 +		}
3152 +
3153 +		slots[i].start = ms2ns(start);
3154 +		slots[i].end   = ms2ns(end);
3155 +
3156 +		if (i > 0 && slots[i - 1].end >= slots[i].start) {
3157 +			fprintf(stderr, "interval %s: overlaps with previous interval\n", arg[i]);
3158 +			exit(5);
3159 +		}
3160 +
3161 +		(*num_intervals)++;
3162 +	}
3163 +	
3164 +	for (i=0; i<num; i++) {
3165 +		free(arg[i]);
3166 +	}
3167 +	free(arg);
3168 +	return slots;
3169 +}
3170 +
3171 +#define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:vh:m:i:b:"
3172 +int main(int argc, char** argv)
3173 +{
3174 +	int ret;
3175 +	lt_t wcet;
3176 +	lt_t period;
3177 +	lt_t hyperperiod;
3178 +	lt_t budget;
3179 +	double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
3180 +	unsigned int priority = LITMUS_NO_PRIORITY;
3181 +	int migrate = 0;
3182 +	int cluster = 0;
3183 +	int opt;
3184 +	int wait = 0;
3185 +	int test_loop = 0;
3186 +	int column = 1;
3187 +	const char *file = NULL;
3188 +	int want_enforcement = 0;
3189 +	double duration = 0, start = 0;
3190 +	double *exec_times = NULL;
3191 +	double scale = 1.0;
3192 +	task_class_t class = RT_CLASS_HARD;
3193 +	int cur_job = 0, num_jobs = 0;
3194 +	struct rt_task param;
3195 +	struct mc2_task mc2_param;
3196 +	struct reservation_config config;
3197 +	int res_type = PERIODIC_POLLING;
3198 +	int n_str, num_int = 0;
3199 +
3200 +	int verbose = 0;
3201 +	unsigned int job_no;
3202 +
3203 +	/* locking */
3204 +	int lock_od = -1;
3205 +	int resource_id = 0;
3206 +	const char *lock_namespace = "./rtspin-locks";
3207 +	int protocol = -1;
3208 +	double cs_length = 1; /* millisecond */
3209 +
3210 +	progname = argv[0];
3211 +
3212 +	/* default for reservation */
3213 +	config.id = 0;
3214 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
3215 +	config.cpu = -1;
3216 +	
3217 +	mc2_param.crit = CRIT_LEVEL_C;
3218 +	
3219 +	hyperperiod_ms = 1000;
3220 +	budget_ms = 10;
3221 +	
3222 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
3223 +		switch (opt) {
3224 +		case 'w':
3225 +			wait = 1;
3226 +			break;
3227 +		case 'p':
3228 +			cluster = atoi(optarg);
3229 +			migrate = 1;
3230 +			config.cpu = cluster;
3231 +			break;
3232 +		case 'q':
3233 +			priority = atoi(optarg);
3234 +			if (!litmus_is_valid_fixed_prio(priority))
3235 +				usage("Invalid priority.");
3236 +			break;
3237 +		case 'c':
3238 +			class = str2class(optarg);
3239 +			if (class == -1)
3240 +				usage("Unknown task class.");
3241 +			break;
3242 +		case 'e':
3243 +			want_enforcement = 1;
3244 +			break;
3245 +		case 'l':
3246 +			test_loop = 1;
3247 +			break;
3248 +		case 'o':
3249 +			column = atoi(optarg);
3250 +			break;
3251 +		case 'f':
3252 +			file = optarg;
3253 +			break;
3254 +		case 's':
3255 +			scale = atof(optarg);
3256 +			break;
3257 +		case 'X':
3258 +			protocol = lock_protocol_for_name(optarg);
3259 +			if (protocol < 0)
3260 +				usage("Unknown locking protocol specified.");
3261 +			break;
3262 +		case 'L':
3263 +			cs_length = atof(optarg);
3264 +			if (cs_length <= 0)
3265 +				usage("Invalid critical section length.");
3266 +			break;
3267 +		case 'Q':
3268 +			resource_id = atoi(optarg);
3269 +			if (resource_id <= 0 && strcmp(optarg, "0"))
3270 +				usage("Invalid resource ID.");
3271 +			break;
3272 +		case 'v':
3273 +			verbose = 1;
3274 +			break;
3275 +		case 'm':
3276 +			mc2_param.crit = atoi(optarg);
3277 +			if (mc2_param.crit == CRIT_LEVEL_A) {
3278 +				res_type = TABLE_DRIVEN;
3279 +				config.priority = LITMUS_HIGHEST_PRIORITY;
3280 +			}
3281 +			else if (mc2_param.crit == CRIT_LEVEL_B || mc2_param.crit == CRIT_LEVEL_C) {
3282 +				res_type = PERIODIC_POLLING;
3283 +			}
3284 +			else
3285 +				usage("Invalid criticality level.");
3286 +			break;
3287 +		case 'h':
3288 +			hyperperiod_ms = atof(optarg);
3289 +			break;
3290 +		case 'b':
3291 +			budget_ms = atof(optarg);
3292 +			break;
3293 +		case 'i':
3294 +			n_str = strlen(optarg);
3295 +			while(n_str--) {
3296 +				if (optarg[n_str] == ',')
3297 +					num_int++;
3298 +			}
3299 +			if (!num_int)
3300 +				usage("Bad argument.");
3301 +			config.table_driven_params.intervals = parse_td_intervals(num_int, optarg, &config.table_driven_params.num_intervals);
3302 +			break;
3303 +		case ':':
3304 +			usage("Argument missing.");
3305 +			break;
3306 +		case '?':
3307 +		default:
3308 +			usage("Bad argument.");
3309 +			break;
3310 +		}
3311 +	}
3312 +
3313 +	if (test_loop) {
3314 +		debug_delay_loop();
3315 +		return 0;
3316 +	}
3317 +
3318 +	srand(getpid());
3319 +
3320 +	if (file) {
3321 +		get_exec_times(file, column, &num_jobs, &exec_times);
3322 +
3323 +		if (argc - optind < 2)
3324 +			usage("Arguments missing.");
3325 +
3326 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
3327 +			/* convert the execution time to seconds */
3328 +			duration += exec_times[cur_job] * 0.001;
3329 +		}
3330 +	} else {
3331 +		/*
3332 +		 * if we're not reading from the CSV file, then we need
3333 +		 * three parameters
3334 +		 */
3335 +		if (argc - optind < 3)
3336 +			usage("Arguments missing.");
3337 +	}
3338 +
3339 +	wcet_ms   = atof(argv[optind + 0]);
3340 +	period_ms = atof(argv[optind + 1]);
3341 +
3342 +	wcet   = ms2ns(wcet_ms);
3343 +	period = ms2ns(period_ms);
3344 +	budget = ms2ns(budget_ms);
3345 +	hyperperiod = ms2ns(hyperperiod_ms);
3346 +	
3347 +	if (wcet <= 0)
3348 +		usage("The worst-case execution time must be a "
3349 +				"positive number.");
3350 +	if (period <= 0)
3351 +		usage("The period must be a positive number.");
3352 +	if (!file && wcet > period) {
3353 +		usage("The worst-case execution time must not "
3354 +				"exceed the period.");
3355 +	}
3356 +
3357 +	if (!file)
3358 +		duration  = atof(argv[optind + 2]);
3359 +	else if (file && num_jobs > 1)
3360 +		duration += period_ms * 0.001 * (num_jobs - 1);
3361 +
3362 +	if (migrate) {
3363 +		ret = be_migrate_to_domain(cluster);
3364 +		if (ret < 0)
3365 +			bail_out("could not migrate to target partition or cluster.");
3366 +	}
3367 +
3368 +	/* reservation config */
3369 +	config.id = gettid();
3370 +	
3371 +	if (hyperperiod%period != 0 ) {
3372 +		;//bail_out("hyperperiod must be multiple of period");
3373 +	}
3374 +	
3375 +	if (mc2_param.crit == CRIT_LEVEL_A) {
3376 +		config.table_driven_params.major_cycle_length = period;
3377 +	} else if (mc2_param.crit == CRIT_LEVEL_B || mc2_param.crit == CRIT_LEVEL_C) {
3378 +		config.polling_params.budget = budget;
3379 +		config.polling_params.period = period;
3380 +		config.polling_params.offset = 0;
3381 +		config.polling_params.relative_deadline = 0;
3382 +		if (config.polling_params.budget > config.polling_params.period) {
3383 +			usage("The budget must not exceed the period.");
3384 +		}
3385 +	}
3386 +	
3387 +	/* create a reservation */
3388 +	ret = reservation_create(res_type, &config);
3389 +	if (ret < 0) {
3390 +		bail_out("failed to create reservation.");
3391 +	}
3392 +	
3393 +	init_rt_task_param(&param);
3394 +	param.exec_cost = wcet;
3395 +	param.period = period;
3396 +	param.priority = priority;
3397 +	param.cls = class;
3398 +	param.release_policy = TASK_PERIODIC;
3399 +	param.budget_policy = (want_enforcement) ?
3400 +			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
3401 +	if (migrate) {
3402 +		param.cpu = gettid();
3403 +	}
3404 +	ret = set_rt_task_param(gettid(), &param);
3405 +//printf("SET_RT_TASK\n");
3406 +	if (ret < 0)
3407 +		bail_out("could not setup rt task params");
3408 +	
3409 +	mc2_param.res_id = gettid();
3410 +	ret = set_mc2_task_param(gettid(), &mc2_param);
3411 +//printf("SET_MC2_TASK\n");
3412 +	if (ret < 0)
3413 +		bail_out("could not setup mc2 task params");
3414 +
3415 +	pages = (int*)malloc(sizeof(int)*NUM_ITEMS);
3416 +	access_order = (unsigned long*)malloc(sizeof(unsigned long)*NUM_ITEMS);
3417 +	sattolo(access_order, NUM_ITEMS);
3418 +
3419 +//	mlockall(MCL_CURRENT | MCL_FUTURE);
3420 +//	set_page_color(config.cpu);
3421 +
3422 +	init_litmus();
3423 +//printf("INIT_LITMUS\n");
3424 +	start = wctime();
3425 +	ret = task_mode(LITMUS_RT_TASK);
3426 +//printf("TASK_MODE\n");
3427 +	if (ret != 0)
3428 +		bail_out("could not become RT task");
3429 +
3430 +	if (protocol >= 0) {
3431 +		lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
3432 +		if (lock_od < 0) {
3433 +			perror("litmus_open_lock");
3434 +			usage("Could not open lock.");
3435 +		}
3436 +	}
3437 +
3438 +
3439 +	if (wait) {
3440 +//printf("BEFORE WAIT\n");
3441 +		ret = wait_for_ts_release();
3442 +		if (ret != 0)
3443 +			bail_out("wait_for_ts_release()");
3444 +		start = wctime();
3445 +	}
3446 +
3447 +	if (file) {
3448 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
3449 +			job(exec_times[cur_job] * 0.001 * scale,
3450 +			    start + duration,
3451 +			    lock_od, cs_length * 0.001);
3452 +		}
3453 +	} else {
3454 +		do {
3455 +			if (verbose) {
3456 +				get_job_no(&job_no);
3457 +				printf("rtspin/%d:%u @ %.4fms\n", gettid(),
3458 +					job_no, (wctime() - start) * 1000);
3459 +			}
3460 +		} while (job(wcet_ms * 0.001 * scale, start + duration,
3461 +			   lock_od, cs_length * 0.001));
3462 +	}
3463 +printf("BEFORE BACK_TASK\n");
3464 +	ret = task_mode(BACKGROUND_TASK);
3465 +	if (ret != 0)
3466 +		bail_out("could not become regular task (huh?)");
3467 +
3468 +	if (file)
3469 +		free(exec_times);
3470 +
3471 +	reservation_destroy(gettid(), config.cpu);
3472 +	if (mc2_param.crit == CRIT_LEVEL_A) {
3473 +		free(config.table_driven_params.intervals);
3474 +	}
3475 +	free(pages);
3476 +	free(access_order);
3477 +	return 0;
3478 +}
3479 diff --git a/bin/mc2syn.c b/bin/mc2syn.c
3480 new file mode 100644
3481 index 0000000..020653c
3482 --- /dev/null
3483 +++ b/bin/mc2syn.c
3484 @@ -0,0 +1,575 @@
3485 +#include <sys/time.h>
3486 +#include <sys/mman.h>
3487 +
3488 +#include <stdio.h>
3489 +#include <stdlib.h>
3490 +#include <unistd.h>
3491 +#include <time.h>
3492 +#include <string.h>
3493 +#include <assert.h>
3494 +#include <limits.h>
3495 +
3496 +
3497 +#include "litmus.h"
3498 +#include "common.h"
3499 +
3500 +#define PAGE_SIZE	(4096)
3501 +#define WSS_KB		(64)
3502 +#define NUM_ITEMS	((WSS_KB*1024)/sizeof(unsigned long))
3503 +
3504 +unsigned long *pages;
3505 +unsigned long *access_order;
3506 +static int loops;
3507 +
3508 +static int randrange(const int max)
3509 +{
3510 +	return (rand() / (RAND_MAX / max + 1));
3511 +}
3512 +
3513 +/*
3514 + * Sattolo's algorithm makes a random cycle that includes all the elements
3515 + * in the items array.
3516 + */
3517 +static void sattolo(unsigned long *items, const unsigned long len)
3518 +{
3519 +	unsigned long i;
3520 +	/* first set up 0, 1, ..., n - 1 */
3521 +	for (i = 0; i < len; i++)
3522 +		items[i] = i;
3523 +	/* note: i is now n */
3524 +	while (1 < i--) {
3525 +		/* 0 <= j < i */
3526 +		int t, j = randrange(i);
3527 +		t = items[i];
3528 +		items[i] = items[j];
3529 +		items[j] = t;
3530 +	}
3531 +}
3532 +
3533 +static void usage(char *error) {
3534 +	fprintf(stderr, "Error: %s\n", error);
3535 +	fprintf(stderr,
3536 +		"Usage:\n"
3537 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
3538 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
3539 +		"	rt_spin -l\n"
3540 +		"\n"
3541 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
3542 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
3543 +		"              [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
3544 +		"              [-i [start,end]:[start,end]...]\n"
3545 +		"\n"
3546 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n"
3547 +		"CRITICAL SECTION LENGTH is in milliseconds.\n");
3548 +	exit(EXIT_FAILURE);
3549 +}
3550 +
3551 +/*
3552 + * returns the character that made processing stop, newline or EOF
3553 + */
3554 +static int skip_to_next_line(FILE *fstream)
3555 +{
3556 +	int ch;
3557 +	for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
3558 +	return ch;
3559 +}
3560 +
3561 +static void skip_comments(FILE *fstream)
3562 +{
3563 +	int ch;
3564 +	for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
3565 +		skip_to_next_line(fstream);
3566 +	ungetc(ch, fstream);
3567 +}
3568 +
3569 +static void get_exec_times(const char *file, const int column,
3570 +			   int *num_jobs,    double **exec_times)
3571 +{
3572 +	FILE *fstream;
3573 +	int  cur_job, cur_col, ch;
3574 +	*num_jobs = 0;
3575 +
3576 +	fstream = fopen(file, "r");
3577 +	if (!fstream)
3578 +		bail_out("could not open execution time file");
3579 +
3580 +	/* figure out the number of jobs */
3581 +	do {
3582 +		skip_comments(fstream);
3583 +		ch = skip_to_next_line(fstream);
3584 +		if (ch != EOF)
3585 +			++(*num_jobs);
3586 +	} while (ch != EOF);
3587 +
3588 +	if (-1 == fseek(fstream, 0L, SEEK_SET))
3589 +		bail_out("rewinding file failed");
3590 +
3591 +	/* allocate space for exec times */
3592 +	*exec_times = calloc(*num_jobs, sizeof(*exec_times));
3593 +	if (!*exec_times)
3594 +		bail_out("couldn't allocate memory");
3595 +
3596 +	for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
3597 +
3598 +		skip_comments(fstream);
3599 +
3600 +		for (cur_col = 1; cur_col < column; ++cur_col) {
3601 +			/* discard input until we get to the column we want */
3602 +			int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
3603 +		}
3604 +
3605 +		/* get the desired exec. time */
3606 +		if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
3607 +			fprintf(stderr, "invalid execution time near line %d\n",
3608 +					cur_job);
3609 +			exit(EXIT_FAILURE);
3610 +		}
3611 +
3612 +		skip_to_next_line(fstream);
3613 +	}
3614 +
3615 +	assert(cur_job == *num_jobs);
3616 +	fclose(fstream);
3617 +}
3618 +
3619 +#define NUMS 4096
3620 +static int num[NUMS];
3621 +static char* progname;
3622 +
3623 +int index_s = 0;
3624 +
3625 +static int loop_once(void)
3626 +{
3627 +/*	int i, j = 0;
3628 +	for (i = 0; i < NUMS; i++)
3629 +		j += num[i]++;
3630 +	return j;
3631 +*/
3632 +	unsigned long i;
3633 +	unsigned long tmp;
3634 +	for (i = 0; i < NUM_ITEMS; i++) {
3635 +		tmp = access_order[i];
3636 +		((volatile unsigned long*)access_order)[i] = tmp++;
3637 +		((volatile unsigned long*)access_order)[i] = access_order[i]%NUM_ITEMS;
3638 +	}
3639 +	
3640 +	return tmp;
3641 +}
3642 +
3643 +static int loop_for(double exec_time, double emergency_exit)
3644 +{
3645 +	double last_loop = 0, loop_start;
3646 +	int tmp = 0;
3647 +	int iter = 0;
3648 +
3649 +	double start = cputime();
3650 +	double now = cputime();
3651 +
3652 +	//while (now + last_loop < start + exec_time) {
3653 +	while(iter++ < loops) {
3654 +		loop_start = now;
3655 +		tmp = loop_once();
3656 +		now = cputime();
3657 +		last_loop = now - loop_start;
3658 +		if (emergency_exit && wctime() > emergency_exit) {
3659 +			/* Oops --- this should only be possible if the execution time tracking
3660 +			 * is broken in the LITMUS^RT kernel. */
3661 +			fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
3662 +			fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
3663 +			break;
3664 +		}
3665 +	}
3666 +
3667 +	return tmp;
3668 +}
3669 +
3670 +
3671 +static void debug_delay_loop(void)
3672 +{
3673 +	double start, end, delay;
3674 +
3675 +	while (1) {
3676 +		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
3677 +			start = wctime();
3678 +			loop_for(delay, 0);
3679 +			end = wctime();
3680 +			printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
3681 +			       delay,
3682 +			       end - start,
3683 +			       end - start - delay,
3684 +			       100 * (end - start - delay) / delay);
3685 +		}
3686 +	}
3687 +}
3688 +
3689 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
3690 +{
3691 +	double chunk1, chunk2;
3692 +
3693 +	if (wctime() > program_end)
3694 +		return 0;
3695 +	else {
3696 +		if (lock_od >= 0) {
3697 +			/* simulate critical section somewhere in the middle */
3698 +			chunk1 = drand48() * (exec_time - cs_length);
3699 +			chunk2 = exec_time - cs_length - chunk1;
3700 +
3701 +			/* non-critical section */
3702 +			loop_for(chunk1, program_end + 1);
3703 +
3704 +			/* critical section */
3705 +			litmus_lock(lock_od);
3706 +			loop_for(cs_length, program_end + 1);
3707 +			litmus_unlock(lock_od);
3708 +
3709 +			/* non-critical section */
3710 +			loop_for(chunk2, program_end + 2);
3711 +		} else {
3712 +			loop_for(exec_time, program_end + 1);
3713 +		}
3714 +		sleep_next_period();
3715 +		return 1;
3716 +	}
3717 +}
3718 +
3719 +struct lt_interval* parse_td_intervals(int num, char* optarg, unsigned int *num_intervals)
3720 +{
3721 +	int i, matched;
3722 +	struct lt_interval *slots = malloc(sizeof(slots[0]) * num);
3723 +	char** arg = (char**)malloc(sizeof(char*) * num);
3724 +	char *token, *saveptr;
3725 +	double start, end;
3726 +	
3727 +	for (i = 0; i < num; i++) {
3728 +		arg[i] = (char*)malloc(sizeof(char)*100);
3729 +	}
3730 +	
3731 +	i = 0;
3732 +	token = strtok_r(optarg, ":", &saveptr);
3733 +	while(token != NULL) {
3734 +		sprintf(arg[i++], "%s", token);
3735 +		token = strtok_r(NULL, ":", &saveptr);
3736 +	}
3737 +	
3738 +	*num_intervals = 0;
3739 +	
3740 +	for (i=0; i<num; i++) {
3741 +		matched = sscanf(arg[i], "[%lf,%lf]", &start, &end);
3742 +		if (matched != 2) {
3743 +			fprintf(stderr, "could not parse '%s' as interval\n", arg[i]);
3744 +			exit(5);
3745 +		}
3746 +		if (start < 0) {
3747 +			fprintf(stderr, "interval %s: must not start before zero\n", arg[i]);
3748 +			exit(5);
3749 +		}
3750 +		if (end <= start) {
3751 +			fprintf(stderr, "interval %s: end before start\n", arg[i]);
3752 +			exit(5);
3753 +		}
3754 +
3755 +		slots[i].start = ms2ns(start);
3756 +		slots[i].end   = ms2ns(end);
3757 +
3758 +		if (i > 0 && slots[i - 1].end >= slots[i].start) {
3759 +			fprintf(stderr, "interval %s: overlaps with previous interval\n", arg[i]);
3760 +			exit(5);
3761 +		}
3762 +
3763 +		(*num_intervals)++;
3764 +	}
3765 +	
3766 +	for (i=0; i<num; i++) {
3767 +		free(arg[i]);
3768 +	}
3769 +	free(arg);
3770 +	return slots;
3771 +}
3772 +
3773 +#define OPTSTR "p:c:wl:veo:f:s:q:X:L:Q:vh:m:i:b:"
3774 +int main(int argc, char** argv)
3775 +{
3776 +	int ret, i;
3777 +	lt_t wcet;
3778 +	lt_t period;
3779 +	lt_t hyperperiod;
3780 +	lt_t budget;
3781 +	double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
3782 +	unsigned int priority = LITMUS_NO_PRIORITY;
3783 +	int migrate = 0;
3784 +	int cluster = 0;
3785 +	int opt;
3786 +	int wait = 0;
3787 +	int test_loop = 0;
3788 +	int column = 1;
3789 +	const char *file = NULL;
3790 +	int want_enforcement = 0;
3791 +	double duration = 0, start = 0;
3792 +	double *exec_times = NULL;
3793 +	double scale = 1.0;
3794 +	task_class_t class = RT_CLASS_HARD;
3795 +	int cur_job = 0, num_jobs = 0;
3796 +	struct rt_task param;
3797 +	struct mc2_task mc2_param;
3798 +	struct reservation_config config;
3799 +	int res_type = PERIODIC_POLLING;
3800 +	int n_str, num_int = 0;
3801 +
3802 +	int verbose = 0;
3803 +	unsigned int job_no;
3804 +
3805 +	/* locking */
3806 +	int lock_od = -1;
3807 +	int resource_id = 0;
3808 +	const char *lock_namespace = "./rtspin-locks";
3809 +	int protocol = -1;
3810 +	double cs_length = 1; /* millisecond */
3811 +
3812 +	progname = argv[0];
3813 +
3814 +	/* default for reservation */
3815 +	config.id = 0;
3816 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
3817 +	config.cpu = -1;
3818 +	
3819 +	mc2_param.crit = CRIT_LEVEL_C;
3820 +	
3821 +	hyperperiod_ms = 1000;
3822 +	budget_ms = 10;
3823 +	
3824 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
3825 +		switch (opt) {
3826 +		case 'w':
3827 +			wait = 1;
3828 +			break;
3829 +		case 'p':
3830 +			cluster = atoi(optarg);
3831 +			migrate = 1;
3832 +			config.cpu = cluster;
3833 +			break;
3834 +		case 'q':
3835 +			priority = atoi(optarg);
3836 +			if (!litmus_is_valid_fixed_prio(priority))
3837 +				usage("Invalid priority.");
3838 +			break;
3839 +		case 'c':
3840 +			class = str2class(optarg);
3841 +			if (class == -1)
3842 +				usage("Unknown task class.");
3843 +			break;
3844 +		case 'e':
3845 +			want_enforcement = 1;
3846 +			break;
3847 +		case 'l':
3848 +			loops = atoi(optarg);
3849 +			break;
3850 +		case 'o':
3851 +			column = atoi(optarg);
3852 +			break;
3853 +		case 'f':
3854 +			file = optarg;
3855 +			break;
3856 +		case 's':
3857 +			scale = atof(optarg);
3858 +			break;
3859 +		case 'X':
3860 +			protocol = lock_protocol_for_name(optarg);
3861 +			if (protocol < 0)
3862 +				usage("Unknown locking protocol specified.");
3863 +			break;
3864 +		case 'L':
3865 +			cs_length = atof(optarg);
3866 +			if (cs_length <= 0)
3867 +				usage("Invalid critical section length.");
3868 +			break;
3869 +		case 'Q':
3870 +			resource_id = atoi(optarg);
3871 +			if (resource_id <= 0 && strcmp(optarg, "0"))
3872 +				usage("Invalid resource ID.");
3873 +			break;
3874 +		case 'v':
3875 +			verbose = 1;
3876 +			break;
3877 +		case 'm':
3878 +			mc2_param.crit = atoi(optarg);
3879 +			if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
3880 +				res_type = PERIODIC_POLLING;
3881 +			}
3882 +			else
3883 +				usage("Invalid criticality level.");
3884 +			break;
3885 +		case 'h':
3886 +			hyperperiod_ms = atof(optarg);
3887 +			break;
3888 +		case 'b':
3889 +			budget_ms = atof(optarg);
3890 +			break;
3891 +		case 'i':
3892 +			config.priority = atoi(optarg);
3893 +			break;
3894 +		case ':':
3895 +			usage("Argument missing.");
3896 +			break;
3897 +		case '?':
3898 +		default:
3899 +			usage("Bad argument.");
3900 +			break;
3901 +		}
3902 +	}
3903 +
3904 +	if (test_loop) {
3905 +		debug_delay_loop();
3906 +		return 0;
3907 +	}
3908 +
3909 +	srand(getpid());
3910 +
3911 +	if (file) {
3912 +		get_exec_times(file, column, &num_jobs, &exec_times);
3913 +
3914 +		if (argc - optind < 2)
3915 +			usage("Arguments missing.");
3916 +
3917 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
3918 +			/* convert the execution time to seconds */
3919 +			duration += exec_times[cur_job] * 0.001;
3920 +		}
3921 +	} else {
3922 +		/*
3923 +		 * if we're not reading from the CSV file, then we need
3924 +		 * three parameters
3925 +		 */
3926 +		if (argc - optind < 3)
3927 +			usage("Arguments missing.");
3928 +	}
3929 +
3930 +	wcet_ms   = atof(argv[optind + 0]);
3931 +	period_ms = atof(argv[optind + 1]);
3932 +
3933 +	wcet   = ms2ns(wcet_ms);
3934 +	period = ms2ns(period_ms);
3935 +	budget = ms2ns(budget_ms);
3936 +	hyperperiod = ms2ns(hyperperiod_ms);
3937 +	if (wcet <= 0)
3938 +		usage("The worst-case execution time must be a "
3939 +				"positive number.");
3940 +	if (period <= 0)
3941 +		usage("The period must be a positive number.");
3942 +	if (!file && wcet > period) {
3943 +		usage("The worst-case execution time must not "
3944 +				"exceed the period.");
3945 +	}
3946 +
3947 +	if (!file)
3948 +		duration  = atof(argv[optind + 2]);
3949 +	else if (file && num_jobs > 1)
3950 +		duration += period_ms * 0.001 * (num_jobs - 1);
3951 +
3952 +	if (migrate) {
3953 +		ret = be_migrate_to_domain(cluster);
3954 +		if (ret < 0)
3955 +			bail_out("could not migrate to target partition or cluster.");
3956 +	}
3957 +
3958 +	/* reservation config */
3959 +	config.id = gettid();
3960 +	
3961 +	if (hyperperiod%period != 0 ) {
3962 +		;//bail_out("hyperperiod must be multiple of period");
3963 +	}
3964 +	
3965 +	config.polling_params.budget = budget;
3966 +	config.polling_params.period = period;
3967 +	config.polling_params.offset = 0;
3968 +	config.polling_params.relative_deadline = 0;
3969 +	
3970 +	if (config.polling_params.budget > config.polling_params.period) {
3971 +		usage("The budget must not exceed the period.");
3972 +	}
3973 +	
3974 +	/* create a reservation */
3975 +	ret = reservation_create(res_type, &config);
3976 +	if (ret < 0) {
3977 +		bail_out("failed to create reservation.");
3978 +	}
3979 +	
3980 +	init_rt_task_param(&param);
3981 +	param.exec_cost = wcet;
3982 +	param.period = period;
3983 +	param.priority = priority;
3984 +	param.cls = class;
3985 +	param.release_policy = TASK_PERIODIC;
3986 +	param.budget_policy = (want_enforcement) ?
3987 +			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
3988 +	if (migrate) {
3989 +		param.cpu = gettid();
3990 +	}
3991 +	ret = set_rt_task_param(gettid(), &param);
3992 +	if (ret < 0)
3993 +		bail_out("could not setup rt task params");
3994 +	
3995 +	mc2_param.res_id = gettid();
3996 +	ret = set_mc2_task_param(gettid(), &mc2_param);
3997 +	if (ret < 0)
3998 +		bail_out("could not setup mc2 task params");
3999 +	
4000 +	pages = (unsigned long*)malloc(WSS_KB * 1024);
4001 +	access_order = (unsigned long*)malloc(NUM_ITEMS*sizeof(unsigned long));
4002 +
4003 +	srand(0);
4004 +	sattolo(access_order, NUM_ITEMS);
4005 +		
4006 +	ret = init_litmus();
4007 +	if (ret != 0)
4008 +		bail_out("init_litmus() failed\n");
4009 +
4010 +	start = wctime();
4011 +	ret = task_mode(LITMUS_RT_TASK);
4012 +	if (ret != 0)
4013 +		bail_out("could not become RT task");
4014 +
4015 +	if (protocol >= 0) {
4016 +		lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
4017 +		if (lock_od < 0) {
4018 +			perror("litmus_open_lock");
4019 +			usage("Could not open lock.");
4020 +		}
4021 +	}
4022 +
4023 +
4024 +	if (wait) {
4025 +		ret = wait_for_ts_release();
4026 +		if (ret != 0)
4027 +			bail_out("wait_for_ts_release()");
4028 +		start = wctime();
4029 +	}
4030 +
4031 +	if (file) {
4032 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
4033 +			job(exec_times[cur_job] * 0.001 * scale,
4034 +			    start + duration,
4035 +			    lock_od, cs_length * 0.001);
4036 +		}
4037 +	} else {
4038 +		do {
4039 +			if (verbose) {
4040 +				get_job_no(&job_no);
4041 +				printf("rtspin/%d:%u @ %.4fms\n", gettid(),
4042 +					job_no, (wctime() - start) * 1000);
4043 +			}
4044 +		} while (job(wcet_ms * 0.001 * scale, start + duration,
4045 +			   lock_od, cs_length * 0.001));
4046 +	}
4047 +
4048 +	ret = task_mode(BACKGROUND_TASK);
4049 +	if (ret != 0)
4050 +		bail_out("could not become regular task (huh?)");
4051 +
4052 +	if (file)
4053 +		free(exec_times);
4054 +
4055 +	reservation_destroy(gettid(), config.cpu);
4056 +	free(pages);
4057 +	free(access_order);
4058 +	return 0;
4059 +}
4060 diff --git a/bin/mc2sys.c b/bin/mc2sys.c
4061 new file mode 100644
4062 index 0000000..b8f1e2f
4063 --- /dev/null
4064 +++ b/bin/mc2sys.c
4065 @@ -0,0 +1,557 @@
4066 +#include <sys/time.h>
4067 +#include <sys/mman.h>
4068 +
4069 +#include <stdio.h>
4070 +#include <stdlib.h>
4071 +#include <unistd.h>
4072 +#include <time.h>
4073 +#include <string.h>
4074 +#include <assert.h>
4075 +#include <limits.h>
4076 +
4077 +
4078 +#include "litmus.h"
4079 +#include "common.h"
4080 +
4081 +static void usage(char *error) {
4082 +	fprintf(stderr, "Error: %s\n", error);
4083 +	fprintf(stderr,
4084 +		"Usage:\n"
4085 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
4086 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
4087 +		"	rt_spin -l\n"
4088 +		"\n"
4089 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
4090 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
4091 +		"              [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
4092 +		"              [-i [start,end]:[start,end]...]\n"
4093 +		"\n"
4094 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n"
4095 +		"CRITICAL SECTION LENGTH is in milliseconds.\n");
4096 +	exit(EXIT_FAILURE);
4097 +}
4098 +
4099 +/*
4100 + * returns the character that made processing stop, newline or EOF
4101 + */
4102 +static int skip_to_next_line(FILE *fstream)
4103 +{
4104 +	int ch;
4105 +	for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
4106 +	return ch;
4107 +}
4108 +
4109 +static void skip_comments(FILE *fstream)
4110 +{
4111 +	int ch;
4112 +	for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
4113 +		skip_to_next_line(fstream);
4114 +	ungetc(ch, fstream);
4115 +}
4116 +
4117 +static void get_exec_times(const char *file, const int column,
4118 +			   int *num_jobs,    double **exec_times)
4119 +{
4120 +	FILE *fstream;
4121 +	int  cur_job, cur_col, ch;
4122 +	*num_jobs = 0;
4123 +
4124 +	fstream = fopen(file, "r");
4125 +	if (!fstream)
4126 +		bail_out("could not open execution time file");
4127 +
4128 +	/* figure out the number of jobs */
4129 +	do {
4130 +		skip_comments(fstream);
4131 +		ch = skip_to_next_line(fstream);
4132 +		if (ch != EOF)
4133 +			++(*num_jobs);
4134 +	} while (ch != EOF);
4135 +
4136 +	if (-1 == fseek(fstream, 0L, SEEK_SET))
4137 +		bail_out("rewinding file failed");
4138 +
4139 +	/* allocate space for exec times */
4140 +	*exec_times = calloc(*num_jobs, sizeof(*exec_times));
4141 +	if (!*exec_times)
4142 +		bail_out("couldn't allocate memory");
4143 +
4144 +	for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
4145 +
4146 +		skip_comments(fstream);
4147 +
4148 +		for (cur_col = 1; cur_col < column; ++cur_col) {
4149 +			/* discard input until we get to the column we want */
4150 +			int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
4151 +		}
4152 +
4153 +		/* get the desired exec. time */
4154 +		if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
4155 +			fprintf(stderr, "invalid execution time near line %d\n",
4156 +					cur_job);
4157 +			exit(EXIT_FAILURE);
4158 +		}
4159 +
4160 +		skip_to_next_line(fstream);
4161 +	}
4162 +
4163 +	assert(cur_job == *num_jobs);
4164 +	fclose(fstream);
4165 +}
4166 +// 4096 = 32KB
4167 +// 8192 = 64KB
4168 +// 16384 = 128KB
4169 +// 32768 = 256KB
4170 +
4171 +#define NUMS 32768
4172 +static int num[NUMS];
4173 +static long unsigned int order[NUMS];
4174 +static char* progname;
4175 +
4176 +static int randrange(const int max)
4177 +{
4178 +	return (rand() / (RAND_MAX / max + 1));
4179 +}
4180 +
4181 +static void sattolo(unsigned long *items, const unsigned long len)
4182 +{
4183 +	unsigned long i;
4184 +	/* first set up 0, 1, ..., n - 1 */
4185 +	for (i = 0; i < len; i++)
4186 +		items[i] = i;
4187 +	/* note: i is now n */
4188 +	while (1 < i--) {
4189 +		/* 0 <= j < i */
4190 +		int t, j = randrange(i);
4191 +		t = items[i];
4192 +		items[i] = items[j];
4193 +		items[j] = t;
4194 +	}
4195 +}
4196 +
4197 +static int loop_once(void)
4198 +{
4199 +	int n, i, j = 0;
4200 +	for (n = 0; n < 2; n++) {
4201 +		for (i = 0; i < NUMS; i++) {
4202 +			j += num[order[i]]++;
4203 +		}
4204 +	}
4205 +	return j;
4206 +}
4207 +
4208 +static int loop_for(double exec_time, double emergency_exit)
4209 +{
4210 +	double last_loop = 10, loop_start;
4211 +	int tmp = 0;
4212 +
4213 +	double start = cputime();
4214 +	double now = cputime();
4215 +/*
4216 +	while (now + last_loop < start + exec_time) {
4217 +		loop_start = now;
4218 +		tmp += loop_once();
4219 +		now = cputime();
4220 +		last_loop = now - loop_start;
4221 +		if (emergency_exit && wctime() > emergency_exit) {
4222 +			fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
4223 +			fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
4224 +			break;
4225 +		}
4226 +	}
4227 +*/
4228 +	while (last_loop--) {
4229 +		tmp += loop_once();
4230 +		null_call(NULL);
4231 +	}
4232 +	return tmp;
4233 +}
4234 +
4235 +
4236 +static void debug_delay_loop(int count)
4237 +{
4238 +	double start, end, delay;
4239 +
4240 +	while (count--) {
4241 +		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
4242 +			start = wctime();
4243 +			loop_for(delay, 0);
4244 +			end = wctime();
4245 +			printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
4246 +			       delay,
4247 +			       end - start,
4248 +			       end - start - delay,
4249 +			       100 * (end - start - delay) / delay);
4250 +		}
4251 +	}
4252 +}
4253 +
4254 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
4255 +{
4256 +	double chunk1, chunk2;
4257 +
4258 +	if (wctime() > program_end)
4259 +		return 0;
4260 +	else {
4261 +		if (lock_od >= 0) {
4262 +			/* simulate critical section somewhere in the middle */
4263 +			chunk1 = drand48() * (exec_time - cs_length);
4264 +			chunk2 = exec_time - cs_length - chunk1;
4265 +
4266 +			/* non-critical section */
4267 +			loop_for(chunk1, program_end + 1);
4268 +
4269 +			/* critical section */
4270 +			litmus_lock(lock_od);
4271 +			loop_for(cs_length, program_end + 1);
4272 +			litmus_unlock(lock_od);
4273 +
4274 +			/* non-critical section */
4275 +			loop_for(chunk2, program_end + 2);
4276 +		} else {
4277 +			loop_for(exec_time, program_end + 1);
4278 +		}
4279 +		sleep_next_period();
4280 +		return 1;
4281 +	}
4282 +}
4283 +
4284 +struct lt_interval* parse_td_intervals(int num, char* optarg, unsigned int *num_intervals)
4285 +{
4286 +	int i, matched;
4287 +	struct lt_interval *slots = malloc(sizeof(slots[0]) * num);
4288 +	char** arg = (char**)malloc(sizeof(char*) * num);
4289 +	char *token, *saveptr;
4290 +	double start, end;
4291 +	
4292 +	for (i = 0; i < num; i++) {
4293 +		arg[i] = (char*)malloc(sizeof(char)*100);
4294 +	}
4295 +	
4296 +	i = 0;
4297 +	token = strtok_r(optarg, ":", &saveptr);
4298 +	while(token != NULL) {
4299 +		sprintf(arg[i++], "%s", token);
4300 +		token = strtok_r(NULL, ":", &saveptr);
4301 +	}
4302 +	
4303 +	*num_intervals = 0;
4304 +	
4305 +	for (i=0; i<num; i++) {
4306 +		matched = sscanf(arg[i], "[%lf,%lf]", &start, &end);
4307 +		if (matched != 2) {
4308 +			fprintf(stderr, "could not parse '%s' as interval\n", arg[i]);
4309 +			exit(5);
4310 +		}
4311 +		if (start < 0) {
4312 +			fprintf(stderr, "interval %s: must not start before zero\n", arg[i]);
4313 +			exit(5);
4314 +		}
4315 +		if (end <= start) {
4316 +			fprintf(stderr, "interval %s: end before start\n", arg[i]);
4317 +			exit(5);
4318 +		}
4319 +
4320 +		slots[i].start = ms2ns(start);
4321 +		slots[i].end   = ms2ns(end);
4322 +
4323 +		if (i > 0 && slots[i - 1].end >= slots[i].start) {
4324 +			fprintf(stderr, "interval %s: overlaps with previous interval\n", arg[i]);
4325 +			exit(5);
4326 +		}
4327 +
4328 +		(*num_intervals)++;
4329 +	}
4330 +	
4331 +	for (i=0; i<num; i++) {
4332 +		free(arg[i]);
4333 +	}
4334 +	free(arg);
4335 +	return slots;
4336 +}
4337 +
4338 +#define OPTSTR "p:c:wlveo:f:s:q:X:L:Q:vh:m:i:b:"
4339 +int main(int argc, char** argv)
4340 +{
4341 +	int ret;
4342 +	lt_t wcet;
4343 +	lt_t period;
4344 +	lt_t hyperperiod;
4345 +	lt_t budget;
4346 +	double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
4347 +	unsigned int priority = LITMUS_NO_PRIORITY;
4348 +	int migrate = 0;
4349 +	int cluster = 0;
4350 +	int opt;
4351 +	int wait = 0;
4352 +	int test_loop = 0;
4353 +	int column = 1;
4354 +	const char *file = NULL;
4355 +	int want_enforcement = 0;
4356 +	double duration = 0, start = 0;
4357 +	double *exec_times = NULL;
4358 +	double scale = 1.0;
4359 +	task_class_t class = RT_CLASS_HARD;
4360 +	int cur_job = 0, num_jobs = 0;
4361 +	struct rt_task param;
4362 +	struct mc2_task mc2_param;
4363 +	struct reservation_config config;
4364 +	int res_type = PERIODIC_POLLING;
4365 +	int n_str, num_int = 0;
4366 +
4367 +	int verbose = 0;
4368 +	unsigned int job_no;
4369 +
4370 +	/* locking */
4371 +	int lock_od = -1;
4372 +	int resource_id = 0;
4373 +	const char *lock_namespace = "./rtspin-locks";
4374 +	int protocol = -1;
4375 +	double cs_length = 1; /* millisecond */
4376 +
4377 +	progname = argv[0];
4378 +
4379 +	/* default for reservation */
4380 +	config.id = 0;
4381 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
4382 +	config.cpu = -1;
4383 +	
4384 +	mc2_param.crit = CRIT_LEVEL_C;
4385 +	
4386 +	hyperperiod_ms = 1000;
4387 +	budget_ms = 10;
4388 +	
4389 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
4390 +		switch (opt) {
4391 +		case 'w':
4392 +			wait = 1;
4393 +			break;
4394 +		case 'p':
4395 +			cluster = atoi(optarg);
4396 +			migrate = 1;
4397 +			config.cpu = cluster;
4398 +			break;
4399 +		case 'q':
4400 +			priority = atoi(optarg);
4401 +			if (!litmus_is_valid_fixed_prio(priority))
4402 +				usage("Invalid priority.");
4403 +			break;
4404 +		case 'c':
4405 +			class = str2class(optarg);
4406 +			if (class == -1)
4407 +				usage("Unknown task class.");
4408 +			break;
4409 +		case 'e':
4410 +			want_enforcement = 1;
4411 +			break;
4412 +		case 'l':
4413 +			test_loop = 1;
4414 +			break;
4415 +		case 'o':
4416 +			column = atoi(optarg);
4417 +			break;
4418 +		case 'f':
4419 +			file = optarg;
4420 +			break;
4421 +		case 's':
4422 +			scale = atof(optarg);
4423 +			break;
4424 +		case 'X':
4425 +			protocol = lock_protocol_for_name(optarg);
4426 +			if (protocol < 0)
4427 +				usage("Unknown locking protocol specified.");
4428 +			break;
4429 +		case 'L':
4430 +			cs_length = atof(optarg);
4431 +			if (cs_length <= 0)
4432 +				usage("Invalid critical section length.");
4433 +			break;
4434 +		case 'Q':
4435 +			resource_id = atoi(optarg);
4436 +			if (resource_id <= 0 && strcmp(optarg, "0"))
4437 +				usage("Invalid resource ID.");
4438 +			break;
4439 +		case 'v':
4440 +			verbose = 1;
4441 +			break;
4442 +		case 'm':
4443 +			mc2_param.crit = atoi(optarg);
4444 +			if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) {
4445 +				usage("Invalid criticality level.");
4446 +			}
4447 +			res_type = PERIODIC_POLLING;
4448 +			break;
4449 +		case 'h':
4450 +			hyperperiod_ms = atof(optarg);
4451 +			break;
4452 +		case 'b':
4453 +			budget_ms = atof(optarg);
4454 +			break;
4455 +		case 'i':
4456 +			config.priority = atoi(optarg);
4457 +			break;
4458 +		case ':':
4459 +			usage("Argument missing.");
4460 +			break;
4461 +		case '?':
4462 +		default:
4463 +			usage("Bad argument.");
4464 +			break;
4465 +		}
4466 +	}
4467 +
4468 +	if (test_loop) {
4469 +		debug_delay_loop(1);
4470 +		return 0;
4471 +	}
4472 +
4473 +	if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
4474 +		usage("Bad criticailty level or priority");
4475 +
4476 +	srand(getpid());
4477 +
4478 +	if (file) {
4479 +		get_exec_times(file, column, &num_jobs, &exec_times);
4480 +
4481 +		if (argc - optind < 2)
4482 +			usage("Arguments missing.");
4483 +
4484 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
4485 +			/* convert the execution time to seconds */
4486 +			duration += exec_times[cur_job] * 0.001;
4487 +		}
4488 +	} else {
4489 +		/*
4490 +		 * if we're not reading from the CSV file, then we need
4491 +		 * three parameters
4492 +		 */
4493 +		if (argc - optind < 3)
4494 +			usage("Arguments missing.");
4495 +	}
4496 +
4497 +	wcet_ms   = atof(argv[optind + 0]);
4498 +	period_ms = atof(argv[optind + 1]);
4499 +
4500 +	wcet   = ms2ns(wcet_ms);
4501 +	period = ms2ns(period_ms);
4502 +	budget = ms2ns(budget_ms);
4503 +	hyperperiod = ms2ns(hyperperiod_ms);
4504 +	
4505 +	if (wcet <= 0)
4506 +		usage("The worst-case execution time must be a "
4507 +				"positive number.");
4508 +	if (period <= 0)
4509 +		usage("The period must be a positive number.");
4510 +	if (!file && wcet > period) {
4511 +		usage("The worst-case execution time must not "
4512 +				"exceed the period.");
4513 +	}
4514 +
4515 +	if (!file)
4516 +		duration  = atof(argv[optind + 2]);
4517 +	else if (file && num_jobs > 1)
4518 +		duration += period_ms * 0.001 * (num_jobs - 1);
4519 +
4520 +	if (migrate) {
4521 +		ret = be_migrate_to_domain(cluster);
4522 +		if (ret < 0)
4523 +			bail_out("could not migrate to target partition or cluster.");
4524 +	}
4525 +
4526 +	sattolo(order, NUMS);
4527 +
4528 +	/* reservation config */
4529 +	config.id = gettid();
4530 +	
4531 +	if (hyperperiod%period != 0 ) {
4532 +		;//bail_out("hyperperiod must be multiple of period");
4533 +	}
4534 +	
4535 +	config.polling_params.budget = budget;
4536 +	config.polling_params.period = period;
4537 +	config.polling_params.offset = 0;
4538 +	config.polling_params.relative_deadline = 0;
4539 +	if (config.polling_params.budget > config.polling_params.period) {
4540 +		usage("The budget must not exceed the period.");
4541 +	}
4542 +	
4543 +	/* create a reservation */
4544 +	ret = reservation_create(res_type, &config);
4545 +	if (ret < 0) {
4546 +		bail_out("failed to create reservation.");
4547 +	}
4548 +	
4549 +	init_rt_task_param(&param);
4550 +	param.exec_cost = wcet;
4551 +	param.period = period;
4552 +	param.priority = priority;
4553 +	param.cls = class;
4554 +	param.release_policy = TASK_PERIODIC;
4555 +	param.budget_policy = (want_enforcement) ?
4556 +			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
4557 +	if (migrate) {
4558 +		param.cpu = gettid();
4559 +	}
4560 +	ret = set_rt_task_param(gettid(), &param);
4561 +//printf("SET_RT_TASK\n");
4562 +	if (ret < 0)
4563 +		bail_out("could not setup rt task params");
4564 +	
4565 +	mc2_param.res_id = gettid();
4566 +	ret = set_mc2_task_param(gettid(), &mc2_param);
4567 +//printf("SET_MC2_TASK\n");
4568 +	if (ret < 0)
4569 +		bail_out("could not setup mc2 task params");
4570 +
4571 +	init_litmus();
4572 +
4573 +//printf("INIT_LITMUS\n");
4574 +	start = wctime();
4575 +	ret = task_mode(LITMUS_RT_TASK);
4576 +//printf("TASK_MODE\n");
4577 +	if (ret != 0)
4578 +		bail_out("could not become RT task");
4579 +
4580 +	if (protocol >= 0) {
4581 +		lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
4582 +		if (lock_od < 0) {
4583 +			perror("litmus_open_lock");
4584 +			usage("Could not open lock.");
4585 +		}
4586 +	}
4587 +
4588 +
4589 +	if (wait) {
4590 +		ret = wait_for_ts_release();
4591 +		if (ret != 0)
4592 +			bail_out("wait_for_ts_release()");
4593 +		start = wctime();
4594 +	}
4595 +
4596 +	if (file) {
4597 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
4598 +			job(exec_times[cur_job] * 0.001 * scale,
4599 +			    start + duration,
4600 +			    lock_od, cs_length * 0.001);
4601 +		}
4602 +	} else {
4603 +		do {
4604 +			if (verbose) {
4605 +				get_job_no(&job_no);
4606 +				printf("rtspin/%d:%u @ %.4fms\n", gettid(),
4607 +					job_no, (wctime() - start) * 1000);
4608 +			}
4609 +		} while (job(wcet_ms * 0.001 * scale, start + duration,
4610 +			   lock_od, cs_length * 0.001));
4611 +	}
4612 +	ret = task_mode(BACKGROUND_TASK);
4613 +	if (ret != 0)
4614 +		bail_out("could not become regular task (huh?)");
4615 +
4616 +	if (file)
4617 +		free(exec_times);
4618 +
4619 +	reservation_destroy(gettid(), config.cpu);
4620 +	
4621 +	return 0;
4622 +}
4623 diff --git a/bin/mc2thrash.c b/bin/mc2thrash.c
4624 new file mode 100644
4625 index 0000000..813f74f
4626 --- /dev/null
4627 +++ b/bin/mc2thrash.c
4628 @@ -0,0 +1,272 @@
4629 +#include <sys/time.h>
4630 +#include <sys/mman.h>
4631 +
4632 +#include <stdio.h>
4633 +#include <stdlib.h>
4634 +#include <unistd.h>
4635 +#include <time.h>
4636 +#include <string.h>
4637 +#include <assert.h>
4638 +#include <limits.h>
4639 +
4640 +#include "litmus.h"
4641 +#include "common.h"
4642 +#include "cache_common.h"
4643 +
4644 +#define PAGE_SIZE (4096)
4645 +#define CACHELINE_SIZE 32
4646 +#define WSS 		1024
4647 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
4648 +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
4649 +#define INTS_IN_1KB	(1024 / sizeof(int))
4650 +
4651 +static cacheline_t* arena = NULL;
4652 +
4653 +static int random_walk(cacheline_t *mem, int write_cycle)
4654 +{
4655 +	/* a random cycle among the cache lines was set up by init_arena(). */
4656 +	int sum, i, next;
4657 +
4658 +	int numlines = WSS * CACHELINES_IN_1KB;
4659 +
4660 +	sum = 0;
4661 +
4662 +	next = mem - arena;
4663 +
4664 +	if (write_cycle == 0) {
4665 +		for (i = 0; i < numlines; i++) {
4666 +			/* every element in the cacheline has the same value */
4667 +			next = arena[next].line[0];
4668 +			sum += next;
4669 +		}
4670 +	}
4671 +	
4672 +	else {
4673 +		int w, which_line;
4674 +		for (i = 0, w = 0; i < numlines; i++) {
4675 +			which_line = next;
4676 +			next = arena[next].line[0];
4677 +			if((w % write_cycle) != (write_cycle - 1)) {
4678 +				sum += next;
4679 +			}
4680 +			else {
4681 +				((volatile cacheline_t*)arena)[which_line].line[0] = next;
4682 +			}
4683 +		}
4684 +	}
4685 +	return sum;
4686 +}
4687 +
4688 +static cacheline_t* random_start(void)
4689 +{
4690 +	return arena + randrange(0, ((WSS * 1024)/sizeof(cacheline_t)));
4691 +}
4692 +
4693 +static volatile int dont_optimize_me = 0;
4694 +
4695 +static void usage(char *error) {
4696 +	fprintf(stderr, "Error: %s\n", error);
4697 +	fprintf(stderr,
4698 +		"Usage:\n"
4699 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
4700 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
4701 +		"	rt_spin -l\n"
4702 +		"\n"
4703 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
4704 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-m CRITICALITY LEVEL]\n"
4705 +		"              [-k WSS] [-l LOOPS] [-b BUDGET]\n"
4706 +		"\n"
4707 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n");
4708 +	exit(EXIT_FAILURE);
4709 +}
4710 +
4711 +static int loop_once(void)
4712 +{
4713 +	cacheline_t *mem;
4714 +	int temp;
4715 +	
4716 +	mem = random_start();
4717 +	temp = random_walk(mem, 1);
4718 +    
4719 +	//mem = sequential_start(wss);
4720 +	//temp = sequential_walk(mem, wss, 0);
4721 +	dont_optimize_me = temp;
4722 +	
4723 +	return dont_optimize_me;
4724 +}
4725 +
4726 +static int job(double exec_time, double program_end)
4727 +{
4728 +	if (wctime() > program_end)
4729 +		return 0;
4730 +	else {
4731 +		double last_loop = 0, loop_start;
4732 +		double start = cputime();
4733 +		double now = cputime();
4734 +		while(now + last_loop < start + exec_time) {
4735 +			loop_start = now;
4736 +			loop_once();
4737 +			now = cputime();
4738 +			last_loop = now - loop_start;
4739 +		}
4740 +		sleep_next_period(); 
4741 +   		return 1;
4742 +	}
4743 +}
4744 +
4745 +#define OPTSTR "p:wm:i:k:"
4746 +int main(int argc, char** argv)
4747 +{
4748 +	int ret, i;
4749 +	lt_t wcet, period, budget;
4750 +	double wcet_ms, period_ms;
4751 +	unsigned int priority = LITMUS_NO_PRIORITY;
4752 +	int migrate = 0;
4753 +	int cluster = 0;
4754 +	int opt;
4755 +	int wait = 0;
4756 +	double duration = 0, start = 0;
4757 +	struct rt_task param;
4758 +	struct mc2_task mc2_param;
4759 +	struct reservation_config config;
4760 +	int res_type = PERIODIC_POLLING;
4761 +	size_t arena_sz;
4762 +	
4763 +	/* default for reservation */
4764 +	config.id = 0;
4765 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
4766 +	config.cpu = -1;
4767 +	mc2_param.crit = CRIT_LEVEL_C;
4768 +	
4769 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
4770 +		switch (opt) {
4771 +		case 'w':
4772 +			wait = 1;
4773 +			break;
4774 +		case 'p':
4775 +			cluster = atoi(optarg);
4776 +			migrate = 1;
4777 +			config.cpu = cluster;
4778 +			break;
4779 +		case 'm':
4780 +			mc2_param.crit = atoi(optarg);
4781 +			if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
4782 +				res_type = PERIODIC_POLLING;
4783 +			}
4784 +			else
4785 +				usage("Invalid criticality level.");
4786 +			break;
4787 +		case 'i':
4788 +			config.priority = atoi(optarg);
4789 +			break;
4790 +		case ':':
4791 +			usage("Argument missing.");
4792 +			break;
4793 +		case '?':
4794 +		default:
4795 +			usage("Bad argument.");
4796 +			break;
4797 +		}
4798 +	}
4799 +	srand(getpid());
4800 +	/* We need three parameters */
4801 +	if (argc - optind < 3)
4802 +		usage("Arguments missing.");
4803 +
4804 +	wcet_ms   = atof(argv[optind + 0]);
4805 +	period_ms = atof(argv[optind + 1]);
4806 +
4807 +	wcet   = ms2ns(wcet_ms);
4808 +	period = ms2ns(period_ms);
4809 +	budget = ms2ns(period_ms);
4810 +	if (wcet <= 0)
4811 +		usage("The worst-case execution time must be a "
4812 +				"positive number.");
4813 +	if (period <= 0)
4814 +		usage("The period must be a positive number.");
4815 +	if (wcet > period) {
4816 +		usage("The worst-case execution time must not "
4817 +				"exceed the period.");
4818 +	}
4819 +
4820 +	duration  = atof(argv[optind + 2]);
4821 +	
4822 +	if (migrate) {
4823 +		ret = be_migrate_to_domain(cluster);
4824 +		if (ret < 0)
4825 +			bail_out("could not migrate to target partition or cluster.");
4826 +	}
4827 +
4828 +	/* reservation config */
4829 +	config.id = gettid();
4830 +	config.polling_params.budget = budget;
4831 +	config.polling_params.period = period;
4832 +	config.polling_params.offset = 0;
4833 +	config.polling_params.relative_deadline = 0;
4834 +	
4835 +	if (config.polling_params.budget > config.polling_params.period) {
4836 +		usage("The budget must not exceed the period.");
4837 +	}
4838 +	
4839 +	/* create a reservation */
4840 +	ret = reservation_create(res_type, &config);
4841 +	if (ret < 0) {
4842 +		bail_out("failed to create reservation.");
4843 +	}
4844 +	
4845 +	init_rt_task_param(&param);
4846 +	param.exec_cost = wcet;
4847 +	param.period = period;
4848 +	param.priority = priority;
4849 +	param.cls = RT_CLASS_HARD;
4850 +	param.release_policy = TASK_PERIODIC;
4851 +	param.budget_policy = NO_ENFORCEMENT;
4852 +	if (migrate) {
4853 +		param.cpu = gettid();
4854 +	}
4855 +	ret = set_rt_task_param(gettid(), &param);
4856 +	if (ret < 0)
4857 +		bail_out("could not setup rt task params");
4858 +	
4859 +	mc2_param.res_id = gettid();
4860 +	ret = set_mc2_task_param(gettid(), &mc2_param);
4861 +	if (ret < 0)
4862 +		bail_out("could not setup mc2 task params");
4863 +	
4864 +	arena_sz = WSS*1024;
4865 +	arena = alloc_arena(arena_sz, 0, 0);
4866 +	init_arena(arena, arena_sz);
4867 +	
4868 +	ret = init_litmus();
4869 +	if (ret != 0)
4870 +		bail_out("init_litmus() failed\n");
4871 +
4872 +	start = wctime();
4873 +	ret = task_mode(LITMUS_RT_TASK);
4874 +	if (ret != 0)
4875 +		bail_out("could not become RT task");
4876 +
4877 +	if (mc2_param.crit == CRIT_LEVEL_C)
4878 +		set_page_color(-1);
4879 +	else
4880 +		set_page_color(config.cpu);
4881 +	
4882 +	lock_memory();
4883 +	
4884 +	if (wait) {
4885 +		ret = wait_for_ts_release();
4886 +		if (ret != 0)
4887 +			bail_out("wait_for_ts_release()");
4888 +		start = wctime();
4889 +	}
4890 +
4891 +	while (job(wcet_ms * 0.001, start + duration)) {};
4892 +
4893 +	ret = task_mode(BACKGROUND_TASK);
4894 +	if (ret != 0)
4895 +		bail_out("could not become regular task (huh?)");
4896 +
4897 +	reservation_destroy(gettid(), config.cpu);
4898 +	dealloc_arena(arena, arena_sz);
4899 +	return 0;
4900 +}
4901 diff --git a/bin/mc2thrash2.c b/bin/mc2thrash2.c
4902 new file mode 100644
4903 index 0000000..89af23e
4904 --- /dev/null
4905 +++ b/bin/mc2thrash2.c
4906 @@ -0,0 +1,626 @@
4907 +#include <sys/time.h>
4908 +#include <sys/mman.h>
4909 +
4910 +#include <stdio.h>
4911 +#include <stdlib.h>
4912 +#include <unistd.h>
4913 +#include <time.h>
4914 +#include <string.h>
4915 +#include <assert.h>
4916 +#include <limits.h>
4917 +
4918 +
4919 +#include "litmus.h"
4920 +#include "common.h"
4921 +#include "cache_common.h"
4922 +
4923 +#define PAGE_SIZE (4096)
4924 +
4925 +#define CACHELINE_SIZE 32
4926 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
4927 +//#define ARENA_SIZE_MB 4
4928 +#define ARENA_SIZE_KB 1024
4929 +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
4930 +#define INTS_IN_1KB	(1024 / sizeof(int))
4931 +#define NUM_ARENA_ELEM	((ARENA_SIZE_KB * 1024)/sizeof(cacheline_t))
4932 +
4933 +//static int wss = ARENA_SIZE_MB * 1024;
4934 +static int wss = ARENA_SIZE_KB;
4935 +static int write_cycle = 1; /* every nth cycle is a write; 0 means read-only  */
4936 +static int loops = 10;
4937 +
4938 +static cacheline_t* arena = NULL;
4939 +
4940 +typedef int (*walk_t)(cacheline_t *mem, int wss, int write_cycle);
4941 +typedef cacheline_t* (*walk_start_t)(int wss);
4942 +
4943 +struct walk_method
4944 +{
4945 +	const walk_t walk;
4946 +	const walk_start_t walk_start;
4947 +};
4948 +
4949 +static int sequential_walk(cacheline_t *_mem, int wss, int write_cycle)
4950 +{
4951 +	int sum = 0, i;
4952 +	int* mem = (int*)_mem; /* treat as raw buffer of ints */
4953 +	int num_ints = wss * INTS_IN_1KB;
4954 +
4955 +	if (write_cycle > 0) {
4956 +		for (i = 0; i < num_ints; i++) {
4957 +			if (i % write_cycle == (write_cycle - 1))
4958 +				mem[i]++;
4959 +			else
4960 +				sum += mem[i];
4961 +		}
4962 +	} else {
4963 +		/* sequential access, pure read */
4964 +		for (i = 0; i < num_ints; i++)
4965 +			sum += mem[i];
4966 +	}
4967 +	return sum;
4968 +}
4969 +
4970 +static cacheline_t* sequential_start(int wss)
4971 +{
4972 +	static int pos = 0;
4973 +
4974 +	int num_cachelines = wss * CACHELINES_IN_1KB;
4975 +
4976 +	cacheline_t *mem;
4977 +
4978 +	/* Don't allow re-use between allocations.
4979 +	 * At most half of the arena may be used
4980 +	 * at any one time.
4981 +	 */
4982 +	if (num_cachelines * 2 > NUM_ARENA_ELEM)
4983 +		die("static memory arena too small");
4984 +
4985 +	if (pos + num_cachelines > NUM_ARENA_ELEM) {
4986 +		/* wrap to beginning */
4987 +		mem = arena;
4988 +		pos = num_cachelines;
4989 +	} else {
4990 +		mem = arena + pos;
4991 +		pos += num_cachelines;
4992 +	}
4993 +
4994 +	return mem;
4995 +}
4996 +
4997 +static const struct walk_method sequential_method =
4998 +{
4999 +	.walk = sequential_walk,
5000 +	.walk_start = sequential_start
5001 +};
5002 +
5003 +
5004 +/* Random walk around the arena in cacheline-sized chunks.
5005 +   Cacheline-sized chucks ensures the same utilization of each
5006 +   hit line as sequential read. (Otherwise, our utilization
5007 +   would only be 1/INTS_IN_CACHELINE.) */
5008 +static int random_walk(cacheline_t *mem, int wss, int write_cycle)
5009 +{
5010 +	/* a random cycle among the cache lines was set up by init_arena(). */
5011 +	int sum, i, j, next, which_line;
5012 +
5013 +	int numlines = wss * CACHELINES_IN_1KB;
5014 +
5015 +	sum = 0;
5016 +
5017 +	/* contents of arena is structured s.t. offsets are all
5018 +	   w.r.t. to start of arena, so compute the initial offset */
5019 +	next = mem - arena;
5020 +
5021 +	if (write_cycle == 0) {
5022 +		for (i = 0; i < numlines; i++) {
5023 +			which_line = next;
5024 +			/* every element in the cacheline has the same value */
5025 +			for(j = 0; j < INTS_IN_CACHELINE; j++) {
5026 +				next = arena[which_line].line[j];
5027 +				sum += next;
5028 +			}
5029 +		}
5030 +	}
5031 +	
5032 +	else {
5033 +		int w;
5034 +		for (i = 0, w = 0; i < numlines; i++) {
5035 +			which_line = next;
5036 +			/* count down s.t. next has value of 0th int
5037 +			   when the loop exits */
5038 +			for(j = 0; j < INTS_IN_CACHELINE; j++) {
5039 +				next = arena[which_line].line[j];
5040 +				if((w % write_cycle) != (write_cycle - 1)) {
5041 +					sum += next;
5042 +				}
5043 +				else {
5044 +					/* Write back what we just read. We can't write back a
5045 +					   different value without destroying the walk-cycle, so
5046 +					   cast the write to volatile to ensure the write is
5047 +					   performed. Note: Volatiles are still cached. */
5048 +					((volatile cacheline_t*)arena)[which_line].line[j] = next;
5049 +				}
5050 +			}
5051 +		}
5052 +	}
5053 +	return sum;
5054 +}
5055 +
5056 +static cacheline_t* random_start(int wss)
5057 +{
5058 +	return arena + randrange(0, NUM_ARENA_ELEM);
5059 +}
5060 +
5061 +static const struct walk_method random_method =
5062 +{
5063 +	.walk = random_walk,
5064 +	.walk_start = random_start
5065 +};
5066 +
5067 +static volatile int dont_optimize_me = 0;
5068 +
5069 +static void usage(char *error) {
5070 +	fprintf(stderr, "Error: %s\n", error);
5071 +	fprintf(stderr,
5072 +		"Usage:\n"
5073 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
5074 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
5075 +		"	rt_spin -l\n"
5076 +		"\n"
5077 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
5078 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
5079 +		"              [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
5080 +		"              [-i [start,end]:[start,end]...]\n"
5081 +		"\n"
5082 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n"
5083 +		"CRITICAL SECTION LENGTH is in milliseconds.\n");
5084 +	exit(EXIT_FAILURE);
5085 +}
5086 +
5087 +/*
5088 + * returns the character that made processing stop, newline or EOF
5089 + */
5090 +static int skip_to_next_line(FILE *fstream)
5091 +{
5092 +	int ch;
5093 +	for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
5094 +	return ch;
5095 +}
5096 +
5097 +static void skip_comments(FILE *fstream)
5098 +{
5099 +	int ch;
5100 +	for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
5101 +		skip_to_next_line(fstream);
5102 +	ungetc(ch, fstream);
5103 +}
5104 +
5105 +static void get_exec_times(const char *file, const int column,
5106 +			   int *num_jobs,    double **exec_times)
5107 +{
5108 +	FILE *fstream;
5109 +	int  cur_job, cur_col, ch;
5110 +	*num_jobs = 0;
5111 +
5112 +	fstream = fopen(file, "r");
5113 +	if (!fstream)
5114 +		bail_out("could not open execution time file");
5115 +
5116 +	/* figure out the number of jobs */
5117 +	do {
5118 +		skip_comments(fstream);
5119 +		ch = skip_to_next_line(fstream);
5120 +		if (ch != EOF)
5121 +			++(*num_jobs);
5122 +	} while (ch != EOF);
5123 +
5124 +	if (-1 == fseek(fstream, 0L, SEEK_SET))
5125 +		bail_out("rewinding file failed");
5126 +
5127 +	/* allocate space for exec times */
5128 +	*exec_times = calloc(*num_jobs, sizeof(*exec_times));
5129 +	if (!*exec_times)
5130 +		bail_out("couldn't allocate memory");
5131 +
5132 +	for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
5133 +
5134 +		skip_comments(fstream);
5135 +
5136 +		for (cur_col = 1; cur_col < column; ++cur_col) {
5137 +			/* discard input until we get to the column we want */
5138 +			int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
5139 +		}
5140 +
5141 +		/* get the desired exec. time */
5142 +		if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
5143 +			fprintf(stderr, "invalid execution time near line %d\n",
5144 +					cur_job);
5145 +			exit(EXIT_FAILURE);
5146 +		}
5147 +
5148 +		skip_to_next_line(fstream);
5149 +	}
5150 +
5151 +	assert(cur_job == *num_jobs);
5152 +	fclose(fstream);
5153 +}
5154 +
5155 +static char* progname;
5156 +
5157 +static int loop_once(void)
5158 +{
5159 +	cacheline_t *mem;
5160 +	int temp;
5161 +	
5162 +	mem = random_method.walk_start(wss);
5163 +	temp = random_method.walk(mem, wss, 4);
5164 +	dont_optimize_me = temp;
5165 +}
5166 +
5167 +static int loop_for(double exec_time, double emergency_exit)
5168 +{
5169 +	double last_loop = 0, loop_start;
5170 +	int tmp = 0;
5171 +	int cur_loop = 0;
5172 +
5173 +	double start = cputime();
5174 +	double now = cputime();
5175 +
5176 +	while (now + last_loop < start + exec_time) {
5177 +		loop_start = now;
5178 +		tmp = loop_once();
5179 +		now = cputime();
5180 +		last_loop = now - loop_start;
5181 +		if (emergency_exit && wctime() > emergency_exit) {
5182 +			/* Oops --- this should only be possible if the execution time tracking
5183 +			 * is broken in the LITMUS^RT kernel. */
5184 +			fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
5185 +			fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
5186 +			break;
5187 +		}
5188 +	}
5189 +
5190 +	return tmp;
5191 +}
5192 +
5193 +
5194 +static void debug_delay_loop(void)
5195 +{
5196 +	double start, end, delay;
5197 +
5198 +	while (1) {
5199 +		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
5200 +			start = wctime();
5201 +			loop_for(delay, 0);
5202 +			end = wctime();
5203 +			printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
5204 +			       delay,
5205 +			       end - start,
5206 +			       end - start - delay,
5207 +			       100 * (end - start - delay) / delay);
5208 +		}
5209 +	}
5210 +}
5211 +
5212 +static int job(double exec_time, double program_end, int lock_od, double cs_length)
5213 +{
5214 +	double chunk1, chunk2;
5215 +
5216 +	if (wctime() > program_end)
5217 +		return 0;
5218 +	else {
5219 +		if (lock_od >= 0) {
5220 +			/* simulate critical section somewhere in the middle */
5221 +			chunk1 = drand48() * (exec_time - cs_length);
5222 +			chunk2 = exec_time - cs_length - chunk1;
5223 +
5224 +			/* non-critical section */
5225 +			loop_for(chunk1, program_end + 1);
5226 +
5227 +			/* critical section */
5228 +			litmus_lock(lock_od);
5229 +			loop_for(cs_length, program_end + 1);
5230 +			litmus_unlock(lock_od);
5231 +
5232 +			/* non-critical section */
5233 +			loop_for(chunk2, program_end + 2);
5234 +		} else {
5235 +			loop_for(exec_time, program_end + 1);
5236 +		}
5237 +		sleep_next_period();
5238 +		return 1;
5239 +	}
5240 +}
5241 +
5242 +#define OPTSTR "p:c:wl:veo:f:s:q:X:L:Q:vh:m:i:b:"
5243 +int main(int argc, char** argv)
5244 +{
5245 +	int ret, i;
5246 +	lt_t wcet;
5247 +	lt_t period;
5248 +	lt_t hyperperiod;
5249 +	lt_t budget;
5250 +	double wcet_ms, period_ms, hyperperiod_ms, budget_ms;
5251 +	unsigned int priority = LITMUS_NO_PRIORITY;
5252 +	int migrate = 0;
5253 +	int cluster = 0;
5254 +	int opt;
5255 +	int wait = 0;
5256 +	int test_loop = 0;
5257 +	int column = 1;
5258 +	const char *file = NULL;
5259 +	int want_enforcement = 0;
5260 +	double duration = 0, start = 0;
5261 +	double *exec_times = NULL;
5262 +	double scale = 1.0;
5263 +	task_class_t class = RT_CLASS_HARD;
5264 +	int cur_job = 0, num_jobs = 0;
5265 +	struct rt_task param;
5266 +	struct mc2_task mc2_param;
5267 +	struct reservation_config config;
5268 +	int res_type = PERIODIC_POLLING;
5269 +	int n_str, num_int = 0;
5270 +	size_t arena_sz;
5271 +	int verbose = 0;
5272 +	unsigned int job_no;
5273 +
5274 +	/* locking */
5275 +	int lock_od = -1;
5276 +	int resource_id = 0;
5277 +	const char *lock_namespace = "./rtspin-locks";
5278 +	int protocol = -1;
5279 +	double cs_length = 1; /* millisecond */
5280 +
5281 +	progname = argv[0];
5282 +
5283 +	/* default for reservation */
5284 +	config.id = 0;
5285 +	config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */
5286 +	config.cpu = -1;
5287 +	
5288 +	mc2_param.crit = CRIT_LEVEL_C;
5289 +	
5290 +	hyperperiod_ms = 1000;
5291 +	budget_ms = 10;
5292 +	
5293 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
5294 +		switch (opt) {
5295 +		case 'w':
5296 +			wait = 1;
5297 +			break;
5298 +		case 'p':
5299 +			cluster = atoi(optarg);
5300 +			migrate = 1;
5301 +			config.cpu = cluster;
5302 +			break;
5303 +		case 'q':
5304 +			priority = atoi(optarg);
5305 +			if (!litmus_is_valid_fixed_prio(priority))
5306 +				usage("Invalid priority.");
5307 +			break;
5308 +		case 'c':
5309 +			class = str2class(optarg);
5310 +			if (class == -1)
5311 +				usage("Unknown task class.");
5312 +			break;
5313 +		case 'e':
5314 +			want_enforcement = 1;
5315 +			break;
5316 +		case 'l':
5317 +			loops = atoi(optarg);
5318 +			break;
5319 +		case 'o':
5320 +			column = atoi(optarg);
5321 +			break;
5322 +		case 'f':
5323 +			file = optarg;
5324 +			break;
5325 +		case 's':
5326 +			scale = atof(optarg);
5327 +			break;
5328 +		case 'X':
5329 +			protocol = lock_protocol_for_name(optarg);
5330 +			if (protocol < 0)
5331 +				usage("Unknown locking protocol specified.");
5332 +			break;
5333 +		case 'L':
5334 +			cs_length = atof(optarg);
5335 +			if (cs_length <= 0)
5336 +				usage("Invalid critical section length.");
5337 +			break;
5338 +		case 'Q':
5339 +			resource_id = atoi(optarg);
5340 +			if (resource_id <= 0 && strcmp(optarg, "0"))
5341 +				usage("Invalid resource ID.");
5342 +			break;
5343 +		case 'v':
5344 +			verbose = 1;
5345 +			break;
5346 +		case 'm':
5347 +			mc2_param.crit = atoi(optarg);
5348 +			if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) {
5349 +				res_type = PERIODIC_POLLING;
5350 +			}
5351 +			else
5352 +				usage("Invalid criticality level.");
5353 +			break;
5354 +		case 'h':
5355 +			hyperperiod_ms = atof(optarg);
5356 +			break;
5357 +		case 'b':
5358 +			budget_ms = atof(optarg);
5359 +			break;
5360 +		case 'i':
5361 +			config.priority = atoi(optarg);
5362 +			break;
5363 +		case ':':
5364 +			usage("Argument missing.");
5365 +			break;
5366 +		case '?':
5367 +		default:
5368 +			usage("Bad argument.");
5369 +			break;
5370 +		}
5371 +	}
5372 +
5373 +	if (test_loop) {
5374 +		debug_delay_loop();
5375 +		return 0;
5376 +	}
5377 +
5378 +	srand(getpid());
5379 +
5380 +	if (file) {
5381 +		get_exec_times(file, column, &num_jobs, &exec_times);
5382 +
5383 +		if (argc - optind < 2)
5384 +			usage("Arguments missing.");
5385 +
5386 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
5387 +			/* convert the execution time to seconds */
5388 +			duration += exec_times[cur_job] * 0.001;
5389 +		}
5390 +	} else {
5391 +		/*
5392 +		 * if we're not reading from the CSV file, then we need
5393 +		 * three parameters
5394 +		 */
5395 +		if (argc - optind < 3)
5396 +			usage("Arguments missing.");
5397 +	}
5398 +
5399 +	wcet_ms   = atof(argv[optind + 0]);
5400 +	period_ms = atof(argv[optind + 1]);
5401 +
5402 +	wcet   = ms2ns(wcet_ms);
5403 +	period = ms2ns(period_ms);
5404 +	budget = ms2ns(budget_ms);
5405 +	hyperperiod = ms2ns(hyperperiod_ms);
5406 +	if (wcet <= 0)
5407 +		usage("The worst-case execution time must be a "
5408 +				"positive number.");
5409 +	if (period <= 0)
5410 +		usage("The period must be a positive number.");
5411 +	if (!file && wcet > period) {
5412 +		usage("The worst-case execution time must not "
5413 +				"exceed the period.");
5414 +	}
5415 +
5416 +	if (!file)
5417 +		duration  = atof(argv[optind + 2]);
5418 +	else if (file && num_jobs > 1)
5419 +		duration += period_ms * 0.001 * (num_jobs - 1);
5420 +
5421 +	if (migrate) {
5422 +		ret = be_migrate_to_domain(cluster);
5423 +		if (ret < 0)
5424 +			bail_out("could not migrate to target partition or cluster.");
5425 +	}
5426 +
5427 +	/* reservation config */
5428 +	config.id = gettid();
5429 +	
5430 +	if (hyperperiod%period != 0 ) {
5431 +		;//bail_out("hyperperiod must be multiple of period");
5432 +	}
5433 +	
5434 +	config.polling_params.budget = budget;
5435 +	config.polling_params.period = period;
5436 +	config.polling_params.offset = 0;
5437 +	config.polling_params.relative_deadline = 0;
5438 +	
5439 +	if (config.polling_params.budget > config.polling_params.period) {
5440 +		usage("The budget must not exceed the period.");
5441 +	}
5442 +	
5443 +	/* create a reservation */
5444 +	ret = reservation_create(res_type, &config);
5445 +	if (ret < 0) {
5446 +		bail_out("failed to create reservation.");
5447 +	}
5448 +	
5449 +	init_rt_task_param(&param);
5450 +	param.exec_cost = wcet;
5451 +	param.period = period;
5452 +	param.priority = priority;
5453 +	param.cls = class;
5454 +	param.release_policy = TASK_PERIODIC;
5455 +	param.budget_policy = (want_enforcement) ?
5456 +			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
5457 +	if (migrate) {
5458 +		param.cpu = gettid();
5459 +	}
5460 +	ret = set_rt_task_param(gettid(), &param);
5461 +	if (ret < 0)
5462 +		bail_out("could not setup rt task params");
5463 +	
5464 +	mc2_param.res_id = gettid();
5465 +	ret = set_mc2_task_param(gettid(), &mc2_param);
5466 +	if (ret < 0)
5467 +		bail_out("could not setup mc2 task params");
5468 +	
5469 +	arena_sz = ARENA_SIZE_KB*1024;
5470 +	arena = alloc_arena(arena_sz, 0, 0);
5471 +	init_arena(arena, arena_sz);
5472 +	
5473 +	if (mc2_param.crit == CRIT_LEVEL_C)
5474 +		set_page_color(-1);
5475 +	else
5476 +		set_page_color(config.cpu);	
5477 +	
5478 +	lock_memory();
5479 +		
5480 +	ret = init_litmus();
5481 +	if (ret != 0)
5482 +		bail_out("init_litmus() failed\n");
5483 +
5484 +	start = wctime();
5485 +	ret = task_mode(LITMUS_RT_TASK);
5486 +	if (ret != 0)
5487 +		bail_out("could not become RT task");
5488 +
5489 +	if (protocol >= 0) {
5490 +		lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
5491 +		if (lock_od < 0) {
5492 +			perror("litmus_open_lock");
5493 +			usage("Could not open lock.");
5494 +		}
5495 +	}
5496 +
5497 +
5498 +	if (wait) {
5499 +		ret = wait_for_ts_release();
5500 +		if (ret != 0)
5501 +			bail_out("wait_for_ts_release()");
5502 +		start = wctime();
5503 +	}
5504 +
5505 +	if (file) {
5506 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
5507 +			job(exec_times[cur_job] * 0.001 * scale,
5508 +			    start + duration,
5509 +			    lock_od, cs_length * 0.001);
5510 +		}
5511 +	} else {
5512 +		do {
5513 +			if (verbose) {
5514 +				get_job_no(&job_no);
5515 +				printf("rtspin/%d:%u @ %.4fms\n", gettid(),
5516 +					job_no, (wctime() - start) * 1000);
5517 +			}
5518 +		} while (job(wcet_ms * 0.001 * scale, start + duration,
5519 +			   lock_od, cs_length * 0.001));
5520 +	}
5521 +
5522 +	ret = task_mode(BACKGROUND_TASK);
5523 +	if (ret != 0)
5524 +		bail_out("could not become regular task (huh?)");
5525 +
5526 +	if (file)
5527 +		free(exec_times);
5528 +
5529 +	reservation_destroy(gettid(), config.cpu);
5530 +	dealloc_arena(arena, arena_sz);
5531 +	return 0;
5532 +}
5533 diff --git a/bin/memthrash.c b/bin/memthrash.c
5534 new file mode 100644
5535 index 0000000..5eed3cc
5536 --- /dev/null
5537 +++ b/bin/memthrash.c
5538 @@ -0,0 +1,62 @@
5539 +#include <stdio.h>
5540 +#include <stdlib.h>
5541 +#include <stdint.h>
5542 +#include <string.h>
5543 +
5544 +#include <sys/mman.h>
5545 +#include <sys/resource.h>
5546 +#include <unistd.h>
5547 +#include <sched.h>
5548 +
5549 +#include <time.h>
5550 +
5551 +#include "cache_common.h"
5552 +
5553 +#define NUM_VARS   (8388608*2)
5554 +
5555 +int64_t data[NUM_VARS];
5556 +
5557 +#define OPTSTR "m:"
5558 +int main(int argc, char** argv)
5559 +{
5560 +        int i;
5561 +        int64_t sum;
5562 +
5563 +        int cpu = -1;
5564 +        int opt;
5565 +
5566 +        while ((opt = getopt(argc, argv, OPTSTR)) != -1)
5567 +        {
5568 +                switch(opt)
5569 +                {
5570 +                case 'm':
5571 +                        cpu = atoi(optarg);
5572 +                        break;
5573 +                case ':':
5574 +                case '?':
5575 +                default:
5576 +                        printf("Bad or missing argument.\n");
5577 +                        exit(-1);
5578 +                }
5579 +        }
5580 +
5581 +        srand(time(NULL));
5582 +
5583 +        if(cpu != -1)
5584 +                migrate_to(cpu);
5585 +
5586 +        lock_memory();
5587 +        renice(-20); /* meanest task around */
5588 +
5589 +        while (1) {
5590 +                for (i = 0; i < NUM_VARS; i++)
5591 +                        data[i] = rand();
5592 +                sum = 0;
5593 +                for (i = 0; i < NUM_VARS; i++)
5594 +                        sum += (i % 2 ? 1 : -1) * data[i];
5595 +                for (i = NUM_VARS - 1; i >= 0; i--)
5596 +                        sum += (i % 2 ? -1 : 1) * 100  /  (data[i] ? data[i] : 1);
5597 +        }
5598 +
5599 +        return 0;
5600 +}
5601 \ No newline at end of file
5602 diff --git a/bin/portab.h b/bin/portab.h
5603 new file mode 100644
5604 index 0000000..f0222b1
5605 --- /dev/null
5606 +++ b/bin/portab.h
5607 @@ -0,0 +1,41 @@
5608 +#ifndef __PORTAB_H__
5609 +#define __PORTAB_H__
5610 +
5611 +#define IF_ELSE(a,b,c) ((a) ? (b) : (c))
5612 +
5613 +#if defined(__DSP5600x__)
5614 +
5615 +#define S16BIT int
5616 +#define U16BIT unsigned int
5617 +#define S24BIT int
5618 +#define U24BIT unsigned int
5619 +#define S32BIT long
5620 +#define U32BIT unsigned long
5621 +
5622 +#elif defined(__ADSP2101__) || defined(__TMS320C50__) || \
5623 +      defined(__DSP16xx__)  || defined(__DSP56156__) || \
5624 +      defined(__uPD77016__)
5625 +
5626 +#define S16BIT int
5627 +#define U16BIT unsigned int
5628 +#define S24BIT long
5629 +#define U24BIT unsigned long
5630 +#define S32BIT long
5631 +#define U32BIT unsigned long
5632 +
5633 +#else
5634 +
5635 +#define S16BIT short
5636 +#define U16BIT unsigned short
5637 +#define S24BIT int
5638 +#define U24BIT unsigned int
5639 +#define S32BIT int
5640 +#define U32BIT unsigned int
5641 +/*
5642 +#include "mocad.H"  // use this with ObjectCenter only!
5643 +*/
5644 +#endif
5645 +#endif
5646 +
5647 +
5648 +
5649 diff --git a/bin/resspin.c b/bin/resspin.c
5650 new file mode 100644
5651 index 0000000..8848d8b
5652 --- /dev/null
5653 +++ b/bin/resspin.c
5654 @@ -0,0 +1,576 @@
5655 +#include <sys/time.h>
5656 +#include <sys/mman.h>
5657 +
5658 +#include <stdio.h>
5659 +#include <stdlib.h>
5660 +#include <unistd.h>
5661 +#include <time.h>
5662 +#include <string.h>
5663 +#include <assert.h>
5664 +#include <limits.h>
5665 +
5666 +
5667 +#include "litmus.h"
5668 +#include "common.h"
5669 +#include "cache_common.h"
5670 +
5671 +#define PAGE_SIZE (4096)
5672 +
5673 +#define CACHELINE_SIZE 32
5674 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
5675 +#define ARENA_SIZE_KB 64
5676 +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t))
5677 +#define INTS_IN_1KB	(1024 / sizeof(int))
5678 +#define NUM_ARENA_ELEM	((ARENA_SIZE_KB * 1024)/sizeof(cacheline_t))
5679 +
5680 +//static int wss = ARENA_SIZE_KB;
5681 +static int loops = 10;
5682 +
5683 +static cacheline_t* arena = NULL;
5684 +
5685 +struct timeval tm1, tm2;
5686 +
5687 +typedef int (*walk_t)(cacheline_t *mem, int wss, int write_cycle);
5688 +typedef cacheline_t* (*walk_start_t)(int wss);
5689 +
5690 +struct walk_method
5691 +{
5692 +	const walk_t walk;
5693 +	const walk_start_t walk_start;
5694 +};
5695 +
5696 +static int sequential_walk(cacheline_t *_mem, int wss, int write_cycle)
5697 +{
5698 +	int sum = 0, i;
5699 +	int* mem = (int*)_mem; /* treat as raw buffer of ints */
5700 +	int num_ints = wss * INTS_IN_1KB;
5701 +
5702 +	if (write_cycle > 0) {
5703 +		for (i = 0; i < num_ints; i++) {
5704 +			if (i % write_cycle == (write_cycle - 1))
5705 +				mem[i]++;
5706 +			else
5707 +				sum += mem[i];
5708 +		}
5709 +	} else {
5710 +		/* sequential access, pure read */
5711 +		for (i = 0; i < num_ints; i++)
5712 +			sum += mem[i];
5713 +	}
5714 +	return sum;
5715 +}
5716 +
5717 +static cacheline_t* sequential_start(int wss)
5718 +{
5719 +	static int pos = 0;
5720 +
5721 +	int num_cachelines = wss * CACHELINES_IN_1KB;
5722 +
5723 +	cacheline_t *mem;
5724 +
5725 +	/* Don't allow re-use between allocations.
5726 +	 * At most half of the arena may be used
5727 +	 * at any one time.
5728 +	 */
5729 +	//if (num_cachelines * 2 > NUM_ARENA_ELEM)
5730 +		//die("static memory arena too small");
5731 +
5732 +	if (pos + num_cachelines > ((wss * 1024)/sizeof(cacheline_t))) {
5733 +		/* wrap to beginning */
5734 +		mem = arena;
5735 +		pos = num_cachelines;
5736 +	} else {
5737 +		mem = arena + pos;
5738 +		pos += num_cachelines;
5739 +	}
5740 +
5741 +	return mem;
5742 +}
5743 +
5744 +static const struct walk_method sequential_method =
5745 +{
5746 +	.walk = sequential_walk,
5747 +	.walk_start = sequential_start
5748 +};
5749 +
5750 +
5751 +/* Random walk around the arena in cacheline-sized chunks.
5752 +   Cacheline-sized chucks ensures the same utilization of each
5753 +   hit line as sequential read. (Otherwise, our utilization
5754 +   would only be 1/INTS_IN_CACHELINE.) */
5755 +static int random_walk(cacheline_t *mem, int wss, int write_cycle)
5756 +{
5757 +	/* a random cycle among the cache lines was set up by init_arena(). */
5758 +	int sum, i, j, next, which_line;
5759 +
5760 +	int numlines = wss * CACHELINES_IN_1KB;
5761 +
5762 +	sum = 0;
5763 +
5764 +	/* contents of arena is structured s.t. offsets are all
5765 +	   w.r.t. to start of arena, so compute the initial offset */
5766 +	next = mem - arena;
5767 +
5768 +	if (write_cycle == 0) {
5769 +		for (i = 0; i < numlines; i++) {
5770 +			which_line = next;
5771 +			/* every element in the cacheline has the same value */
5772 +			for(j = 0; j < INTS_IN_CACHELINE; j++) {
5773 +				next = arena[which_line].line[j];
5774 +				sum += next;
5775 +			}
5776 +		}
5777 +	}
5778 +	
5779 +	else {
5780 +		int w;
5781 +		for (i = 0, w = 0; i < numlines; i++) {
5782 +			which_line = next;
5783 +			/* count down s.t. next has value of 0th int
5784 +			   when the loop exits */
5785 +			for(j = 0; j < INTS_IN_CACHELINE; j++) {
5786 +				next = arena[which_line].line[j];
5787 +				if((w % write_cycle) != (write_cycle - 1)) {
5788 +					sum += next;
5789 +				}
5790 +				else {
5791 +					/* Write back what we just read. We can't write back a
5792 +					   different value without destroying the walk-cycle, so
5793 +					   cast the write to volatile to ensure the write is
5794 +					   performed. Note: Volatiles are still cached. */
5795 +					((volatile cacheline_t*)arena)[which_line].line[j] = next;
5796 +				}
5797 +			}
5798 +		}
5799 +	}
5800 +	return sum;
5801 +}
5802 +
5803 +static cacheline_t* random_start(int wss)
5804 +{
5805 +	return arena + randrange(0, ((wss * 1024)/sizeof(cacheline_t)));
5806 +}
5807 +
5808 +static const struct walk_method random_method =
5809 +{
5810 +	.walk = random_walk,
5811 +	.walk_start = random_start
5812 +};
5813 +
5814 +static volatile int dont_optimize_me = 0;
5815 +
5816 +static void usage(char *error) {
5817 +	fprintf(stderr, "Error: %s\n", error);
5818 +	fprintf(stderr,
5819 +		"Usage:\n"
5820 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
5821 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
5822 +		"	rt_spin -l\n"
5823 +		"\n"
5824 +		"COMMON-OPTS = [-w] [-s SCALE]\n"
5825 +		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
5826 +		"              [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]\n"
5827 +		"              [-i [start,end]:[start,end]...]\n"
5828 +		"\n"
5829 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n"
5830 +		"CRITICAL SECTION LENGTH is in milliseconds.\n");
5831 +	exit(EXIT_FAILURE);
5832 +}
5833 +
5834 +/*
5835 + * returns the character that made processing stop, newline or EOF
5836 + */
5837 +static int skip_to_next_line(FILE *fstream)
5838 +{
5839 +	int ch;
5840 +	for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
5841 +	return ch;
5842 +}
5843 +
5844 +static void skip_comments(FILE *fstream)
5845 +{
5846 +	int ch;
5847 +	for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
5848 +		skip_to_next_line(fstream);
5849 +	ungetc(ch, fstream);
5850 +}
5851 +
5852 +static void get_exec_times(const char *file, const int column,
5853 +			   int *num_jobs,    double **exec_times)
5854 +{
5855 +	FILE *fstream;
5856 +	int  cur_job, cur_col, ch;
5857 +	*num_jobs = 0;
5858 +
5859 +	fstream = fopen(file, "r");
5860 +	if (!fstream)
5861 +		bail_out("could not open execution time file");
5862 +
5863 +	/* figure out the number of jobs */
5864 +	do {
5865 +		skip_comments(fstream);
5866 +		ch = skip_to_next_line(fstream);
5867 +		if (ch != EOF)
5868 +			++(*num_jobs);
5869 +	} while (ch != EOF);
5870 +
5871 +	if (-1 == fseek(fstream, 0L, SEEK_SET))
5872 +		bail_out("rewinding file failed");
5873 +
5874 +	/* allocate space for exec times */
5875 +	*exec_times = calloc(*num_jobs, sizeof(*exec_times));
5876 +	if (!*exec_times)
5877 +		bail_out("couldn't allocate memory");
5878 +
5879 +	for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
5880 +
5881 +		skip_comments(fstream);
5882 +
5883 +		for (cur_col = 1; cur_col < column; ++cur_col) {
5884 +			/* discard input until we get to the column we want */
5885 +			int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
5886 +		}
5887 +
5888 +		/* get the desired exec. time */
5889 +		if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
5890 +			fprintf(stderr, "invalid execution time near line %d\n",
5891 +					cur_job);
5892 +			exit(EXIT_FAILURE);
5893 +		}
5894 +
5895 +		skip_to_next_line(fstream);
5896 +	}
5897 +
5898 +	assert(cur_job == *num_jobs);
5899 +	fclose(fstream);
5900 +}
5901 +
5902 +static char* progname;
5903 +
5904 +static int loop_once(int wss)
5905 +{
5906 +	cacheline_t *mem;
5907 +	int temp;
5908 +	
5909 +	//mem = random_method.walk_start(wss);
5910 +	//temp = random_method.walk(mem, wss, 0);
5911 +	mem = sequential_method.walk_start(wss);
5912 +	temp = sequential_method.walk(mem, wss, 0);
5913 +	dont_optimize_me = temp;
5914 +	
5915 +	return dont_optimize_me;
5916 +}
5917 +
5918 +static int loop_for(int wss, double exec_time, double emergency_exit)
5919 +{
5920 +	double last_loop = 0, loop_start;
5921 +	int tmp = 0;
5922 +	int cur_loop = 0;
5923 +
5924 +	double start = cputime();
5925 +	double now = cputime();
5926 +
5927 +	//while (now + last_loop < start + exec_time) {
5928 +	while(cur_loop++ < loops) {
5929 +		loop_start = now;
5930 +		tmp = loop_once(wss);
5931 +		now = cputime();
5932 +		last_loop = now - loop_start;
5933 +		if (emergency_exit && wctime() > emergency_exit) {
5934 +			/* Oops --- this should only be possible if the execution time tracking
5935 +			 * is broken in the LITMUS^RT kernel. */
5936 +			fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
5937 +			fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
5938 +			break;
5939 +		}
5940 +	}
5941 +
5942 +	return tmp;
5943 +}
5944 +
5945 +
5946 +static void debug_delay_loop(int wss)
5947 +{
5948 +	double start, end, delay;
5949 +
5950 +	while (1) {
5951 +		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
5952 +			start = wctime();
5953 +			loop_for(wss, delay, 0);
5954 +			end = wctime();
5955 +			printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
5956 +			       delay,
5957 +			       end - start,
5958 +			       end - start - delay,
5959 +			       100 * (end - start - delay) / delay);
5960 +		}
5961 +	}
5962 +}
5963 +
5964 +static int job(int wss, double exec_time, double program_end, int lock_od, double cs_length)
5965 +{
5966 +	double chunk1, chunk2;
5967 +
5968 +	if (wctime() > program_end)
5969 +		return 0;
5970 +	else {
5971 +		if (lock_od >= 0) {
5972 +			/* simulate critical section somewhere in the middle */
5973 +			chunk1 = drand48() * (exec_time - cs_length);
5974 +			chunk2 = exec_time - cs_length - chunk1;
5975 +
5976 +			/* non-critical section */
5977 +			loop_for(wss, chunk1, program_end + 1);
5978 +
5979 +			/* critical section */
5980 +			litmus_lock(lock_od);
5981 +			loop_for(wss, cs_length, program_end + 1);
5982 +			litmus_unlock(lock_od);
5983 +
5984 +			/* non-critical section */
5985 +			loop_for(wss, chunk2, program_end + 2);
5986 +		} else {
5987 +			register unsigned long t;
5988 +			register unsigned long overhead = get_cyclecount();
5989 +			overhead = get_cyclecount() - overhead;
5990 +			
5991 +			//gettimeofday(&tm1, NULL);
5992 +			t = get_cyclecount();
5993 +			loop_for(wss, exec_time, program_end + 1);
5994 +			t = get_cyclecount() - t;
5995 +			printf("%ld cycles (%ld overhead))\n", t, overhead);
5996 +			//gettimeofday(&tm2, NULL);
5997 +			//printf("%ld\n", ((tm2.tv_sec * 1000000 + tm2.tv_usec) - (tm1.tv_sec * 1000000 + tm1.tv_usec)));
5998 +		}
5999 +		sleep_next_period();
6000 +		return 1;
6001 +	}
6002 +}
6003 +
6004 +#define OPTSTR "p:c:wl:veo:f:s:q:X:L:Q:vh:k:"
6005 +int main(int argc, char** argv)
6006 +{
6007 +	int ret, i;
6008 +	lt_t wcet;
6009 +	lt_t period;
6010 +	double wcet_ms, period_ms;
6011 +	unsigned int priority = LITMUS_NO_PRIORITY;
6012 +	int migrate = 0;
6013 +	int cluster = 0;
6014 +	int opt;
6015 +	int wait = 0;
6016 +	int test_loop = 0;
6017 +	int column = 1;
6018 +	const char *file = NULL;
6019 +	int want_enforcement = 0;
6020 +	double duration = 0, start = 0;
6021 +	double *exec_times = NULL;
6022 +	double scale = 1.0;
6023 +	task_class_t class = RT_CLASS_HARD;
6024 +	int cur_job = 0, num_jobs = 0;
6025 +	struct rt_task param;
6026 +	int n_str, num_int = 0;
6027 +	size_t arena_sz;
6028 +	int verbose = 0;
6029 +	unsigned int job_no;
6030 +	int wss;
6031 +
6032 +	/* locking */
6033 +	int lock_od = -1;
6034 +	int resource_id = 0;
6035 +	const char *lock_namespace = "./rtspin-locks";
6036 +	int protocol = -1;
6037 +	double cs_length = 1; /* millisecond */
6038 +
6039 +	progname = argv[0];
6040 +
6041 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
6042 +		switch (opt) {
6043 +		case 'w':
6044 +			wait = 1;
6045 +			break;
6046 +		case 'p':
6047 +			cluster = atoi(optarg);
6048 +			migrate = 1;
6049 +			break;
6050 +		case 'q':
6051 +			priority = atoi(optarg);
6052 +			if (!litmus_is_valid_fixed_prio(priority))
6053 +				usage("Invalid priority.");
6054 +			break;
6055 +		case 'c':
6056 +			class = str2class(optarg);
6057 +			if (class == -1)
6058 +				usage("Unknown task class.");
6059 +			break;
6060 +		case 'e':
6061 +			want_enforcement = 1;
6062 +			break;
6063 +		case 'l':
6064 +			loops = atoi(optarg);
6065 +			break;
6066 +		case 'k':
6067 +			wss = atoi(optarg);
6068 +			break;
6069 +		case 'o':
6070 +			column = atoi(optarg);
6071 +			break;
6072 +		case 'f':
6073 +			file = optarg;
6074 +			break;
6075 +		case 's':
6076 +			scale = atof(optarg);
6077 +			break;
6078 +		case 'X':
6079 +			protocol = lock_protocol_for_name(optarg);
6080 +			if (protocol < 0)
6081 +				usage("Unknown locking protocol specified.");
6082 +			break;
6083 +		case 'L':
6084 +			cs_length = atof(optarg);
6085 +			if (cs_length <= 0)
6086 +				usage("Invalid critical section length.");
6087 +			break;
6088 +		case 'Q':
6089 +			resource_id = atoi(optarg);
6090 +			if (resource_id <= 0 && strcmp(optarg, "0"))
6091 +				usage("Invalid resource ID.");
6092 +			break;
6093 +		case 'v':
6094 +			verbose = 1;
6095 +			break;
6096 +		case ':':
6097 +			usage("Argument missing.");
6098 +			break;
6099 +		case '?':
6100 +		default:
6101 +			usage("Bad argument.");
6102 +			break;
6103 +		}
6104 +	}
6105 +
6106 +	if (test_loop) {
6107 +		debug_delay_loop(wss);
6108 +		return 0;
6109 +	}
6110 +
6111 +	srand(getpid());
6112 +
6113 +	if (file) {
6114 +		get_exec_times(file, column, &num_jobs, &exec_times);
6115 +
6116 +		if (argc - optind < 2)
6117 +			usage("Arguments missing.");
6118 +
6119 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
6120 +			/* convert the execution time to seconds */
6121 +			duration += exec_times[cur_job] * 0.001;
6122 +		}
6123 +	} else {
6124 +		/*
6125 +		 * if we're not reading from the CSV file, then we need
6126 +		 * three parameters
6127 +		 */
6128 +		if (argc - optind < 3)
6129 +			usage("Arguments missing.");
6130 +	}
6131 +
6132 +	wcet_ms   = atof(argv[optind + 0]);
6133 +	period_ms = atof(argv[optind + 1]);
6134 +
6135 +	wcet   = ms2ns(wcet_ms);
6136 +	period = ms2ns(period_ms);
6137 +	if (wcet <= 0)
6138 +		usage("The worst-case execution time must be a "
6139 +				"positive number.");
6140 +	if (period <= 0)
6141 +		usage("The period must be a positive number.");
6142 +	if (!file && wcet > period) {
6143 +		usage("The worst-case execution time must not "
6144 +				"exceed the period.");
6145 +	}
6146 +
6147 +	if (!file)
6148 +		duration  = atof(argv[optind + 2]);
6149 +	else if (file && num_jobs > 1)
6150 +		duration += period_ms * 0.001 * (num_jobs - 1);
6151 +
6152 +	if (migrate) {
6153 +		ret = be_migrate_to_domain(cluster);
6154 +		if (ret < 0)
6155 +			bail_out("could not migrate to target partition or cluster.");
6156 +	}
6157 +	
6158 +	init_rt_task_param(&param);
6159 +	param.exec_cost = wcet;
6160 +	param.period = period;
6161 +	param.priority = priority;
6162 +	param.cls = class;
6163 +	param.budget_policy = (want_enforcement) ?
6164 +			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
6165 +	if (migrate) {
6166 +		param.cpu = domain_to_first_cpu(cluster);
6167 +	}
6168 +	ret = set_rt_task_param(gettid(), &param);
6169 +	if (ret < 0)
6170 +		bail_out("could not setup rt task params");
6171 +	
6172 +	
6173 +	arena_sz = wss*1024;
6174 +	arena = alloc_arena(arena_sz, 0, 0);
6175 +	init_arena(arena, arena_sz);
6176 +	
6177 +	lock_memory();
6178 +	
6179 +	ret = init_litmus();
6180 +	if (ret != 0)
6181 +		bail_out("init_litmus() failed\n");
6182 +
6183 +	start = wctime();
6184 +	ret = task_mode(LITMUS_RT_TASK);
6185 +	if (ret != 0)
6186 +		bail_out("could not become RT task");
6187 +
6188 +	if (protocol >= 0) {
6189 +		lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster);
6190 +		if (lock_od < 0) {
6191 +			perror("litmus_open_lock");
6192 +			usage("Could not open lock.");
6193 +		}
6194 +	}
6195 +
6196 +
6197 +	if (wait) {
6198 +		ret = wait_for_ts_release();
6199 +		if (ret != 0)
6200 +			bail_out("wait_for_ts_release()");
6201 +		start = wctime();
6202 +	}
6203 +
6204 +	if (file) {
6205 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
6206 +			job(wss, exec_times[cur_job] * 0.001 * scale,
6207 +			    start + duration,
6208 +			    lock_od, cs_length * 0.001);
6209 +		}
6210 +	} else {
6211 +		do {
6212 +			if (verbose) {
6213 +				get_job_no(&job_no);
6214 +				printf("rtspin/%d:%u @ %.4fms\n", gettid(),
6215 +					job_no, (wctime() - start) * 1000);
6216 +			}
6217 +		} while (job(wss, wcet_ms * 0.001 * scale, start + duration,
6218 +			   lock_od, cs_length * 0.001));
6219 +	}
6220 +
6221 +	ret = task_mode(BACKGROUND_TASK);
6222 +	if (ret != 0)
6223 +		bail_out("could not become regular task (huh?)");
6224 +
6225 +	if (file)
6226 +		free(exec_times);
6227 +
6228 +	dealloc_arena(arena, arena_sz);
6229 +	return 0;
6230 +}
6231 diff --git a/bin/rtspin.c b/bin/rtspin.c
6232 index ea7f192..fd57c45 100644
6233 --- a/bin/rtspin.c
6234 +++ b/bin/rtspin.c
6235 @@ -6,7 +6,7 @@
6236  #include <time.h>
6237  #include <string.h>
6238  #include <assert.h>
6239 -
6240 +#include <limits.h>
6241  
6242  #include "litmus.h"
6243  #include "common.h"
6244 @@ -191,7 +191,7 @@ int main(int argc, char** argv)
6245  	lt_t wcet;
6246  	lt_t period;
6247  	double wcet_ms, period_ms;
6248 -	unsigned int priority = LITMUS_LOWEST_PRIORITY;
6249 +	unsigned int priority = LITMUS_NO_PRIORITY;
6250  	int migrate = 0;
6251  	int cluster = 0;
6252  	int reservation = -1;
6253 diff --git a/include/cache_common.h b/include/cache_common.h
6254 new file mode 100644
6255 index 0000000..7e9646c
6256 --- /dev/null
6257 +++ b/include/cache_common.h
6258 @@ -0,0 +1,213 @@
6259 +#ifndef __CACHE_COMMON_H__
6260 +#define __CACHE_COMMON_H__
6261 +
6262 +#include <stdio.h>
6263 +#include <stdlib.h>
6264 +#include <time.h>
6265 +#include <string.h>
6266 +#include <assert.h>
6267 +
6268 +#include <signal.h>
6269 +#include <sys/mman.h>
6270 +#include <sys/types.h>
6271 +#include <sys/stat.h>
6272 +#include <fcntl.h>
6273 +#include <unistd.h>
6274 +
6275 +#include <sys/io.h>
6276 +#include <sys/utsname.h>
6277 +
6278 +#include <sched.h>
6279 +#include <sys/time.h>
6280 +#include <sys/resource.h>
6281 +
6282 +#include "litmus.h"
6283 +#include "asm/cycles.h"
6284 +
6285 +#if defined(__i386__) || defined(__x86_64__)
6286 +#include "asm/irq.h"
6287 +#endif
6288 +
6289 +
6290 +#define UNCACHE_DEV "/dev/litmus/uncache"
6291 +
6292 +static void die(char *error)
6293 +{
6294 +    fprintf(stderr, "Error: %s (errno: %m)\n",
6295 +        error);
6296 +    exit(1);
6297 +}
6298 +
6299 +static int migrate_to(int cpu)
6300 +{
6301 +    int ret;
6302 +
6303 +    static __thread cpu_set_t* cpu_set = NULL;
6304 +    static __thread size_t cpu_set_sz;
6305 +    static __thread int num_cpus;
6306 +    if(!cpu_set)
6307 +    {
6308 +        num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
6309 +        cpu_set = CPU_ALLOC(num_cpus);
6310 +        cpu_set_sz = CPU_ALLOC_SIZE(num_cpus);
6311 +    }
6312 +
6313 +    CPU_ZERO_S(cpu_set_sz, cpu_set);
6314 +    CPU_SET_S(cpu, cpu_set_sz, cpu_set);
6315 +    ret = sched_setaffinity(0 /* self */, cpu_set_sz, cpu_set);
6316 +    return ret;
6317 +}
6318 +
6319 +static int check_migrations(int num_cpus)
6320 +{
6321 +    int cpu, err;
6322 +
6323 +    for (cpu = 0; cpu < num_cpus; cpu++) {
6324 +        err = migrate_to(cpu);
6325 +        if (err != 0) {
6326 +            fprintf(stderr, "Migration to CPU %d failed: %m.\n",
6327 +                cpu + 1);
6328 +            return 1;
6329 +        }
6330 +    }
6331 +    return 0;
6332 +}
6333 +
6334 +static int become_posix_realtime_task(int prio)
6335 +{
6336 +    struct sched_param param;
6337 +    memset(&param, 0, sizeof(param));
6338 +    param.sched_priority = prio;
6339 +    return sched_setscheduler(0 /* self */, SCHED_FIFO, &param);
6340 +}
6341 +
6342 +static int renice(int nice_val)
6343 +{
6344 +        return setpriority(PRIO_PROCESS, 0 /* self */, nice_val);
6345 +}
6346 +
6347 +static int lock_memory(void)
6348 +{
6349 +    return mlockall(MCL_CURRENT | MCL_FUTURE);
6350 +}
6351 +
6352 +/* define CACHELINE_SIZE if not provided by compiler args */
6353 +#ifndef CACHELINE_SIZE
6354 +#if defined(__i386__) || defined(__x86_64__)
6355 +/* recent intel cpus */
6356 +#define CACHELINE_SIZE 64
6357 +#elif defined(__arm__)
6358 +/* at least with Cortex-A9 cpus ("8 words") */
6359 +#define CACHELINE_SIZE 32
6360 +#else
6361 +#error "Could not determine cacheline size!"
6362 +#endif
6363 +#endif
6364 +
6365 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int))
6366 +typedef struct cacheline
6367 +{
6368 +        int line[INTS_IN_CACHELINE];
6369 +} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t;
6370 +
6371 +static cacheline_t* alloc_arena(size_t size, int use_huge_pages, int use_uncache_pages)
6372 +{
6373 +    int flags = MAP_PRIVATE | MAP_POPULATE;
6374 +    cacheline_t* arena = NULL;
6375 +    int fd;
6376 +
6377 +    if(use_huge_pages)
6378 +        flags |= MAP_HUGETLB;
6379 +
6380 +	if(use_uncache_pages) {
6381 +			fd = open(UNCACHE_DEV, O_RDWR);
6382 +			if (fd == -1)
6383 +					die("Failed to open uncache device. Are you running the LITMUS^RT kernel?");
6384 +	}
6385 +	else {
6386 +			fd = -1;
6387 +			flags |= MAP_ANONYMOUS;
6388 +	}
6389 +
6390 +    arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0);
6391 +	
6392 +    if(use_uncache_pages)
6393 +		close(fd);
6394 +
6395 +    assert(arena);
6396 +
6397 +        return arena;
6398 +}
6399 +
6400 +static void dealloc_arena(cacheline_t* arena, size_t size)
6401 +{
6402 +		int ret = munmap((void*)arena, size);
6403 +        if(ret != 0)
6404 +                die("munmap() error");
6405 +}
6406 +
6407 +static int randrange(int min, int max)
6408 +{
6409 +        /* generate a random number on the range [min, max) w/o skew */
6410 +        int limit = max - min;
6411 +        int devisor = RAND_MAX/limit;
6412 +        int retval;
6413 +
6414 +        do {
6415 +                retval = rand() / devisor;
6416 +        } while(retval == limit);
6417 +        retval += min;
6418 +
6419 +        return retval;
6420 +}
6421 +
6422 +static void init_arena(cacheline_t* arena, size_t size)
6423 +{
6424 +    int i;
6425 +        size_t num_arena_elem = size / sizeof(cacheline_t);
6426 +
6427 +        /* Generate a cycle among the cache lines using Sattolo's algorithm.
6428 +           Every int in the cache line points to the same cache line.
6429 +           Note: Sequential walk doesn't care about these values. */
6430 +        for (i = 0; i < num_arena_elem; i++) {
6431 +                int j;
6432 +                for(j = 0; j < INTS_IN_CACHELINE; ++j)
6433 +                        arena[i].line[j] = i;
6434 +        }
6435 +        while(1 < i--) {
6436 +                int j = randrange(0, i);
6437 +                cacheline_t temp = arena[j];
6438 +                arena[j] = arena[i];
6439 +                arena[i] = temp;
6440 +        }
6441 +}
6442 +
6443 +static void sleep_us(int microseconds)
6444 +{
6445 +    struct timespec delay;
6446 +
6447 +    delay.tv_sec = 0;
6448 +    delay.tv_nsec = microseconds * 1000;
6449 +    if (nanosleep(&delay, NULL) != 0)
6450 +        die("sleep failed");
6451 +}
6452 +
6453 +static int completed(int nSamples, int* history, int nCategories)
6454 +{
6455 +        int i;
6456 +        for(i = 0; i < nCategories; ++i)
6457 +                if(history[i] < nSamples)
6458 +                        return 0;
6459 +        return 1;
6460 +}
6461 +
6462 +inline unsigned long get_cyclecount (void)
6463 +{
6464 +	unsigned long value;
6465 +	// Read CCNT Register
6466 +	asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
6467 +	return value;
6468 +}
6469 +
6470 +
6471 +#endif
6472 \ No newline at end of file
6473 diff --git a/include/litmus.h b/include/litmus.h
6474 index b90a83d..b8e32a4 100644
6475 --- a/include/litmus.h
6476 +++ b/include/litmus.h
6477 @@ -424,6 +424,8 @@ int reservation_destroy(unsigned int reservation_id, int cpu);
6478  
6479  int set_mc2_task_param(pid_t pid, struct mc2_task* param);
6480  
6481 +int set_page_color(int cpu);
6482 +
6483  #ifdef __cplusplus
6484  }
6485  #endif
6486 diff --git a/mc2spin b/mc2spin
6487 deleted file mode 100755
6488 index 00b20c0223e92547cde52d2546b7ddbcb349c1a1..0000000000000000000000000000000000000000
6489 GIT binary patch
6490 literal 0
6491 HcmV?d00001
6492 
6493 literal 102692
6494 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
7318 RC~&S^73oPH3wvb1{udehT~z=8
7319 
7320 diff --git a/src/syscalls.c b/src/syscalls.c
7321 index b07d135..a58f55b 100644
7322 --- a/src/syscalls.c
7323 +++ b/src/syscalls.c
7324 @@ -100,4 +100,9 @@ int reservation_destroy(unsigned int reservation_id, int cpu)
7325  int set_mc2_task_param(pid_t pid, struct mc2_task *param)
7326  {
7327  	return syscall(__NR_set_mc2_task_param, pid, param);
7328 -}
7329 \ No newline at end of file
7330 +}
7331 +
7332 +int set_page_color(int cpu)
7333 +{
7334 +	return syscall(__NR_set_page_color, cpu);
7335 +}
7336 -- 
7337 1.9.1

Attached Files

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

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