Attachment 'MC2_liblitmus_ipdps15.patch'

Download

   1 diff --git a/Makefile b/Makefile
   2 index db94ffb..a81b010 100644
   3 --- a/Makefile
   4 +++ b/Makefile
   5 @@ -12,14 +12,15 @@ host-arch := $(shell uname -m | \
   6  ARCH ?= ${host-arch}
   7  
   8  # LITMUS_KERNEL -- where to find the litmus kernel?
   9 -LITMUS_KERNEL ?= ../litmus2010
  10 +LITMUS_KERNEL ?= ../litmus-rt
  11  
  12  
  13  # ##############################################################################
  14  # Internal configuration.
  15  
  16  # compiler flags
  17 -flags-debug    = -Wall -Werror -g -Wdeclaration-after-statement
  18 +flags-debug    = -Wall -g -Wdeclaration-after-statement
  19 +#flags-debug    = -Wall -Werror -g -Wdeclaration-after-statement
  20  flags-api      = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE
  21  
  22  # architecture-specific flags
  23 @@ -70,8 +71,8 @@ AR  := ${CROSS_COMPILE}${AR}
  24  # Targets
  25  
  26  all     = lib ${rt-apps}
  27 -rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
  28 -	  base_mt_task runtests
  29 +rt-apps = cycles base_task rt_launch rtspin rtspinovr rtspin.ovh rtspin.beta \
  30 +		release_ts measure_syscall base_mt_task runtests monitor cycles_test
  31  
  32  .PHONY: all lib clean dump-config TAGS tags cscope help
  33  
  34 @@ -154,7 +155,7 @@ arch/${include-${ARCH}}/include/asm/%.h: \
  35  	cp $< $@
  36  
  37  litmus-headers = include/litmus/rt_param.h include/litmus/unistd_32.h \
  38 -	include/litmus/unistd_64.h
  39 +	include/litmus/unistd_64.h include/litmus/sched_mc.h
  40  
  41  unistd-headers = \
  42    $(foreach file,${unistd-${ARCH}},arch/${include-${ARCH}}/include/asm/$(file))
  43 @@ -211,11 +212,26 @@ obj-rt_launch = rt_launch.o common.o
  44  obj-rtspin = rtspin.o common.o
  45  lib-rtspin = -lrt
  46  
  47 +obj-rtspinovr = rtspinovr.o common.o
  48 +lib-rtspinovr = -lrt
  49 +
  50 +obj-rtspin.ovh = rtspin.ovh.o common.o
  51 +lib-rtspin.ovh = -lrt
  52 +
  53 +obj-rtspin.beta = rtspin.beta.o common.o
  54 +lib-rtspin.beta = -lrt $(shell gsl-config --libs)
  55 +
  56  obj-release_ts = release_ts.o
  57  
  58  obj-measure_syscall = null_call.o
  59  lib-measure_syscall = -lm
  60  
  61 +obj-monitor = monitor.o common.o
  62 +lib-monitor = -lrt
  63 +
  64 +obj-cycles_test = cycles_test.o common.o
  65 +lib-cycles_test = -lrt
  66 +
  67  # ##############################################################################
  68  # Build everything that depends on liblitmus.
  69  
  70 diff --git a/bin/monitor.c b/bin/monitor.c
  71 new file mode 100644
  72 index 0000000..9c72397
  73 --- /dev/null
  74 +++ b/bin/monitor.c
  75 @@ -0,0 +1,471 @@
  76 +#include <sys/time.h>
  77 +
  78 +#include <stdio.h>
  79 +#include <stdlib.h>
  80 +#include <unistd.h>
  81 +#include <time.h>
  82 +#include <assert.h>
  83 +#include <strings.h>
  84 +#include <signal.h>
  85 +#include <memory.h>
  86 +
  87 +#include "litmus.h"
  88 +#include "common.h"
  89 +#include "linkedlist.h"
  90 +
  91 +#include <litmus/sched_mc.h>
  92 +#define CLOCK_PER_MS 2129704
  93 +
  94 +struct task_info {
  95 +    int id;
  96 +    double relative_pp;
  97 +    double tolerance;
  98 +    int period;
  99 +};
 100 +
 101 +pid_t task_pid[100];
 102 +struct task_info task_set[100];
 103 +struct report_data report[2048];
 104 +static int recovery_mode = 0;
 105 +LinkedList pend_now;
 106 +LinkedList pend_idle_cand;
 107 +unsigned long long seq = 0;
 108 +lt_t idle_cand = 0;
 109 +int speed_num = 5, speed_denom = 10;
 110 +int current_num, current_denom, num_jobs, num_c_jobs = 0;
 111 +cycles_t time_start, time_end;
 112 +lt_t t_start, t_end;
 113 +int task_mapped = 0;
 114 +int map_idx = 0;
 115 +int num_transition = 0;
 116 +cycles_t total_cycle = 0;
 117 +double min_speed = 1, current_speed = 1.0;
 118 +
 119 +int get_task_value(pid_t pid)
 120 +{
 121 +    int i = 0;
 122 +    for (i=0; i<num_c_jobs;i++)
 123 +    {
 124 +        if (task_pid[i] == pid) {
 125 +            return i;
 126 +        }
 127 +    }
 128 +    printf("Not a registered task\n");
 129 +    return 0;
 130 +}
 131 +
 132 +static void usage(char *error) {
 133 +	fprintf(stderr, "Error: %s\n", error);
 134 +	fprintf(stderr,
 135 +		"Usage:\n"
 136 +		"	monitor [COMMON-OPTS] WCET PERIOD DURATION\n"
 137 +		"	monitor [COMMON-OPTS] -f TASK_INFO_FILE [-o COLUMN] WCET PERIOD\n"
 138 +		"\n"
 139 +		"COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n"
 140 +		"              [-r CRITICALITY = [a|b|c|d]] [-i MC-LVL-A-ID]\n"
 141 +		"\n"
 142 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n");
 143 +	exit(EXIT_FAILURE);
 144 +}
 145 +
 146 +/*
 147 + * returns the character that made processing stop, newline or EOF
 148 + */
 149 +static int skip_to_next_line(FILE *fstream)
 150 +{
 151 +	int ch;
 152 +	for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
 153 +	return ch;
 154 +}
 155 +
 156 +static void skip_comments(FILE *fstream)
 157 +{
 158 +	int ch;
 159 +	for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
 160 +		skip_to_next_line(fstream);
 161 +	ungetc(ch, fstream);
 162 +}
 163 +
 164 +void get_task_info(const char *file)
 165 +{
 166 +	FILE *fstream;
 167 +	int  cur_job, ch;
 168 +    int temp1, temp2, id, crit;
 169 +    float pp, tol;
 170 +    float temp3, temp4;
 171 +    
 172 +	num_jobs = 0;
 173 +
 174 +    fstream = fopen(file, "r");
 175 +	if (!fstream)
 176 +		bail_out("could not open execution time file");
 177 +
 178 +	/* figure out the number of jobs */
 179 +	do {
 180 +		skip_comments(fstream);
 181 +		ch = skip_to_next_line(fstream);
 182 +		if (ch != EOF)
 183 +			++(num_jobs);
 184 +	} while (ch != EOF);
 185 +	
 186 +	if (-1 == fseek(fstream, 0L, SEEK_SET))
 187 +		bail_out("rewinding file failed");
 188 +    ch = skip_to_next_line(fstream);
 189 +	/* allocate space for exec times */
 190 +	for (cur_job = 0; cur_job < num_jobs && !feof(fstream); ++cur_job) {
 191 +		skip_comments(fstream);
 192 +
 193 +        fscanf(fstream, "%d %d %d %f %f %d %f %f", &id, &temp1, &temp2, &pp, &tol, &crit, &temp3, &temp4);
 194 +        
 195 +        if (crit == 2) {
 196 +            task_set[num_c_jobs].id = id;
 197 +            task_set[num_c_jobs].relative_pp = (double)pp;
 198 +            task_set[num_c_jobs].tolerance = (double)tol;
 199 +            task_set[num_c_jobs].period = (int)temp2;
 200 +            num_c_jobs++;
 201 +            crit = 0;
 202 +        }
 203 +
 204 +		skip_to_next_line(fstream);
 205 +	}
 206 +
 207 +	assert(cur_job == num_jobs);
 208 +	fclose(fstream);
 209 +}
 210 +
 211 +static char* progname;
 212 +
 213 +static int job(double exec_time, double program_end)
 214 +{
 215 +	if (wctime() > program_end)
 216 +    {
 217 +        return 0;
 218 +    }
 219 +	else {
 220 +        sleep_next_period();
 221 +		return 1;
 222 +	}
 223 +}
 224 +
 225 +enum crit_level str2crit(const char* str)
 226 +{
 227 +	if (0 == strncasecmp("a", str, 1))
 228 +		return CRIT_LEVEL_A;
 229 +	else if (0 == strncasecmp("b", str, 1))
 230 +		return CRIT_LEVEL_B;
 231 +	else if (0 == strncasecmp("c", str, 1))
 232 +		return CRIT_LEVEL_C;
 233 +	/* failure */
 234 +	return NUM_CRIT_LEVELS;
 235 +}
 236 +inline void print_job(struct report_data data)
 237 +{
 238 +    printf("[%llu] %d/%d release: %llu, pp: %llu, comp: %llu, queue: %d\n", data.seq, data.pid, data.job_no, data.release_time, data.priority_point, data.now, data.rq_empty);
 239 +}
 240 +
 241 +void init_recovery(lt_t comp_time, int queue_empty)
 242 +{
 243 +    recovery_mode = 1;
 244 +    if (queue_empty == 1) {
 245 +        idle_cand = comp_time;
 246 +        list_copy(&pend_idle_cand, &pend_now);
 247 +    }
 248 +    else {
 249 +        idle_cand = 0;
 250 +        pend_idle_cand.removeAll(&pend_idle_cand);
 251 +    }
 252 +}
 253 +
 254 +void handle_miss_adaptive(struct report_data job, double yi, double ksi)
 255 +{
 256 +    double new_speed;
 257 +    double a_factor = (double)speed_num/10.0;
 258 +    double a,b;
 259 +    
 260 +    if (recovery_mode == 0) {
 261 +        current_speed = 1.0;
 262 +        init_recovery(job.now, job.rq_empty);
 263 +    }
 264 +    a = (double)(a_factor*(yi+ksi));
 265 +    b = (double)((double)(job.now-job.release_time)/CLOCK_PER_MS);
 266 +    new_speed = a/b;
 267 +    if ( new_speed < current_speed)
 268 +    {
 269 +        current_num = (int)a;
 270 +        current_denom = (int)b;
 271 +        change_speed(current_num, current_denom);
 272 +        null_call(&time_start);
 273 +        current_speed = new_speed;
 274 +        min_speed = new_speed;
 275 +    }
 276 +}
 277 +
 278 +void handle_miss(struct report_data job)
 279 +{
 280 +    if (recovery_mode == 0) {
 281 +        change_speed(speed_num, speed_denom);
 282 +        null_call(&time_start);
 283 +        init_recovery(job.now, job.rq_empty);
 284 +    }
 285 +}
 286 +        
 287 +void on_job_complete(struct report_data job)
 288 +{ 
 289 +    double ksi, yi;
 290 +    
 291 +    //print_job(job);
 292 +    pend_now.remove(&pend_now, job);
 293 +    
 294 +    ksi = task_set[get_task_value(job.pid)].tolerance * 1.0;
 295 +    yi = task_set[get_task_value(job.pid)].relative_pp;
 296 +    if (((double)(job.now - job.priority_point))/((double)CLOCK_PER_MS) > ksi && job.priority_point != 0) {
 297 +        //handle_miss(job);
 298 +        handle_miss_adaptive(job, ksi, yi);
 299 +    }
 300 +    if ((recovery_mode == 1) && (idle_cand != 0)) {
 301 +        if (((double)(job.now - job.priority_point))/((double)CLOCK_PER_MS) > ksi) {
 302 +            idle_cand = 0;
 303 +            pend_idle_cand.removeAll(&pend_idle_cand);
 304 +        }
 305 +        else {
 306 +            pend_idle_cand.remove(&pend_idle_cand, job);
 307 +        }
 308 +    }
 309 +    
 310 +    if ((recovery_mode == 1) && (idle_cand == 0) && (job.rq_empty == 1)) {
 311 +        idle_cand = job.now;
 312 +        list_copy(&pend_idle_cand, &pend_now);
 313 +    }
 314 +    
 315 +    if ((recovery_mode == 1) && (idle_cand != 0) && (pend_idle_cand.size == 0)) {
 316 +        change_speed(1,1);
 317 +        null_call(&time_end);
 318 +        num_transition++;
 319 +        total_cycle += time_end-time_start;
 320 +        recovery_mode = 0;
 321 +    }            
 322 +}
 323 +
 324 +void sig_handler(int n, siginfo_t *info, void *unused)
 325 +{
 326 +    int nr_report, i;
 327 +    //if (info->si_int >= 1000)
 328 +    {
 329 +        get_job_report(0, &nr_report, report);
 330 +        if (nr_report != 0) {
 331 +            for (i = 0; i < nr_report; i++) {
 332 +                pend_now.addLast(&pend_now, report[i]);
 333 +            }
 334 +        }
 335 +        get_job_report(1, &nr_report, report);
 336 +        if (nr_report != 0) {
 337 +            for (i = 0; i < nr_report; i++) {
 338 +                pend_now.addLast(&pend_now, report[i]);
 339 +            }
 340 +        }
 341 +    }
 342 +//    else
 343 +    {
 344 +        get_job_report(2, &nr_report, report);
 345 +        for (i = 0; i < nr_report; i++) {
 346 +            // register jobs
 347 +            if (map_idx < num_c_jobs) {
 348 +                if (report[i].job_no == 3) {
 349 +                    task_pid[map_idx] = report[i].pid;
 350 +                    map_idx++;
 351 +                    if (map_idx == num_c_jobs) {
 352 +                        int j,k;
 353 +                        // sort and flush pend_now
 354 +                        pend_now.removeAll(&pend_now);
 355 +                        for (j=1;j<num_c_jobs;j++)
 356 +                        {
 357 +                            for (k=0; k<num_c_jobs-1;k++)
 358 +                            {
 359 +                                if (task_pid[k] > task_pid[k+1])
 360 +                                {
 361 +                                    pid_t t = task_pid[k];
 362 +                                    task_pid[k] = task_pid[k+1];
 363 +                                    task_pid[k+1] = t;
 364 +                                }
 365 +                            }
 366 +                        }
 367 +                    }
 368 +                }
 369 +                seq++;
 370 +            }
 371 +            else {
 372 +                if (report[i].seq == seq) {
 373 +                    on_job_complete(report[i]);
 374 +                    seq++;
 375 +                }
 376 +                else {
 377 +                    //printf("report[%llu] != seq[%llu]\n", report[i].seq, seq);
 378 +                    if (report[i].seq > seq)
 379 +                        seq++;
 380 +                }
 381 +            }
 382 +        }
 383 +    }
 384 +}
 385 +
 386 +#define OPTSTR "p:c:weo:f:s:r:i:d:"
 387 +
 388 +int main(int argc, char** argv)
 389 +{
 390 +	int ret;
 391 +	lt_t wcet;
 392 +	lt_t period;
 393 +	double wcet_ms, period_ms;
 394 +	int migrate = 0;
 395 +	int cpu = 0;
 396 +	int opt;
 397 +	int wait = 0;
 398 +	const char *file = NULL;
 399 +	int want_enforcement = 0;
 400 +	double duration = 0, start;
 401 +	double scale = 1.0;
 402 +	task_class_t class = RT_CLASS_HARD;
 403 +	struct mc_task mc_task = { .crit = CRIT_LEVEL_C, .lvl_a_id = -1 };
 404 +	struct sigaction sig;
 405 +    int numer = 5, nr;
 406 +	
 407 +	progname = argv[0];
 408 +
 409 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
 410 +		switch (opt) {
 411 +		case 'w':
 412 +			wait = 1;
 413 +			break;
 414 +		case 'p':
 415 +			cpu = atoi(optarg);
 416 +			migrate = 1;
 417 +			break;
 418 +		case 'c':
 419 +			class = str2class(optarg);
 420 +			if (class == -1)
 421 +				usage("Unknown task class.");
 422 +			break;
 423 +		case 'e':
 424 +			want_enforcement = 1;
 425 +			break;
 426 +	    case 'd':
 427 +			numer = atoi(optarg);
 428 +			break;
 429 +		case 'f':
 430 +			file = optarg;
 431 +			break;
 432 +		case 's':
 433 +			scale = atof(optarg);
 434 +			break;
 435 +		case 'r':
 436 +			mc_task.crit = str2crit(optarg);
 437 +			if (NUM_CRIT_LEVELS == mc_task.crit)
 438 +				usage("Bad crit level.");
 439 +			break;
 440 +		case 'i':
 441 +			mc_task.lvl_a_id = atoi(optarg);
 442 +			break;
 443 +		case ':':
 444 +			usage("Argument missing.");
 445 +			break;
 446 +		case '?':
 447 +		default:
 448 +			usage("Bad argument.");
 449 +			break;
 450 +		}
 451 +	}
 452 +    ret = register_pid(gettid());
 453 +
 454 +    // flush report buffer
 455 +    get_job_report(0, &nr, report);
 456 +    get_job_report(1, &nr, report);
 457 +    get_job_report(2, &nr, report);
 458 +    
 459 +	if (file) {
 460 +		get_task_info(file);
 461 +		if (argc - optind < 2)
 462 +			usage("Arguments missing.");
 463 +	} else {
 464 +		/*
 465 +		 * if we're not reading from the CSV file, then we need
 466 +		 * three parameters
 467 +		 */
 468 +		if (argc - optind < 3)
 469 +			usage("Arguments missing.");
 470 +	}
 471 +    
 472 +    
 473 +    speed_num = numer;
 474 +	wcet_ms   = atof(argv[optind + 0]);
 475 +	period_ms = atof(argv[optind + 1]);
 476 +	wcet   = wcet_ms * __NS_PER_MS;
 477 +	period = period_ms * __NS_PER_MS;
 478 +		
 479 +	if (wcet <= 0)
 480 +		usage("The worst-case execution time must be a "
 481 +				"positive number.");
 482 +	if (period <= 0)
 483 +		usage("The period must be a positive number.");
 484 +	if (!file && wcet > period) {
 485 +		usage("The worst-case execution time must not "
 486 +				"exceed the period.");
 487 +	}
 488 +
 489 +	duration  = atof(argv[optind + 2]);
 490 +	
 491 +        if (migrate) {
 492 + 		ret = be_migrate_to(cpu);
 493 +		if (ret < 0)
 494 +			bail_out("could not migrate to target partition");
 495 +	}
 496 +
 497 +	ret = sporadic_task_ns(wcet, period, 0, cpu, class,
 498 +			       want_enforcement ? PRECISE_ENFORCEMENT
 499 +			                        : NO_ENFORCEMENT,
 500 +			       migrate);
 501 +	if (ret < 0)
 502 +		bail_out("could not setup rt task params");
 503 +
 504 +	if (NUM_CRIT_LEVELS != mc_task.crit) {
 505 +		ret = set_rt_task_mc_param(gettid(), &mc_task);
 506 +		if (ret < 0)
 507 +			bail_out("could not setup rt mixed criticality params");
 508 +	}
 509 +    
 510 +	if (ret < 0)
 511 +		bail_out("register pid failed");
 512 +	sig.sa_sigaction = sig_handler;
 513 +	sig.sa_flags = SA_SIGINFO;
 514 +	
 515 +	sigaction(SIGIO, &sig, NULL);
 516 +	pend_now = createLinkedList();
 517 +    pend_idle_cand = createLinkedList();
 518 +        
 519 +    init_litmus();
 520 +
 521 +	ret = task_mode(LITMUS_RT_TASK);
 522 +	if (ret != 0)
 523 +		bail_out("could not become RT task");
 524 +
 525 +	if (wait) {
 526 +		ret = wait_for_ts_release();
 527 +		if (ret != 0)
 528 +			bail_out("wait_for_ts_release()");
 529 +	}
 530 +    
 531 +    start = wctime();
 532 +
 533 +	/* conver to seconds and scale */
 534 +	while (job(wcet_ms * 0.001 * scale, start + duration)) ;
 535 +
 536 +	ret = task_mode(BACKGROUND_TASK);
 537 +	if (ret != 0)
 538 +		bail_out("could not become regular task (huh?)");
 539 +
 540 +    if (num_transition != 0)
 541 +    	printf("%llu, %f\n", (lt_t)((double)total_cycle/(double)num_transition), min_speed);
 542 +    else
 543 +        printf("0, %f\n", min_speed);    
 544 +
 545 +    return 0;
 546 +}
 547 diff --git a/bin/rtspin.beta.c b/bin/rtspin.beta.c
 548 new file mode 100644
 549 index 0000000..556660e
 550 --- /dev/null
 551 +++ b/bin/rtspin.beta.c
 552 @@ -0,0 +1,283 @@
 553 +#include <sys/time.h>
 554 +
 555 +#include <stdio.h>
 556 +#include <stdlib.h>
 557 +#include <unistd.h>
 558 +#include <time.h>
 559 +#include <assert.h>
 560 +#include <strings.h>
 561 +
 562 +#include <gsl/gsl_rng.h>
 563 +#include <gsl/gsl_randist.h>
 564 +
 565 +#include "litmus.h"
 566 +#include "common.h"
 567 +
 568 +#include <litmus/sched_mc.h>
 569 +
 570 +
 571 +static void usage(char *error) {
 572 +	fprintf(stderr, "Error: %s\n", error);
 573 +	fprintf(stderr,
 574 +		"Usage:\n"
 575 +		"	rt_spin [COMMON-OPTS] LVL_C_TIME WCET PERIOD DURATION\n"
 576 +		"	rt_spin -l\n"
 577 +		"\n"
 578 +		"COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n"
 579 +		"              [-r CRITICALITY = [a|b|c|d]] [-i MC-LVL-A-ID]\n"
 580 +		"              [-a ALPHA] [-b BETA] [-d SEED]\n"
 581 +		"\n"
 582 +		"WCET and PERIOD are nanoseconds, DURATION is seconds.\n");
 583 +	exit(EXIT_FAILURE);
 584 +}
 585 +
 586 +#define NUMS 4096
 587 +static int num[NUMS];
 588 +static char* progname;
 589 +
 590 +static gsl_rng *beta_rng;
 591 +static gsl_rng *coin_rng;
 592 +
 593 +static void setup_rng(unsigned long seed)
 594 +{
 595 +	beta_rng = gsl_rng_alloc(gsl_rng_taus);
 596 +	coin_rng = gsl_rng_alloc(gsl_rng_taus);
 597 +	if (!beta_rng || !coin_rng)
 598 +		bail_out("Could not initialize RNG");
 599 +	gsl_rng_set(beta_rng, seed);
 600 +	gsl_rng_set(coin_rng, seed);
 601 +}
 602 +
 603 +static int loop_once(void)
 604 +{
 605 +	int i, j = 0;
 606 +	for (i = 0; i < NUMS; i++)
 607 +		j += num[i]++;
 608 +	return j;
 609 +}
 610 +
 611 +static int loop_for(double exec_time, double emergency_exit)
 612 +{
 613 +	double last_loop = 0, loop_start;
 614 +	int tmp = 0;
 615 +
 616 +	double start = cputime();
 617 +	double now = cputime();
 618 +
 619 +	while (now + last_loop < start + exec_time) {
 620 +		loop_start = now;
 621 +		tmp += loop_once();
 622 +		now = cputime();
 623 +		last_loop = now - loop_start;
 624 +		if (emergency_exit && wctime() > emergency_exit) {
 625 +			/* Oops --- this should only be possible if the execution time tracking
 626 +			 * is broken in the LITMUS^RT kernel. */
 627 +			fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
 628 +			fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
 629 +			break;
 630 +		}
 631 +	}
 632 +
 633 +	return tmp;
 634 +}
 635 +
 636 +
 637 +static void debug_delay_loop(void)
 638 +{
 639 +	double start, end, delay;
 640 +
 641 +	while (1) {
 642 +		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
 643 +			start = wctime();
 644 +			loop_for(delay, 0);
 645 +			end = wctime();
 646 +			printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
 647 +			       delay,
 648 +			       end - start,
 649 +			       end - start - delay,
 650 +			       100 * (end - start - delay) / delay);
 651 +		}
 652 +	}
 653 +}
 654 +
 655 +static int job(double exec_time, double program_end)
 656 +{
 657 +	if (wctime() > program_end)
 658 +		return 0;
 659 +	else {
 660 +		loop_for(exec_time, program_end + 1);
 661 +		sleep_next_period();
 662 +		return 1;
 663 +	}
 664 +}
 665 +
 666 +enum crit_level str2crit(const char* str)
 667 +{
 668 +	if (0 == strncasecmp("a", str, 1))
 669 +		return CRIT_LEVEL_A;
 670 +	else if (0 == strncasecmp("b", str, 1))
 671 +		return CRIT_LEVEL_B;
 672 +	else if (0 == strncasecmp("c", str, 1))
 673 +		return CRIT_LEVEL_C;
 674 +	/* failure */
 675 +	return NUM_CRIT_LEVELS;
 676 +}
 677 +
 678 +#define OPTSTR "a:b:d:p:c:wlves:r:i:"
 679 +
 680 +#define COIN_PROB 0.5
 681 +
 682 +int main(int argc, char** argv)
 683 +{
 684 +	int ret;
 685 +	lt_t wcet;
 686 +	lt_t period;
 687 +	lt_t lvl_c_time;
 688 +	int migrate = 0;
 689 +	int cpu = 0;
 690 +	int opt;
 691 +	int wait = 0;
 692 +	int test_loop = 0;
 693 +	int want_enforcement = 0;
 694 +	unsigned long seed = 1;
 695 +	double duration = 0, start;
 696 +	double scale = 1.0;
 697 +	double alpha = -1, beta = -1, beta_sample, exec_time;
 698 +	task_class_t class = RT_CLASS_HARD;
 699 +	struct mc_task mc_task = { .crit = NUM_CRIT_LEVELS, .lvl_a_id = -1 };
 700 +
 701 +	progname = argv[0];
 702 +
 703 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
 704 +		switch (opt) {
 705 +		case 'a':
 706 +			alpha = atof(optarg);
 707 +			break;
 708 +		case 'b':
 709 +			beta = atof(optarg);
 710 +			break;
 711 +		case 'd':
 712 +			seed = atoi(optarg);
 713 +			break;
 714 +		case 'w':
 715 +			wait = 1;
 716 +			break;
 717 +		case 'p':
 718 +			cpu = atoi(optarg);
 719 +			migrate = 1;
 720 +			break;
 721 +		case 'c':
 722 +			class = str2class(optarg);
 723 +			if (class == -1)
 724 +				usage("Unknown task class.");
 725 +			break;
 726 +		case 'e':
 727 +			want_enforcement = 1;
 728 +			break;
 729 +		case 'l':
 730 +			test_loop = 1;
 731 +			break;
 732 +		case 's':
 733 +			scale = atof(optarg);
 734 +			break;
 735 +		case 'r':
 736 +			mc_task.crit = str2crit(optarg);
 737 +			if (NUM_CRIT_LEVELS == mc_task.crit)
 738 +				usage("Bad crit level.");
 739 +			break;
 740 +		case 'i':
 741 +			mc_task.lvl_a_id = atoi(optarg);
 742 +			break;
 743 +		case ':':
 744 +			usage("Argument missing.");
 745 +			break;
 746 +		case '?':
 747 +		default:
 748 +			usage("Bad argument.");
 749 +			break;
 750 +		}
 751 +	}
 752 +
 753 +	if (test_loop) {
 754 +		debug_delay_loop();
 755 +		return 0;
 756 +	}
 757 +
 758 +	if (argc - optind < 4)
 759 +		usage("Arguments missing.");
 760 +
 761 +	lvl_c_time	= atoi(argv[optind + 0]);
 762 +	wcet		= atoi(argv[optind + 1]);
 763 +	period 		= atoi(argv[optind + 2]);
 764 +
 765 +	if (seed < 1)
 766 +		usage("Seed < 1 not allowed.");
 767 +	if (alpha <= 0 || beta <= 0)
 768 +		usage("Need positive alpha and beta.");
 769 +	if (wcet <= 0)
 770 +		usage("The worst-case execution time must be a "
 771 +				"positive number.");
 772 +	if (period <= 0)
 773 +		usage("The period must be a positive number.");
 774 +	if (wcet > period) {
 775 +		usage("The worst-case execution time must not "
 776 +				"exceed the period.");
 777 +	}
 778 +
 779 +	duration  = atof(argv[optind + 3]);
 780 +
 781 +	setup_rng(seed);
 782 +
 783 +	if (migrate) {
 784 +		ret = be_migrate_to(cpu);
 785 +		if (ret < 0)
 786 +			bail_out("could not migrate to target partition");
 787 +	}
 788 +
 789 +	ret = sporadic_task_ns(wcet, period, 0, cpu, class,
 790 +			       want_enforcement ? PRECISE_ENFORCEMENT
 791 +			                        : NO_ENFORCEMENT,
 792 +			       migrate);
 793 +	if (ret < 0)
 794 +		bail_out("could not setup rt task params");
 795 +
 796 +	if (NUM_CRIT_LEVELS != mc_task.crit) {
 797 +		ret = set_rt_task_mc_param(gettid(), &mc_task);
 798 +		if (ret < 0)
 799 +			bail_out("could not setup rt mixed criticality params");
 800 +	}
 801 +
 802 +	init_litmus();
 803 +
 804 +	ret = task_mode(LITMUS_RT_TASK);
 805 +	if (ret != 0)
 806 +		bail_out("could not become RT task");
 807 +
 808 +	if (wait) {
 809 +		ret = wait_for_ts_release();
 810 +		if (ret != 0)
 811 +			bail_out("wait_for_ts_release()");
 812 +	}
 813 +
 814 +	start = wctime();
 815 +
 816 +	do {
 817 +		double coin_flip = gsl_rng_uniform(coin_rng);
 818 +		if (coin_flip < COIN_PROB) {
 819 +			beta_sample = gsl_ran_beta(beta_rng, alpha, beta);
 820 +			exec_time = lvl_c_time * 20.0 * beta_sample * scale;
 821 +		} else
 822 +			exec_time = lvl_c_time;
 823 +		/* convert to seconds */
 824 +		exec_time = exec_time * 0.000000001;
 825 +	} while(job(exec_time, start + duration));
 826 +
 827 +	ret = task_mode(BACKGROUND_TASK);
 828 +	if (ret != 0)
 829 +		bail_out("could not become regular task (huh?)");
 830 +
 831 +	gsl_rng_free(beta_rng);
 832 +	gsl_rng_free(coin_rng);
 833 +
 834 +	return 0;
 835 +}
 836 diff --git a/bin/rtspin.c b/bin/rtspin.c
 837 index 649da45..b51924d 100644
 838 --- a/bin/rtspin.c
 839 +++ b/bin/rtspin.c
 840 @@ -4,40 +4,101 @@
 841  #include <stdlib.h>
 842  #include <unistd.h>
 843  #include <time.h>
 844 +#include <assert.h>
 845 +#include <strings.h>
 846  
 847  
 848  #include "litmus.h"
 849  #include "common.h"
 850  
 851 +#include <litmus/sched_mc.h>
 852  
 853 -static double cputime()
 854 +
 855 +static void usage(char *error) {
 856 +	fprintf(stderr, "Error: %s\n", error);
 857 +	fprintf(stderr,
 858 +		"Usage:\n"
 859 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
 860 +		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
 861 +		"	rt_spin -l\n"
 862 +		"\n"
 863 +		"COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n"
 864 +		"              [-r CRITICALITY = [a|b|c|d]] [-i MC-LVL-A-ID]\n"
 865 +		"\n"
 866 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n");
 867 +	exit(EXIT_FAILURE);
 868 +}
 869 +
 870 +/*
 871 + * returns the character that made processing stop, newline or EOF
 872 + */
 873 +static int skip_to_next_line(FILE *fstream)
 874  {
 875 -	struct timespec ts;
 876 -	int err;
 877 -	err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
 878 -	if (err != 0)
 879 -		perror("clock_gettime");
 880 -	return (ts.tv_sec + 1E-9 * ts.tv_nsec);
 881 +	int ch;
 882 +	for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
 883 +	return ch;
 884  }
 885  
 886 -static double wctime()
 887 +static void skip_comments(FILE *fstream)
 888  {
 889 -	struct timeval tv;
 890 -	gettimeofday(&tv, NULL);
 891 -	return (tv.tv_sec + 1E-6 * tv.tv_usec);
 892 +	int ch;
 893 +	for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
 894 +		skip_to_next_line(fstream);
 895 +	ungetc(ch, fstream);
 896  }
 897  
 898 -void usage(char *error) {
 899 -	fprintf(stderr, "Error: %s\n", error);
 900 -	fprintf(stderr,
 901 -		"Usage: rt_spin [-w] [-p PARTITION] [-c CLASS] WCET PERIOD DURATION\n"
 902 -		"       rt_spin -l\n");
 903 -	exit(1);
 904 +static void get_exec_times(const char *file, const int column,
 905 +			   int *num_jobs,    double **exec_times)
 906 +{
 907 +	FILE *fstream;
 908 +	int  cur_job, cur_col, ch;
 909 +	*num_jobs = 0;
 910 +
 911 +	fstream = fopen(file, "r");
 912 +	if (!fstream)
 913 +		bail_out("could not open execution time file");
 914 +
 915 +	/* figure out the number of jobs */
 916 +	do {
 917 +		skip_comments(fstream);
 918 +		ch = skip_to_next_line(fstream);
 919 +		if (ch != EOF)
 920 +			++(*num_jobs);
 921 +	} while (ch != EOF);
 922 +
 923 +	if (-1 == fseek(fstream, 0L, SEEK_SET))
 924 +		bail_out("rewinding file failed");
 925 +
 926 +	/* allocate space for exec times */
 927 +	*exec_times = calloc(*num_jobs, sizeof(*exec_times));
 928 +	if (!*exec_times)
 929 +		bail_out("couldn't allocate memory");
 930 +
 931 +	for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) {
 932 +
 933 +		skip_comments(fstream);
 934 +
 935 +		for (cur_col = 1; cur_col < column; ++cur_col) {
 936 +			/* discard input until we get to the column we want */
 937 +			fscanf(fstream, "%*s,");
 938 +		}
 939 +
 940 +		/* get the desired exec. time */
 941 +		if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) {
 942 +			fprintf(stderr, "invalid execution time near line %d\n",
 943 +					cur_job);
 944 +			exit(EXIT_FAILURE);
 945 +		}
 946 +
 947 +		skip_to_next_line(fstream);
 948 +	}
 949 +
 950 +	assert(cur_job == *num_jobs);
 951 +	fclose(fstream);
 952  }
 953  
 954  #define NUMS 4096
 955  static int num[NUMS];
 956 -static double loop_length = 1.0;
 957  static char* progname;
 958  
 959  static int loop_once(void)
 960 @@ -50,19 +111,17 @@ static int loop_once(void)
 961  
 962  static int loop_for(double exec_time, double emergency_exit)
 963  {
 964 -	double t = 0;
 965 +	double last_loop = 0, loop_start;
 966  	int tmp = 0;
 967 -/*	while (t + loop_length < exec_time) {
 968 -		tmp += loop_once();
 969 -		t += loop_length;
 970 -	}
 971 -*/
 972 +
 973  	double start = cputime();
 974  	double now = cputime();
 975 -	while (now + loop_length < start + exec_time) {
 976 +
 977 +	while (now + last_loop < start + exec_time) {
 978 +		loop_start = now;
 979  		tmp += loop_once();
 980 -		t += loop_length;
 981  		now = cputime();
 982 +		last_loop = now - loop_start;
 983  		if (emergency_exit && wctime() > emergency_exit) {
 984  			/* Oops --- this should only be possible if the execution time tracking
 985  			 * is broken in the LITMUS^RT kernel. */
 986 @@ -75,50 +134,11 @@ static int loop_for(double exec_time, double emergency_exit)
 987  	return tmp;
 988  }
 989  
 990 -static void fine_tune(double interval)
 991 -{
 992 -	double start, end, delta;
 993 -
 994 -	start = wctime();
 995 -	loop_for(interval, 0);
 996 -	end = wctime();
 997 -	delta = (end - start - interval) / interval;
 998 -	if (delta != 0)
 999 -		loop_length = loop_length / (1 - delta);
1000 -}
1001 -
1002 -static void configure_loop(void)
1003 -{
1004 -	double start;
1005 -
1006 -	/* prime cache */
1007 -	loop_once();
1008 -	loop_once();
1009 -	loop_once();
1010 -
1011 -	/* measure */
1012 -	start = wctime();
1013 -	loop_once(); /* hope we didn't get preempted  */
1014 -	loop_length = wctime();
1015 -	loop_length -= start;
1016 -
1017 -	/* fine tune */
1018 -	fine_tune(0.1);
1019 -	fine_tune(0.1);
1020 -	fine_tune(0.1);
1021 -}
1022 -
1023 -static void show_loop_length(void)
1024 -{
1025 -	printf("%s/%d: loop_length=%f (%ldus)\n",
1026 -	       progname, getpid(), loop_length,
1027 -	       (long) (loop_length * 1000000));
1028 -}
1029  
1030  static void debug_delay_loop(void)
1031  {
1032  	double start, end, delay;
1033 -	show_loop_length();
1034 +
1035  	while (1) {
1036  		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
1037  			start = wctime();
1038 @@ -144,9 +164,21 @@ static int job(double exec_time, double program_end)
1039  	}
1040  }
1041  
1042 -#define OPTSTR "p:c:wld:ve"
1043 +enum crit_level str2crit(const char* str)
1044 +{
1045 +	if (0 == strncasecmp("a", str, 1))
1046 +		return CRIT_LEVEL_A;
1047 +	else if (0 == strncasecmp("b", str, 1))
1048 +		return CRIT_LEVEL_B;
1049 +	else if (0 == strncasecmp("c", str, 1))
1050 +		return CRIT_LEVEL_C;
1051 +	/* failure */
1052 +	return NUM_CRIT_LEVELS;
1053 +}
1054 +
1055 +#define OPTSTR "p:c:wlveo:f:s:r:i:"
1056  
1057 -int main(int argc, char** argv) 
1058 +int main(int argc, char** argv)
1059  {
1060  	int ret;
1061  	lt_t wcet;
1062 @@ -157,11 +189,15 @@ int main(int argc, char** argv)
1063  	int opt;
1064  	int wait = 0;
1065  	int test_loop = 0;
1066 -	int skip_config = 0;
1067 -	int verbose = 0;
1068 +	int column = 1;
1069 +	const char *file = NULL;
1070  	int want_enforcement = 0;
1071 -	double duration, start;
1072 +	double duration = 0, start;
1073 +	double *exec_times = NULL;
1074 +	double scale = 1.0;
1075  	task_class_t class = RT_CLASS_HARD;
1076 +	int cur_job, num_jobs;
1077 +	struct mc_task mc_task = { .crit = NUM_CRIT_LEVELS, .lvl_a_id = -1 };
1078  
1079  	progname = argv[0];
1080  
1081 @@ -185,14 +221,22 @@ int main(int argc, char** argv)
1082  		case 'l':
1083  			test_loop = 1;
1084  			break;
1085 -		case 'd':
1086 -			/* manually configure delay per loop iteration 
1087 -			 * unit: microseconds */
1088 -			loop_length = atof(optarg) / 1000000;
1089 -			skip_config = 1;
1090 +		case 'o':
1091 +			column = atoi(optarg);
1092 +			break;
1093 +		case 'f':
1094 +			file = optarg;
1095 +			break;
1096 +		case 's':
1097 +			scale = atof(optarg);
1098 +			break;
1099 +		case 'r':
1100 +			mc_task.crit = str2crit(optarg);
1101 +			if (NUM_CRIT_LEVELS == mc_task.crit)
1102 +				usage("Bad crit level.");
1103  			break;
1104 -		case 'v':
1105 -			verbose = 1;
1106 +		case 'i':
1107 +			mc_task.lvl_a_id = atoi(optarg);
1108  			break;
1109  		case ':':
1110  			usage("Argument missing.");
1111 @@ -204,32 +248,50 @@ int main(int argc, char** argv)
1112  		}
1113  	}
1114  
1115 -
1116 -	if (!skip_config)
1117 -		configure_loop();
1118 -
1119  	if (test_loop) {
1120  		debug_delay_loop();
1121  		return 0;
1122  	}
1123  
1124 -	if (argc - optind < 3)
1125 -		usage("Arguments missing.");
1126 +	if (file) {
1127 +		get_exec_times(file, column, &num_jobs, &exec_times);
1128 +
1129 +		if (argc - optind < 1)
1130 +			usage("Arguments missing.");
1131 +
1132 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
1133 +			/* convert the execution time to seconds */
1134 +			duration += exec_times[cur_job] * 0.001;
1135 +		}
1136 +	} else {
1137 +		/*
1138 +		 * if we're not reading from the CSV file, then we need
1139 +		 * three parameters
1140 +		 */
1141 +		if (argc - optind < 3)
1142 +			usage("Arguments missing.");
1143 +	}
1144 +
1145  	wcet_ms   = atof(argv[optind + 0]);
1146  	period_ms = atof(argv[optind + 1]);
1147 -	duration  = atof(argv[optind + 2]);
1148 +
1149  	wcet   = wcet_ms * __NS_PER_MS;
1150  	period = period_ms * __NS_PER_MS;
1151  	if (wcet <= 0)
1152  		usage("The worst-case execution time must be a "
1153 -		      "positive number.");
1154 +				"positive number.");
1155  	if (period <= 0)
1156  		usage("The period must be a positive number.");
1157 -	if (wcet > period) {
1158 +	if (!file && wcet > period) {
1159  		usage("The worst-case execution time must not "
1160 -		      "exceed the period.");
1161 +				"exceed the period.");
1162  	}
1163  
1164 +	if (!file)
1165 +		duration  = atof(argv[optind + 2]);
1166 +	else if (file && num_jobs > 1)
1167 +		duration += period_ms * 0.001 * (num_jobs - 1);
1168 +
1169  	if (migrate) {
1170  		ret = be_migrate_to(cpu);
1171  		if (ret < 0)
1172 @@ -240,12 +302,14 @@ int main(int argc, char** argv)
1173  			       want_enforcement ? PRECISE_ENFORCEMENT
1174  			                        : NO_ENFORCEMENT,
1175  			       migrate);
1176 -
1177  	if (ret < 0)
1178  		bail_out("could not setup rt task params");
1179  
1180 -	if (verbose)
1181 -		show_loop_length();
1182 +	if (NUM_CRIT_LEVELS != mc_task.crit) {
1183 +		ret = set_rt_task_mc_param(gettid(), &mc_task);
1184 +		if (ret < 0)
1185 +			bail_out("could not setup rt mixed criticality params");
1186 +	}
1187  
1188  	init_litmus();
1189  
1190 @@ -261,12 +325,24 @@ int main(int argc, char** argv)
1191  
1192  	start = wctime();
1193  
1194 -	/* 90% wcet, in seconds */
1195 -	while (job(wcet_ms * 0.0009, start + duration));
1196 +	if (file) {
1197 +		/* use times read from the CSV file */
1198 +		for (cur_job = 0; cur_job < num_jobs; ++cur_job) {
1199 +			/* convert job's length to seconds */
1200 +			job(exec_times[cur_job] * 0.001 * scale,
1201 +					start + duration);
1202 +		}
1203 +	} else {
1204 +		/* conver to seconds and scale */
1205 +		while (job(wcet_ms * 0.001 * scale, start + duration));
1206 +	}
1207  
1208  	ret = task_mode(BACKGROUND_TASK);
1209  	if (ret != 0)
1210  		bail_out("could not become regular task (huh?)");
1211  
1212 +	if (file)
1213 +		free(exec_times);
1214 +
1215  	return 0;
1216  }
1217 diff --git a/bin/rtspin.ovh.c b/bin/rtspin.ovh.c
1218 new file mode 100644
1219 index 0000000..d130eac
1220 --- /dev/null
1221 +++ b/bin/rtspin.ovh.c
1222 @@ -0,0 +1,239 @@
1223 +#include <sys/time.h>
1224 +
1225 +#include <stdio.h>
1226 +#include <stdlib.h>
1227 +#include <unistd.h>
1228 +#include <time.h>
1229 +#include <assert.h>
1230 +#include <strings.h>
1231 +
1232 +
1233 +#include "litmus.h"
1234 +#include "common.h"
1235 +
1236 +#include <litmus/sched_mc.h>
1237 +
1238 +
1239 +static void usage(char *error) {
1240 +	fprintf(stderr, "Error: %s\n", error);
1241 +	fprintf(stderr,
1242 +		"Usage:\n"
1243 +		"	rt_spin [COMMON-OPTS] EXEC_TIME WCET PERIOD DURATION\n"
1244 +		"	rt_spin -l\n"
1245 +		"\n"
1246 +		"COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n"
1247 +		"              [-r CRITICALITY = [a|b|c|d]] [-i MC-LVL-A-ID]\n"
1248 +		"\n"
1249 +		"WCET and PERIOD are nanoseconds, DURATION is seconds.\n");
1250 +	exit(EXIT_FAILURE);
1251 +}
1252 +
1253 +#define NUMS 4096
1254 +static int num[NUMS];
1255 +static char* progname;
1256 +
1257 +static int loop_once(void)
1258 +{
1259 +	int i, j = 0;
1260 +	for (i = 0; i < NUMS; i++)
1261 +		j += num[i]++;
1262 +	return j;
1263 +}
1264 +
1265 +static int loop_for(double exec_time, double emergency_exit)
1266 +{
1267 +	double last_loop = 0, loop_start;
1268 +	int tmp = 0;
1269 +
1270 +	double start = cputime();
1271 +	double now = cputime();
1272 +
1273 +	while (now + last_loop < start + exec_time) {
1274 +		loop_start = now;
1275 +		tmp += loop_once();
1276 +		now = cputime();
1277 +		last_loop = now - loop_start;
1278 +		if (emergency_exit && wctime() > emergency_exit) {
1279 +			/* Oops --- this should only be possible if the execution time tracking
1280 +			 * is broken in the LITMUS^RT kernel. */
1281 +			fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
1282 +			fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
1283 +			break;
1284 +		}
1285 +	}
1286 +
1287 +	return tmp;
1288 +}
1289 +
1290 +
1291 +static void debug_delay_loop(void)
1292 +{
1293 +	double start, end, delay;
1294 +
1295 +	while (1) {
1296 +		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
1297 +			start = wctime();
1298 +			loop_for(delay, 0);
1299 +			end = wctime();
1300 +			printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
1301 +			       delay,
1302 +			       end - start,
1303 +			       end - start - delay,
1304 +			       100 * (end - start - delay) / delay);
1305 +		}
1306 +	}
1307 +}
1308 +
1309 +static int job(double exec_time, double program_end)
1310 +{
1311 +	if (wctime() > program_end)
1312 +		return 0;
1313 +	else {
1314 +		loop_for(exec_time, program_end + 1);
1315 +		sleep_next_period();
1316 +		return 1;
1317 +	}
1318 +}
1319 +
1320 +enum crit_level str2crit(const char* str)
1321 +{
1322 +	if (0 == strncasecmp("a", str, 1))
1323 +		return CRIT_LEVEL_A;
1324 +	else if (0 == strncasecmp("b", str, 1))
1325 +		return CRIT_LEVEL_B;
1326 +	else if (0 == strncasecmp("c", str, 1))
1327 +		return CRIT_LEVEL_C;
1328 +	/* failure */
1329 +	return NUM_CRIT_LEVELS;
1330 +}
1331 +
1332 +#define OPTSTR "p:c:wlves:r:i:"
1333 +
1334 +int main(int argc, char** argv)
1335 +{
1336 +	int ret;
1337 +	lt_t exec_time;
1338 +	lt_t wcet;
1339 +	lt_t period;
1340 +	int migrate = 0;
1341 +	int cpu = 0;
1342 +	int opt;
1343 +	int wait = 0;
1344 +	int test_loop = 0;
1345 +	int want_enforcement = 0;
1346 +	double duration = 0, start;
1347 +	double scale = 1.0;
1348 +	task_class_t class = RT_CLASS_HARD;
1349 +	struct mc_task mc_task = { .crit = NUM_CRIT_LEVELS, .lvl_a_id = -1 };
1350 +
1351 +	progname = argv[0];
1352 +
1353 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1354 +		switch (opt) {
1355 +		case 'w':
1356 +			wait = 1;
1357 +			break;
1358 +		case 'p':
1359 +			cpu = atoi(optarg);
1360 +			migrate = 1;
1361 +			break;
1362 +		case 'c':
1363 +			class = str2class(optarg);
1364 +			if (class == -1)
1365 +				usage("Unknown task class.");
1366 +			break;
1367 +		case 'e':
1368 +			want_enforcement = 1;
1369 +			break;
1370 +		case 'l':
1371 +			test_loop = 1;
1372 +			break;
1373 +		case 's':
1374 +			scale = atof(optarg);
1375 +			break;
1376 +		case 'r':
1377 +			mc_task.crit = str2crit(optarg);
1378 +			if (NUM_CRIT_LEVELS == mc_task.crit)
1379 +				usage("Bad crit level.");
1380 +			break;
1381 +		case 'i':
1382 +			mc_task.lvl_a_id = atoi(optarg);
1383 +			break;
1384 +		case ':':
1385 +			usage("Argument missing.");
1386 +			break;
1387 +		case '?':
1388 +		default:
1389 +			usage("Bad argument.");
1390 +			break;
1391 +		}
1392 +	}
1393 +
1394 +	if (test_loop) {
1395 +		debug_delay_loop();
1396 +		return 0;
1397 +	}
1398 +
1399 +	if (argc - optind < 4)
1400 +		usage("Arguments missing.");
1401 +
1402 +	exec_time	= atoi(argv[optind + 0]);
1403 +	wcet		= atoi(argv[optind + 1]);
1404 +	period 		= atoi(argv[optind + 2]);
1405 +
1406 +	if (exec_time <= 0 || exec_time > period)
1407 +		usage("bad execution time");
1408 +	if (wcet <= 0)
1409 +		usage("The worst-case execution time must be a "
1410 +				"positive number.");
1411 +	if (period <= 0)
1412 +		usage("The period must be a positive number.");
1413 +	if (wcet > period) {
1414 +		usage("The worst-case execution time must not "
1415 +				"exceed the period.");
1416 +	}
1417 +
1418 +	duration  = atof(argv[optind + 3]);
1419 +
1420 +	if (migrate) {
1421 +		ret = be_migrate_to(cpu);
1422 +		if (ret < 0)
1423 +			bail_out("could not migrate to target partition");
1424 +	}
1425 +
1426 +	ret = sporadic_task_ns(wcet, period, 0, cpu, class,
1427 +			       want_enforcement ? PRECISE_ENFORCEMENT
1428 +			                        : NO_ENFORCEMENT,
1429 +			       migrate);
1430 +	if (ret < 0)
1431 +		bail_out("could not setup rt task params");
1432 +
1433 +	if (NUM_CRIT_LEVELS != mc_task.crit) {
1434 +		ret = set_rt_task_mc_param(gettid(), &mc_task);
1435 +		if (ret < 0)
1436 +			bail_out("could not setup rt mixed criticality params");
1437 +	}
1438 +
1439 +	init_litmus();
1440 +
1441 +	ret = task_mode(LITMUS_RT_TASK);
1442 +	if (ret != 0)
1443 +		bail_out("could not become RT task");
1444 +
1445 +	if (wait) {
1446 +		ret = wait_for_ts_release();
1447 +		if (ret != 0)
1448 +			bail_out("wait_for_ts_release()");
1449 +	}
1450 +
1451 +	start = wctime();
1452 +
1453 +	/* conver to seconds and scale */
1454 +	while (job(exec_time * 0.000000001 * scale, start + duration));
1455 +
1456 +	ret = task_mode(BACKGROUND_TASK);
1457 +	if (ret != 0)
1458 +		bail_out("could not become regular task (huh?)");
1459 +
1460 +	return 0;
1461 +}
1462 diff --git a/bin/rtspinovr.c b/bin/rtspinovr.c
1463 new file mode 100644
1464 index 0000000..df7004a
1465 --- /dev/null
1466 +++ b/bin/rtspinovr.c
1467 @@ -0,0 +1,365 @@
1468 +#include <sys/time.h>
1469 +
1470 +#include <stdio.h>
1471 +#include <stdlib.h>
1472 +#include <unistd.h>
1473 +#include <time.h>
1474 +#include <assert.h>
1475 +#include <strings.h>
1476 +
1477 +
1478 +#include "litmus.h"
1479 +#include "common.h"
1480 +
1481 +#include <litmus/sched_mc.h>
1482 +
1483 +#define max(a,b) \
1484 +   ({ __typeof__ (a) _a = (a); \
1485 +       __typeof__ (b) _b = (b); \
1486 +     _a > _b ? _a : _b; })
1487 +     
1488 +int migrate = 0;
1489 +int cpu = 0;
1490 +int want_enforcement = 0;
1491 +double wcet_ms, period_ms, over_wcet_ms = 0, real_wcet_b = 0, real_wcet_b_ms;
1492 +struct mc_task mc_task = { .crit = NUM_CRIT_LEVELS, .lvl_a_id = -1 };    
1493 +
1494 +static void usage(char *error) {
1495 +	fprintf(stderr, "Error: %s\n", error);
1496 +	fprintf(stderr,
1497 +		"Usage:\n"
1498 +		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
1499 +		"	rt_spin [COMMON-OPTS] -f FILE WCET PERIOD\n"
1500 +		"	rt_spin -l\n"
1501 +		"\n"
1502 +		"COMMON-OPTS = [-w] [-p PARTITION] [-c CLASS] [-s SCALE]\n"
1503 +		"              [-r CRITICALITY = [a|b|c|d]] [-i MC-LVL-A-ID]\n"
1504 +		"              [-v OVERRUN_START]"
1505 +		"\n"
1506 +		"WCET and PERIOD are milliseconds, DURATION is seconds.\n");
1507 +	exit(EXIT_FAILURE);
1508 +}
1509 +
1510 +/*
1511 + * returns the character that made processing stop, newline or EOF
1512 + */
1513 +static int skip_to_next_line(FILE *fstream)
1514 +{
1515 +	int ch;
1516 +	for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream));
1517 +	return ch;
1518 +}
1519 +
1520 +static void skip_comments(FILE *fstream)
1521 +{
1522 +	int ch;
1523 +	for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream))
1524 +		skip_to_next_line(fstream);
1525 +	ungetc(ch, fstream);
1526 +}
1527 +
1528 +void get_task_info(const char *file, int my_id)
1529 +{
1530 +	FILE *fstream;
1531 +	int cur_job, ch;
1532 +    int temp1, temp2, id, crit;
1533 +    float pp, tol;
1534 +    float wcet_b, wcet_c;
1535 +    
1536 +	int num_jobs = 0;
1537 +
1538 +    fstream = fopen(file, "r");
1539 +	if (!fstream)
1540 +		bail_out("could not open execution time file");
1541 +
1542 +	/* figure out the number of jobs */
1543 +	do {
1544 +		skip_comments(fstream);
1545 +		ch = skip_to_next_line(fstream);
1546 +		if (ch != EOF)
1547 +			++(num_jobs);
1548 +	} while (ch != EOF);
1549 +	
1550 +	if (-1 == fseek(fstream, 0L, SEEK_SET))
1551 +		bail_out("rewinding file failed");
1552 +    
1553 +    ch = skip_to_next_line(fstream);
1554 +	/* allocate space for exec times */
1555 +	for (cur_job = 0; cur_job < num_jobs && !feof(fstream); ++cur_job) {
1556 +		skip_comments(fstream);
1557 +
1558 +        fscanf(fstream, "%d %d %d %f %f %d %f %f", &id, &temp1, &temp2, &pp, &tol, &crit, &wcet_b, &wcet_c);
1559 +        if (id == my_id)
1560 +        {
1561 +            cpu = temp1;
1562 +            wcet_ms = wcet_c;
1563 +            period_ms = (double)temp2;
1564 +            over_wcet_ms = wcet_b;
1565 +            real_wcet_b_ms = wcet_b;
1566 +            if (crit == 1) {
1567 +                mc_task.crit = CRIT_LEVEL_B;
1568 +                migrate = 1;
1569 +                real_wcet_b_ms = wcet_b;
1570 +                want_enforcement = 1;
1571 +            }
1572 +            else if (crit == 2) {
1573 +                mc_task.crit = CRIT_LEVEL_C;
1574 +                over_wcet_ms = period_ms;
1575 +                real_wcet_b_ms = period_ms;
1576 +            }
1577 +            break;
1578 +        }
1579 +		skip_to_next_line(fstream);
1580 +	}
1581 +
1582 +	fclose(fstream);
1583 +}
1584 +
1585 +
1586 +#define NUMS 4096
1587 +static int num[NUMS];
1588 +static char* progname;
1589 +
1590 +static int loop_once(void)
1591 +{
1592 +	int i, j = 0;
1593 +	for (i = 0; i < NUMS; i++)
1594 +		j += num[i]++;
1595 +	return j;
1596 +}
1597 +
1598 +static int loop_for(double exec_time, double emergency_exit)
1599 +{
1600 +	double last_loop = 0, loop_start;
1601 +	int tmp = 0;
1602 +
1603 +	double start = cputime();
1604 +	double now = cputime();
1605 +
1606 +	while (now + last_loop < start + exec_time) {
1607 +		loop_start = now;
1608 +		tmp += loop_once();
1609 +		now = cputime();
1610 +		last_loop = now - loop_start;
1611 +		
1612 +        if (emergency_exit && wctime() > emergency_exit) {
1613 +			fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid());
1614 +			fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n");
1615 +			break;
1616 +		}
1617 +	}
1618 +
1619 +	return tmp;
1620 +}
1621 +
1622 +
1623 +static void debug_delay_loop(void)
1624 +{
1625 +	double start, end, delay;
1626 +
1627 +	while (1) {
1628 +		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
1629 +			start = wctime();
1630 +			loop_for(delay, 0);
1631 +			end = wctime();
1632 +			printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
1633 +			       delay,
1634 +			       end - start,
1635 +			       end - start - delay,
1636 +			       100 * (end - start - delay) / delay);
1637 +		}
1638 +	}
1639 +}
1640 +
1641 +static int job(double exec_time, double program_end)
1642 +{
1643 +	if (wctime() > program_end)
1644 +		return 0;
1645 +	else {
1646 +		loop_for(exec_time, program_end + 1);
1647 +		sleep_next_period();
1648 +		return 1;
1649 +	}
1650 +}
1651 +
1652 +enum crit_level str2crit(const char* str)
1653 +{
1654 +	if (0 == strncasecmp("a", str, 1))
1655 +		return CRIT_LEVEL_A;
1656 +	else if (0 == strncasecmp("b", str, 1))
1657 +		return CRIT_LEVEL_B;
1658 +	else if (0 == strncasecmp("c", str, 1))
1659 +		return CRIT_LEVEL_C;
1660 +	/* failure */
1661 +	return NUM_CRIT_LEVELS;
1662 +}
1663 +
1664 +#define OPTSTR "p:c:wle:f:s:r:i:v:j:d:"
1665 +
1666 +int main(int argc, char** argv)
1667 +{
1668 +	int ret;
1669 +	lt_t wcet;
1670 +	lt_t period;
1671 +	lt_t over_wcet;
1672 +	double prev_wcet_ms;
1673 +	
1674 +	int opt;
1675 +	int wait = 0;
1676 +	int test_loop = 0;
1677 +	const char *file = NULL;
1678 +	double duration = 0, start;
1679 +	double *exec_times = NULL;
1680 +	double scale = 1.0;
1681 +	task_class_t class = RT_CLASS_HARD;
1682 +	int my_id;
1683 +    int overloaded = 0;
1684 +    double overload_start = 0.0;
1685 +
1686 +	progname = argv[0];
1687 +
1688 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1689 +		switch (opt) {
1690 +		case 'w':
1691 +			wait = 1;
1692 +			break;
1693 +		case 'p':
1694 +			cpu = atoi(optarg);
1695 +			migrate = 1;
1696 +			break;
1697 +		case 'c':
1698 +			class = str2class(optarg);
1699 +			if (class == -1)
1700 +				usage("Unknown task class.");
1701 +			break;
1702 +		case 'e':
1703 +			want_enforcement = 1;
1704 +			break;
1705 +		case 'l':
1706 +			test_loop = 1;
1707 +			break;
1708 +		case 'f':
1709 +			file = optarg;
1710 +			break;
1711 +		case 's':
1712 +			scale = atof(optarg);
1713 +			break;
1714 +		case 'r':
1715 +			mc_task.crit = str2crit(optarg);
1716 +			if (NUM_CRIT_LEVELS == mc_task.crit)
1717 +				usage("Bad crit level.");
1718 +			break;
1719 +		case 'i':
1720 +			my_id = atoi(optarg);
1721 +			break;
1722 +		case 'v':
1723 +			overload_start = atoi(optarg);
1724 +			break;
1725 +		case ':':
1726 +			usage("Argument missing.");
1727 +			break;
1728 +		case '?':
1729 +		default:
1730 +			usage("Bad argument.");
1731 +			break;
1732 +		}
1733 +	}
1734 +
1735 +	if (test_loop) {
1736 +		debug_delay_loop();
1737 +		return 0;
1738 +	}
1739 +
1740 +	if (file) {
1741 +		get_task_info(file, my_id);
1742 +	}
1743 +
1744 +    prev_wcet_ms = wcet_ms;
1745 +	wcet   = wcet_ms * __NS_PER_MS;
1746 +	period = period_ms * __NS_PER_MS;
1747 +	if (over_wcet_ms == 0)
1748 +		over_wcet = wcet_ms * __NS_PER_MS;
1749 +	else
1750 +		over_wcet = over_wcet_ms * __NS_PER_MS;
1751 +    real_wcet_b = real_wcet_b_ms * __NS_PER_MS;
1752 +	if (wcet <= 0)
1753 +		usage("The worst-case execution time must be a "
1754 +				"positive number.");
1755 +	if (period <= 0)
1756 +		usage("The period must be a positive number.");
1757 +	if (over_wcet <= 0)
1758 +		usage("The overrun worst-case execution time must be a "
1759 +				"positive number.");
1760 +	if (!file && wcet > period) {
1761 +		usage("The worst-case execution time must not "
1762 +				"exceed the period.");
1763 +	}
1764 +
1765 +	duration  = atof(argv[optind]);
1766 +	
1767 +    if (migrate) {
1768 +		ret = be_migrate_to(cpu);
1769 +		if (ret < 0)
1770 +			bail_out("could not migrate to target partition");
1771 +	}
1772 +        
1773 +	ret = sporadic_task_ns(over_wcet, period, 0, cpu, class,
1774 +			       want_enforcement ? PRECISE_ENFORCEMENT
1775 +			                        : NO_ENFORCEMENT,
1776 +			       migrate);
1777 +	if (ret < 0)
1778 +		bail_out("could not setup rt task params");
1779 +
1780 +	if (NUM_CRIT_LEVELS != mc_task.crit) {
1781 +		ret = set_rt_task_mc_param(gettid(), &mc_task);
1782 +		if (ret < 0)
1783 +			bail_out("could not setup rt mixed criticality params");
1784 +	}
1785 +	
1786 +    init_litmus();
1787 +	ret = task_mode(LITMUS_RT_TASK);
1788 +	if (ret != 0)
1789 +		bail_out("could not become RT task");
1790 +
1791 +	if (wait) {
1792 +		ret = wait_for_ts_release();
1793 +		if (ret != 0)
1794 +			bail_out("wait_for_ts_release()");
1795 +	}
1796 +
1797 +	start = wctime();  
1798 +
1799 +
1800 +	/* conver to seconds and scale */
1801 +	while (job(wcet_ms * 0.001 * scale, start + duration))
1802 +    {
1803 +        if (wctime() - start > overload_start && overloaded < 1) {
1804 +            wcet_ms = over_wcet_ms;
1805 +            overloaded = 1;
1806 +        }
1807 +        if ((wctime() - start > overload_start + 0.5) &&
1808 +            (overloaded == 1)) {
1809 +            wcet_ms = prev_wcet_ms;
1810 +		}
1811 +/*        
1812 +        if ((wctime() - start > overload_start + 1.5) &&
1813 +            (overloaded == 1)) {
1814 +            wcet_ms = over_wcet_ms;
1815 +            overloaded = 2;
1816 +		}
1817 +        if ((wctime() - start > overload_start + 2) &&
1818 +            (overloaded == 2)) {
1819 +            wcet_ms = prev_wcet_ms;
1820 +        }
1821 +*/        
1822 +	}
1823 +
1824 +	ret = task_mode(BACKGROUND_TASK);
1825 +	if (ret != 0)
1826 +		bail_out("could not become regular task (huh?)");
1827 +
1828 +	if (file)
1829 +		free(exec_times);
1830 +
1831 +	return 0;
1832 +}
1833 diff --git a/include/linkedlist.h b/include/linkedlist.h
1834 new file mode 100644
1835 index 0000000..028d10f
1836 --- /dev/null
1837 +++ b/include/linkedlist.h
1838 @@ -0,0 +1,239 @@
1839 +#include <stdio.h>
1840 +#include <stdarg.h>
1841 +#include <stdlib.h>
1842 +
1843 +#include "litmus/rt_param.h"
1844 +
1845 +typedef struct Node {
1846 +	struct report_data item;
1847 +	// previous node
1848 +	struct Node* prev;
1849 +	// next node
1850 +	struct Node* next;
1851 +} Node;
1852 +
1853 +typedef struct LinkedList {
1854 +	Node* head;
1855 +	Node* tail;
1856 +	// size of this LinkedList
1857 +	int size;
1858 +
1859 +	// add item after tail
1860 +	void (*addLast) (struct LinkedList*, struct report_data);
1861 +	// get item from any position
1862 +	struct report_data (*get) (struct LinkedList*, int);
1863 +
1864 +	// remove item from any position
1865 +	void (*remove) (struct LinkedList*, struct report_data);
1866 +    // remove all
1867 +    void (*removeAll) (struct LinkedList*);
1868 +
1869 +	// display all element in the LinkedList
1870 +	void (*display) (struct LinkedList*);
1871 +	// create a node with item
1872 +	Node* (*createNode) (struct report_data);
1873 +} LinkedList;
1874 +
1875 +/** add item to tail
1876 + */
1877 +void addLast (LinkedList* _this, struct report_data item);
1878 +/** get item from specific position
1879 + */
1880 +struct report_data get (LinkedList* _this, int position);
1881 +/** get item and remove it from any position
1882 + */
1883 +void _remove (LinkedList* _this, struct report_data data);
1884 +void _removeAll(LinkedList* _this);
1885 +/** display the items in the list
1886 + */
1887 +void display (LinkedList* _this);
1888 +/** create a LinkedList
1889 + */
1890 +LinkedList createLinkedList ();
1891 +/** create a Node
1892 + */
1893 +Node* createNode (struct report_data item);
1894 +
1895 +/** add item to tail
1896 + */
1897 +void addLast (LinkedList* _this, struct report_data item) {
1898 +	Node* newNode = _this->createNode(item);
1899 +    int is_exist = 0;
1900 +	// list is empty
1901 +	if (_this->head == NULL) {
1902 +        _this->head = newNode;
1903 +        newNode->next = NULL;
1904 +        newNode->prev = newNode;
1905 +        _this->size = 1;
1906 +        return;
1907 +    }
1908 +	else { // has item(s)
1909 +		Node* curNode = _this->head;;
1910 +        while(curNode->next != NULL) {
1911 +            if (item.pid == curNode->item.pid && item.job_no == curNode->item.job_no)
1912 +                is_exist = 1;
1913 +            curNode = curNode->next;
1914 +        }
1915 +        if (is_exist == 1) {
1916 +            //printf("%d/%d is already in the list\n", item.pid, item.job_no);
1917 +            free(newNode);
1918 +            return;
1919 +        }
1920 +        curNode->next = newNode;
1921 +        newNode->prev = curNode;
1922 +        newNode->next = NULL;
1923 +        _this->size++;
1924 +        return;
1925 +	}
1926 +    return;
1927 +}
1928 +
1929 +/** get item from specific position
1930 + */
1931 +struct report_data get(LinkedList* _this, int position) {
1932 +    
1933 +    Node* node;
1934 +    int i = 0;
1935 +    
1936 +	// list is empty
1937 +	if (_this->size == 0) {
1938 +		//printf("LinkedList#get: The list is empty.");
1939 +		//system("PAUSE");
1940 +		exit(0);
1941 +	} else if (position >= _this->size) {
1942 +		// out of bound
1943 +		//printf("LinkedList#get: Index out of bound");
1944 +		//system("PAUSE");
1945 +		exit(0);
1946 +	}
1947 +    node = _this->head;
1948 +    // loop until position
1949 +    while (i < position) {
1950 +        node = node->next;
1951 +        i++;
1952 +    }
1953 +    return node->item;
1954 +}
1955 +
1956 +void list_copy (struct LinkedList* dst, struct LinkedList* src)
1957 +{
1958 +    struct report_data item;
1959 +    int i;
1960 +    
1961 +    if (dst->size != 0)
1962 +        dst->removeAll(dst);
1963 +        
1964 +    if (src->size == 0) {
1965 +        return;
1966 +    }
1967 +    
1968 +    for (i=0; i< src->size; i++) {
1969 +        item = src->get(src, i);
1970 +        //printf("add %d/%d to dst\n", item.pid, item.job_no);
1971 +        dst->addLast(dst, item);
1972 +    }
1973 +    return;
1974 +}
1975 +
1976 +/** get item and remove it from any position
1977 + */
1978 +void _remove (LinkedList* _this, struct report_data data)
1979 +{
1980 +    Node* node = _this->head;
1981 +    
1982 +	// list is empty
1983 +	if (_this->size == 0) {
1984 +		return;
1985 +	}
1986 +
1987 +    // head
1988 +    if (data.pid == node->item.pid && data.job_no == node->item.job_no) {
1989 +        _this->head = node->next;
1990 +        if (node->next != NULL)
1991 +            _this->head->prev = _this->head;
1992 +        _this->size--;
1993 +        return;
1994 +    }
1995 +
1996 +    while (data.pid != node->item.pid || data.job_no != node->item.job_no) {
1997 +        node = node->next;
1998 +        if (node == NULL) {
1999 +            return;
2000 +        }
2001 +    }
2002 +    if (node->next == NULL) {
2003 +        node->prev->next = NULL;
2004 +        free(node);
2005 +        _this->size--;
2006 +        return;
2007 +    }
2008 +    
2009 +    node->prev->next = node->next;
2010 +    node->next->prev = node->prev;
2011 +    free(node);
2012 +    _this->size--;
2013 +    return;
2014 +}
2015 +
2016 +void _removeAll (LinkedList* _this)
2017 +{
2018 +    Node* node;
2019 +    Node* nextNode;
2020 +    
2021 +	// list is empty
2022 +	if (_this->size == 0) {
2023 +		return;
2024 +	}
2025 +    node = _this->head;
2026 +    while (node->next != NULL) {
2027 +        nextNode = node->next;
2028 +        free(node);
2029 +        node = nextNode;
2030 +    }
2031 +    _this->head = NULL;
2032 +    _this->size = 0;
2033 +    return;
2034 +}
2035 +
2036 +/** display the items in the list
2037 + */
2038 +void display (LinkedList* _this) {
2039 +	 int i, size = _this->size;
2040 +	 if (size == 0)
2041 +		printf("has 0 item\n");
2042 +	 else {
2043 +		Node* node = _this->head;
2044 +        printf("has %d items\n", size);
2045 +		
2046 +		for (i = 0; i < size; i++) {
2047 +			if (i > 0)
2048 +				printf(", ");
2049 +			printf("%d/%d", node->item.pid, node->item.job_no);
2050 +			node = node->next;
2051 +		}
2052 +		printf("\n");
2053 +	}
2054 +}
2055 +/** create a LinkedList
2056 + */
2057 +LinkedList createLinkedList () {
2058 +	LinkedList list;
2059 +	list.head = NULL;
2060 +	list.tail = NULL;
2061 +	list.addLast = &addLast;
2062 +	list.remove = &_remove;
2063 +    list.removeAll = &_removeAll;
2064 +	list.display = &display;
2065 +	list.createNode = &createNode;
2066 +    list.size = 0;
2067 +	return list;
2068 +}
2069 +/** create a Node
2070 + */
2071 +Node* createNode (struct report_data item) {
2072 +	Node* node = (Node*) malloc (sizeof(Node));
2073 +	node->item = item;
2074 +	node->prev = NULL;
2075 +	node->next = NULL;
2076 +	return node;
2077 +}
2078 \ No newline at end of file
2079 diff --git a/include/litmus.h b/include/litmus.h
2080 index 2a26a4a..2b82212 100644
2081 --- a/include/litmus.h
2082 +++ b/include/litmus.h
2083 @@ -6,6 +6,7 @@ extern "C" {
2084  #endif
2085  
2086  #include <sys/types.h>
2087 +#include <stdint.h>
2088  
2089  /* Include kernel header.
2090   * This is required for the rt_param
2091 @@ -25,6 +26,12 @@ int be_migrate_to(int target_cpu);
2092  
2093  int set_rt_task_param(pid_t pid, struct rt_task* param);
2094  int get_rt_task_param(pid_t pid, struct rt_task* param);
2095 +int register_pid(pid_t pid);
2096 +int get_job_report(int type, int *num_report, struct report_data *param);
2097 +int change_speed(int num, int denom);
2098 +
2099 +struct mc_task;
2100 +int set_rt_task_mc_param(pid_t pid, struct mc_task *param);
2101  
2102  /* setup helper */
2103  
2104 @@ -60,13 +67,9 @@ static inline int od_open(int fd, obj_type_t type, int obj_id)
2105  	return od_openx(fd, type, obj_id, 0);
2106  }
2107  
2108 -/* FMLP binary semaphore support */
2109 -int fmlp_down(int od);
2110 -int fmlp_up(int od);
2111 -
2112 -/* SRP binary semaphore support */
2113 -int srp_down(int od);
2114 -int srp_up(int od);
2115 +/* real-time locking protocol support */
2116 +int litmus_lock(int od);
2117 +int litmus_unlock(int od);
2118  
2119  /* job control*/
2120  int get_job_no(unsigned int* job_no);
2121 @@ -111,6 +114,12 @@ static inline lt_t ms2lt(unsigned long milliseconds)
2122  	return __NS_PER_MS * milliseconds;
2123  }
2124  
2125 +/* CPU time consumed so far in seconds */
2126 +double cputime(void);
2127 +
2128 +/* wall-clock time in seconds */
2129 +double wctime(void);
2130 +
2131  /* semaphore allocation */
2132  
2133  static inline int open_fmlp_sem(int fd, int name)
2134 diff --git a/src/clocks.c b/src/clocks.c
2135 new file mode 100644
2136 index 0000000..fcb94e5
2137 --- /dev/null
2138 +++ b/src/clocks.c
2139 @@ -0,0 +1,23 @@
2140 +#include <stdio.h>
2141 +
2142 +#include <sys/time.h>
2143 +#include <time.h>
2144 +
2145 +/* CPU time consumed so far in seconds */
2146 +double cputime(void)
2147 +{
2148 +	struct timespec ts;
2149 +	int err;
2150 +	err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
2151 +	if (err != 0)
2152 +		perror("clock_gettime");
2153 +	return (ts.tv_sec + 1E-9 * ts.tv_nsec);
2154 +}
2155 +
2156 +/* wall-clock time in seconds */
2157 +double wctime(void)
2158 +{
2159 +	struct timeval tv;
2160 +	gettimeofday(&tv, NULL);
2161 +	return (tv.tv_sec + 1E-6 * tv.tv_usec);
2162 +}
2163 diff --git a/src/syscalls.c b/src/syscalls.c
2164 index c738ac4..f78475e 100644
2165 --- a/src/syscalls.c
2166 +++ b/src/syscalls.c
2167 @@ -44,24 +44,14 @@ int od_close(int od)
2168  	return syscall(__NR_od_close, od);
2169  }
2170  
2171 -int fmlp_down(int od)
2172 +int litmus_lock(int od)
2173  {
2174 -	return syscall(__NR_fmlp_down, od);
2175 +	return syscall(__NR_litmus_lock, od);
2176  }
2177  
2178 -int fmlp_up(int od)
2179 +int litmus_unlock(int od)
2180  {
2181 -	return syscall(__NR_fmlp_up, od);
2182 -}
2183 -
2184 -int srp_down(int od)
2185 -{
2186 -	return syscall(__NR_srp_down, od);
2187 -}
2188 -
2189 -int srp_up(int od)
2190 -{
2191 -	return syscall(__NR_srp_up, od);
2192 +	return syscall(__NR_litmus_unlock, od);
2193  }
2194  
2195  int get_job_no(unsigned int *job_no)
2196 @@ -98,3 +88,23 @@ int null_call(cycles_t *timestamp)
2197  {
2198  	return syscall(__NR_null_call, timestamp);
2199  }
2200 +
2201 +int set_rt_task_mc_param(pid_t pid, struct mc_task *param)
2202 +{
2203 +	return syscall(__NR_set_rt_task_mc_param, pid, param);
2204 +}
2205 +
2206 +int change_speed(int num, int denom)
2207 +{
2208 +	return syscall(__NR_change_speed, num, denom);
2209 +}
2210 +
2211 +int register_pid(pid_t pid)
2212 +{
2213 +	return syscall(__NR_register_pid, pid);
2214 +}
2215 +
2216 +int get_job_report(int type, int *num_report, struct report_data *param)
2217 +{
2218 +    return syscall(__NR_get_job_report, type, num_report, param);
2219 +}
2220 \ No newline at end of file
2221 diff --git a/tests/core_api.c b/tests/core_api.c
2222 index d858f1f..7f7a099 100644
2223 --- a/tests/core_api.c
2224 +++ b/tests/core_api.c
2225 @@ -1,5 +1,8 @@
2226 -#include "tests.h"
2227 +#include <sys/wait.h> /* for waitpid() */
2228 +#include <unistd.h>
2229 +#include <stdio.h>
2230  
2231 +#include "tests.h"
2232  #include "litmus.h"
2233  
2234  
2235 @@ -19,6 +22,7 @@ TESTCASE(set_rt_task_param_invalid_params, ALL,
2236  	params.period     = 100;
2237  	params.phase      = 0;
2238  	params.cls        = RT_CLASS_HARD;
2239 +	params.budget_policy = NO_ENFORCEMENT;
2240  
2241  	/* over utilize */
2242  	params.exec_cost  = 110;
2243 @@ -49,3 +53,40 @@ TESTCASE(job_control_non_rt, ALL,
2244  
2245  	SYSCALL_FAILS( EPERM, get_job_no(&job_no) );
2246  }
2247 +
2248 +
2249 +TESTCASE(rt_fork_non_rt, LITMUS,
2250 +	 "children of RT tasks are not automatically RT tasks")
2251 +{
2252 +	unsigned int pid, job_no;
2253 +	int status;
2254 +
2255 +	SYSCALL( sporadic_partitioned(10, 100, 0) );
2256 +	SYSCALL( task_mode(LITMUS_RT_TASK) );
2257 +
2258 +	pid = fork();
2259 +
2260 +	ASSERT( pid != -1 );
2261 +
2262 +	if (pid == 0) {
2263 +		/* child */
2264 +
2265 +		SYSCALL_FAILS( EINVAL, sleep_next_period() );
2266 +		SYSCALL_FAILS( EINVAL, wait_for_job_release(0) );
2267 +		SYSCALL_FAILS( EPERM, get_job_no(&job_no) );
2268 +
2269 +		exit(0);
2270 +	} else {
2271 +		/* parent */
2272 +
2273 +		SYSCALL( sleep_next_period() );
2274 +		SYSCALL( wait_for_job_release(20) );
2275 +		SYSCALL( get_job_no(&job_no) );
2276 +
2277 +		SYSCALL( task_mode(BACKGROUND_TASK) );
2278 +
2279 +		SYSCALL( waitpid(pid, &status, 0) );
2280 +
2281 +		ASSERT(WEXITSTATUS(status) == 0);
2282 +	}
2283 +}
2284 diff --git a/tests/fdso.c b/tests/fdso.c
2285 index d60e9ef..8a2a0d0 100644
2286 --- a/tests/fdso.c
2287 +++ b/tests/fdso.c
2288 @@ -20,7 +20,7 @@ TESTCASE(fmlp_not_active, C_EDF | PFAIR | LINUX,
2289  
2290  	ASSERT(fd != -1);
2291  
2292 -	SYSCALL_FAILS(EBUSY, open_fmlp_sem(fd, 0) );
2293 +	SYSCALL_FAILS(ENXIO, open_fmlp_sem(fd, 0) );
2294  
2295  	SYSCALL( close(fd) );
2296  
2297 @@ -31,16 +31,16 @@ TESTCASE(fmlp_not_active, C_EDF | PFAIR | LINUX,
2298  TESTCASE(invalid_od, ALL,
2299  	 "reject invalid object descriptors")
2300  {
2301 -	SYSCALL_FAILS( EINVAL, fmlp_down(3) );
2302 +	SYSCALL_FAILS( EINVAL, litmus_lock(3) );
2303  
2304 -	SYSCALL_FAILS( EINVAL, fmlp_up(3) );
2305 +	SYSCALL_FAILS( EINVAL, litmus_unlock(3) );
2306  
2307  	SYSCALL_FAILS( EINVAL, od_close(3) );
2308  
2309  
2310 -	SYSCALL_FAILS( EINVAL, fmlp_down(-1) );
2311 +	SYSCALL_FAILS( EINVAL, litmus_lock(-1) );
2312  
2313 -	SYSCALL_FAILS( EINVAL, fmlp_up(-1) );
2314 +	SYSCALL_FAILS( EINVAL, litmus_unlock(-1) );
2315  
2316  	SYSCALL_FAILS( EINVAL, od_close(-1) );
2317  }
2318 @@ -61,23 +61,34 @@ TESTCASE(not_inherit_od, GSN_EDF | PSN_EDF,
2319  
2320  	SYSCALL( od = open_fmlp_sem(fd, 0) );
2321  
2322 -	SYSCALL( fmlp_down(od) );
2323 -
2324 -	SYSCALL( fmlp_up(od) );
2325 -
2326  	pid = fork();
2327  
2328  	ASSERT( pid != -1 );
2329  
2330 +	/* must be an RT task to lock at all */
2331 +	SYSCALL( sporadic_partitioned(10, 100, 0) );
2332 +	SYSCALL( task_mode(LITMUS_RT_TASK) );
2333 +
2334  	if (pid == 0) {
2335  		/* child */
2336 -		SYSCALL_FAILS(EINVAL, fmlp_down(od) );
2337 -	        SYSCALL_FAILS(EINVAL, fmlp_up(od) );
2338 +		SYSCALL_FAILS(EINVAL, litmus_lock(od) );
2339 +	        SYSCALL_FAILS(EINVAL, litmus_unlock(od) );
2340 +
2341 +		SYSCALL( task_mode(BACKGROUND_TASK) );
2342 +
2343  		exit(0);
2344  	} else {
2345 -		SYSCALL( fmlp_down(od) );
2346 -		SYSCALL( fmlp_up(od) );
2347 +
2348 +		SYSCALL( litmus_lock(od) );
2349 +		SYSCALL( litmus_unlock(od) );
2350 +
2351 +		SYSCALL( litmus_lock(od) );
2352 +		SYSCALL( litmus_unlock(od) );
2353 +
2354 +		SYSCALL( task_mode(BACKGROUND_TASK) );
2355 +
2356  		SYSCALL( waitpid(pid, &status, 0) );
2357 +
2358  		ASSERT(WEXITSTATUS(status) == 0);
2359  	}
2360  
2361 diff --git a/tests/locks.c b/tests/locks.c
2362 new file mode 100644
2363 index 0000000..65b932a
2364 --- /dev/null
2365 +++ b/tests/locks.c
2366 @@ -0,0 +1,110 @@
2367 +#include <fcntl.h>
2368 +#include <unistd.h>
2369 +#include <stdio.h>
2370 +
2371 +#include "tests.h"
2372 +#include "litmus.h"
2373 +
2374 +
2375 +TESTCASE(not_lock_fmlp_be, GSN_EDF | PSN_EDF,
2376 +	 "don't let best-effort tasks lock FMLP semaphores")
2377 +{
2378 +	int fd, od;
2379 +
2380 +	SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT) );
2381 +
2382 +	SYSCALL( od = open_fmlp_sem(fd, 0) );
2383 +
2384 +	/* BE tasks may not lock FMLP semaphores */
2385 +	SYSCALL_FAILS(EPERM, litmus_lock(od) );
2386 +
2387 +	/* tasks may not unlock resources they don't own */
2388 +	SYSCALL_FAILS(EINVAL, litmus_unlock(od) );
2389 +
2390 +	SYSCALL( od_close(od) );
2391 +
2392 +	SYSCALL( close(fd) );
2393 +
2394 +	SYSCALL( remove(".fmlp_locks") );
2395 +
2396 +}
2397 +
2398 +TESTCASE(not_lock_srp_be, PSN_EDF,
2399 +	 "don't let best-effort tasks open SRP semaphores")
2400 +{
2401 +	int fd, od;
2402 +
2403 +	SYSCALL( fd = open(".srp_locks", O_RDONLY | O_CREAT) );
2404 +
2405 +	/* BE tasks may not open SRP semaphores */
2406 +
2407 +	SYSCALL_FAILS(EPERM, od = open_srp_sem(fd, 0) );
2408 +
2409 +	SYSCALL( close(fd) );
2410 +
2411 +	SYSCALL( remove(".srp_locks") );
2412 +
2413 +}
2414 +
2415 +TESTCASE(lock_srp, PSN_EDF,
2416 +	 "SRP acquisition and release")
2417 +{
2418 +	int fd, od;
2419 +
2420 +	SYSCALL( fd = open(".srp_locks", O_RDONLY | O_CREAT) );
2421 +
2422 +	SYSCALL( sporadic_partitioned(10, 100, 0) );
2423 +	SYSCALL( task_mode(LITMUS_RT_TASK) );
2424 +
2425 +	SYSCALL( od = open_srp_sem(fd, 0) );
2426 +
2427 +	SYSCALL( litmus_lock(od) );
2428 +	SYSCALL( litmus_unlock(od) );
2429 +
2430 +	SYSCALL( litmus_lock(od) );
2431 +	SYSCALL( litmus_unlock(od) );
2432 +
2433 +	SYSCALL( litmus_lock(od) );
2434 +	SYSCALL( litmus_unlock(od) );
2435 +
2436 +	/* tasks may not unlock resources they don't own */
2437 +	SYSCALL_FAILS(EINVAL, litmus_unlock(od) );
2438 +
2439 +	SYSCALL( od_close(od) );
2440 +
2441 +	SYSCALL( close(fd) );
2442 +
2443 +	SYSCALL( remove(".srp_locks") );
2444 +}
2445 +
2446 +
2447 +TESTCASE(lock_fmlp, PSN_EDF | GSN_EDF,
2448 +	 "FMLP acquisition and release")
2449 +{
2450 +	int fd, od;
2451 +
2452 +	SYSCALL( fd = open(".fmlp_locks", O_RDONLY | O_CREAT) );
2453 +
2454 +	SYSCALL( sporadic_partitioned(10, 100, 0) );
2455 +	SYSCALL( task_mode(LITMUS_RT_TASK) );
2456 +
2457 +	SYSCALL( od = open_fmlp_sem(fd, 0) );
2458 +
2459 +	SYSCALL( litmus_lock(od) );
2460 +	SYSCALL( litmus_unlock(od) );
2461 +
2462 +	SYSCALL( litmus_lock(od) );
2463 +	SYSCALL( litmus_unlock(od) );
2464 +
2465 +	SYSCALL( litmus_lock(od) );
2466 +	SYSCALL( litmus_unlock(od) );
2467 +
2468 +	/* tasks may not unlock resources they don't own */
2469 +	SYSCALL_FAILS(EINVAL, litmus_unlock(od) );
2470 +
2471 +	SYSCALL( od_close(od) );
2472 +
2473 +	SYSCALL( close(fd) );
2474 +
2475 +	SYSCALL( remove(".fmlp_locks") );
2476 +}
2477 diff --git a/tests/make_catalog.py b/tests/make_catalog.py
2478 index 75b6aca..96f9b23 100755
2479 --- a/tests/make_catalog.py
2480 +++ b/tests/make_catalog.py
2481 @@ -63,6 +63,7 @@ def create_tc_tables(out=sys.stdout):
2482              plugins.add(p)
2483  
2484      plugins.discard('ALL')
2485 +    plugins.discard('LITMUS')
2486  
2487      _('#include "tests.h"')
2488  
2489 @@ -78,7 +79,9 @@ def create_tc_tables(out=sys.stdout):
2490          count = 0
2491          _('int %s_TESTS[] = {' % p)
2492          for (i, tc) in enumerate(tests):
2493 -            if p in tc.plugins or 'ALL' in tc.plugins:
2494 +            if p in tc.plugins or \
2495 +                    'ALL' in tc.plugins or \
2496 +                    'LITMUS' in tc.plugins and p != 'LINUX':
2497                  _('\t%d,' % i)
2498                  count += 1
2499          _('};')

Attached Files

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

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