Attachment 'liblitmus-semi-part-with-edfos.patch'

Download

   1 diff --git a/.gitignore b/.gitignore
   2 index f420aa3..3df27f8 100644
   3 --- a/.gitignore
   4 +++ b/.gitignore
   5 @@ -8,6 +8,10 @@ tests/__test_catalog.inc
   6  # executables
   7  runtests
   8  rt_launch
   9 +rt_launch_edffm
  10 +rt_launch_edfos
  11 +rt_launch_edfwm
  12 +rt_launch_npsf
  13  wait_test
  14  np_test
  15  stdump
  16 @@ -17,8 +21,14 @@ base_mt_task
  17  release_ts
  18  showst
  19  rtspin
  20 +rtspin_edffm
  21 +rtspin_edfos
  22 +rtspin_edfwm
  23 +rtspin_npsf
  24  cycles
  25  measure_syscall
  26 +npsf_add_server
  27 +
  28  
  29  # scons files
  30  .sconsign.dblite
  31 diff --git a/SConstruct b/SConstruct
  32 index c41e41e..617948d 100644
  33 --- a/SConstruct
  34 +++ b/SConstruct
  35 @@ -160,10 +160,10 @@ if not (env.GetOption('clean') or env.GetOption('help')):
  36          abort("Cannot find kernel headers in '$LITMUS_KERNEL'",
  37                "Please ensure that LITMUS_KERNEL in .config is set to a valid path.")
  38  
  39 -    conf.CheckCHeader('litmus/rt_param.h') or \
  40 -        abort("Cannot find LITMUS^RT headers in '$LITMUS_KERNEL'",
  41 -              "Please ensure sure that the kernel in '$LITMUS_KERNEL'"
  42 -              " is a LITMUS^RT kernel.")
  43 +#    conf.CheckCHeader('litmus/rt_param.h') or \
  44 +#        abort("Cannot find LITMUS^RT headers in '$LITMUS_KERNEL'",
  45 +#              "Please ensure sure that the kernel in '$LITMUS_KERNEL'"
  46 +#              " is a LITMUS^RT kernel.")
  47  
  48      conf.CheckSyscallNr() or \
  49          abort("The LITMUS^RT syscall numbers are not available.",
  50 @@ -208,6 +208,15 @@ rt.Program('base_task', 'bin/base_task.c')
  51  mtrt.Program('base_mt_task', 'bin/base_mt_task.c')
  52  rt.Program('rt_launch', ['bin/rt_launch.c', 'bin/common.c'])
  53  rt.Program('rtspin', ['bin/rtspin.c', 'bin/common.c'])
  54 +rt.Program('rtspin_edffm', ['bin/rtspin_edffm.c', 'bin/common.c'])
  55 +rt.Program('rtspin_edfos', ['bin/rtspin_edfos.c', 'bin/common.c'])
  56 +rt.Program('rt_launch_edffm', ['bin/rt_launch_edffm.c', 'bin/common.c'])
  57 +rt.Program('rt_launch_edfos', ['bin/rt_launch_edfos.c', 'bin/common.c'])
  58 +rt.Program('rtspin_npsf', ['bin/rtspin_npsf.c', 'bin/common.c'])
  59 +rt.Program('npsf_add_server', ['bin/npsf_add_server.c', 'bin/common.c'])
  60 +rt.Program('rt_launch_npsf', ['bin/rt_launch_npsf.c', 'bin/common.c'])
  61 +rt.Program('rtspin_edfwm', ['bin/rtspin_edfwm.c', 'bin/common.c'])
  62 +rt.Program('rt_launch_edfwm', ['bin/rt_launch_edfwm.c', 'bin/common.c'])
  63  rt.Program('release_ts', 'bin/release_ts.c')
  64  rtm.Program('measure_syscall', 'bin/null_call.c')
  65  
  66 diff --git a/bin/common.c b/bin/common.c
  67 index 452b882..167344a 100644
  68 --- a/bin/common.c
  69 +++ b/bin/common.c
  70 @@ -1,6 +1,7 @@
  71  #include <stdio.h>
  72  #include <stdlib.h>
  73  #include <errno.h>
  74 +#include <string.h>
  75  
  76  #include "common.h"
  77  
  78 @@ -9,3 +10,120 @@ void bail_out(const char* msg)
  79  	perror(msg);
  80  	exit(-1 * errno);
  81  }
  82 +
  83 +/* EDF-WM helper functions to parse a custom text file format to "easily"
  84 + * launch tests with rtspin and rt_launch:
  85 + *
  86 + * Format for task:
  87 + *
  88 + * <task_id execution_cost period phase cpu slices_number> .
  89 + *
  90 + * If the task is split on multiple slices, slices_number is non 0
  91 + * and we scan a list of slice parameters up to slices_number:
  92 + *
  93 + * Format for slices:
  94 + *
  95 + * <task_id cpu deadline(from job release) budget offset> .
  96 + *
  97 + * The offset is the start time for the slice relative to the job release.
  98 + *
  99 + * Example:
 100 + * 14 2.26245771754 10 0 5 2
 101 + * 14 5 5.000000 1.497306 0.000000
 102 + * 14 7 10.000000 0.765152 5.000000
 103 + */
 104 +
 105 +#define fms_to_ns(x)	(lt_t)(((x) * __NS_PER_MS))
 106 +/*
 107 + * <task_id, cpu, deadline (from job release), budget, offset> .
 108 + */
 109 +int parse_edfwm_slice(FILE *ts, int slices_no, int task_id,
 110 +		      struct rt_task *rt)
 111 +{
 112 +	int i, tid;
 113 +	unsigned int cpu;
 114 +	double deadline, budget, offset;
 115 +
 116 +	lt_t total_budget = 0;
 117 +
 118 +	struct edf_wm_params* wm = (struct edf_wm_params*) &rt->semi_part;
 119 +
 120 +	for (i = 0; i < slices_no; i++) {
 121 +
 122 +		if (fscanf(ts, "%d %u %lf %lf %lf\n", &tid, &cpu,
 123 +				&deadline, &budget, &offset) != EOF) {
 124 +
 125 +			if (task_id != tid) {
 126 +				fprintf(stderr, "task_id %d != tid %d\n",
 127 +						task_id, tid);
 128 +				return -1;
 129 +			}
 130 +
 131 +			wm->slices[i].deadline = fms_to_ns(deadline);
 132 +			wm->slices[i].budget = fms_to_ns(budget);
 133 +			wm->slices[i].offset = fms_to_ns(offset);
 134 +			wm->slices[i].cpu    = cpu;
 135 +
 136 +			printf("slice(tid, cpu, d, e, ph) = (%d, %u, %llu, %llu, %llu)\n",
 137 +					tid, cpu, wm->slices[i].deadline,
 138 +					wm->slices[i].budget, wm->slices[i].offset);
 139 +
 140 +			total_budget += wm->slices[i].budget;
 141 +			if (wm->slices[i].budget < MIN_EDF_WM_SLICE_SIZE) {
 142 +
 143 +				fprintf(stderr, "Slice %llu is too small\n",
 144 +						wm->slices[i].budget);
 145 +				return -1;
 146 +			}
 147 +		}
 148 +
 149 +		if (ferror(ts)) {
 150 +			fprintf(stderr, "Cannot read file\n");
 151 +			return -1;
 152 +		}
 153 +	}
 154 +	wm->count = slices_no;
 155 +	rt->exec_cost = total_budget;
 156 +	printf("--- total %u slices ---\n", wm->count);
 157 +	return 0;
 158 +}
 159 +
 160 +/*
 161 + * <task_id, execution_cost, period, phase, cpu, slices_number> .
 162 + */
 163 +int parse_edfwm_ts_file(FILE *ts, struct rt_task *rt)
 164 +{
 165 +	int task_id, ret = 1;
 166 +	unsigned int cpu, sliceno;
 167 +	double fwcet, fperiod, fphase;
 168 +
 169 +	ret = fscanf(ts, "%d %lf %lf %lf %d %d\n",
 170 +			&task_id, &fwcet, &fperiod, &fphase, &cpu, &sliceno);
 171 +
 172 +	if (ferror(ts))
 173 +		goto err;
 174 +
 175 +	rt->exec_cost = fms_to_ns(fwcet);
 176 +	rt->period = fms_to_ns(fperiod);
 177 +	rt->phase = fms_to_ns(fphase);
 178 +	rt->cpu = cpu;
 179 +	rt->cls = RT_CLASS_HARD;
 180 +	rt->budget_policy = PRECISE_ENFORCEMENT;
 181 +
 182 +	printf("(tid, wcet, period, ph, cpu, slices) = "
 183 +			"(%d, %llu, %llu, %llu, %u, %u)\n",
 184 +			task_id, rt->exec_cost, rt->period, rt->phase, cpu, sliceno);
 185 +	if (sliceno > 0) {
 186 +		memset(&rt->semi_part, 0, sizeof(struct edf_wm_params));
 187 +		ret = parse_edfwm_slice(ts, sliceno, task_id, rt);
 188 +		if (ret < 0)
 189 +			goto err;
 190 +	}
 191 +
 192 +	return 0;
 193 +
 194 +err:
 195 +	fprintf(stderr, "Error parsing file\n");
 196 +	return -1;
 197 +}
 198 +
 199 diff --git a/bin/npsf_add_server.c b/bin/npsf_add_server.c
 200 new file mode 100644
 201 index 0000000..9f3f92c
 202 --- /dev/null
 203 +++ b/bin/npsf_add_server.c
 204 @@ -0,0 +1,108 @@
 205 +/* wrapper for sys_add_server
 206 + *
 207 + * Input: a file with on each line:
 208 + * npsf_id cpu budget(us)
 209 + */
 210 +#include <stdio.h>
 211 +#include <stdlib.h>
 212 +#include <unistd.h>
 213 +
 214 +#include "litmus.h"
 215 +#include "common.h"
 216 +
 217 +void usage(char *error) {
 218 +	fprintf(stderr, "Error: %s\n", error);
 219 +	fprintf(stderr,
 220 +		"Usage: npsf_add_server SERVERS-FILE MAX-SPLITS-PER-NPSFID\n");
 221 +	exit(1);
 222 +}
 223 +
 224 +int main(int argc, char** argv)
 225 +{
 226 +	int ret;
 227 +	FILE *file;
 228 +	int i,j;
 229 +	int npsf_id, curr_id = -1;
 230 +	int cpu, max_splits_server;
 231 +	int budget_us;
 232 +	struct npsf_budgets *budgets;
 233 +
 234 +	if (argc < 3)
 235 +		usage("Arguments missing.");
 236 +
 237 +	max_splits_server = atoi(argv[2]);
 238 +
 239 +	if ((file = fopen(argv[1], "r")) == NULL) {
 240 +		fprintf(stderr, "Cannot open %s\n", argv[1]);
 241 +		return -1;
 242 +	}
 243 +
 244 +	/* format: npsf_id cpu budget-us */
 245 +	i = 0;
 246 +	while (fscanf(file, "%d %d %d\n", &npsf_id, &cpu, &budget_us) != EOF) {
 247 +
 248 +		printf("Read: %d %d %d\n", npsf_id, cpu, budget_us);
 249 +
 250 +		if (curr_id == -1) {
 251 +			curr_id = npsf_id;
 252 +			budgets = malloc(max_splits_server *
 253 +					sizeof(struct npsf_budgets));
 254 +			for(j = 0; j < max_splits_server; j++) {
 255 +				budgets[j].cpu = -1;
 256 +				budgets[j].budget = 0;
 257 +			}
 258 +		}
 259 +
 260 +		if (npsf_id == curr_id) {
 261 +			/* same notional processor, different cpu and budget */
 262 +			budgets[i].cpu = cpu;
 263 +			budgets[i].budget = (lt_t) (budget_us * 1000);
 264 +			i++;
 265 +		} else {
 266 +			/* different notional processor */
 267 +			/* add server */
 268 +			printf("Adding npsf_id = %d\n", curr_id);
 269 +			ret = add_server(&curr_id, budgets, 0);
 270 +
 271 +			if (ret < 0) {
 272 +				fclose(file);
 273 +				free(budgets);
 274 +				printf("Cannot add Notional Processor %d\n",
 275 +						curr_id);
 276 +				return ret;
 277 +			}
 278 +
 279 +			/* reinit new */
 280 +			i = 0;
 281 +			budgets = malloc(max_splits_server *
 282 +					sizeof(struct npsf_budgets));
 283 +			for(j = 0; j < max_splits_server; j++) {
 284 +				budgets[j].cpu = -1;
 285 +				budgets[j].budget = 0;
 286 +			}
 287 +			curr_id = npsf_id;
 288 +			budgets[i].cpu = cpu;
 289 +			budgets[i].budget = (lt_t) (budget_us * 1000);
 290 +			i++;
 291 +		}
 292 +	}
 293 +
 294 +	if (ferror(file)) {
 295 +		fprintf(stderr, "Error while reading\n");
 296 +		fclose(file);
 297 +		return -1;
 298 +	}
 299 +
 300 +	/* save the last entry */
 301 +	ret = add_server(&curr_id, budgets, 1);
 302 +	printf("Adding npsf_id = %d\n", curr_id);
 303 +	if (ret < 0) {
 304 +		fclose(file);
 305 +		free(budgets);
 306 +		bail_out("Cannot add Notional Processor: ");
 307 +	}
 308 +
 309 +	fclose(file);
 310 +
 311 +	return 0;
 312 +}
 313 diff --git a/bin/rt_launch_edffm.c b/bin/rt_launch_edffm.c
 314 new file mode 100644
 315 index 0000000..ddde7dd
 316 --- /dev/null
 317 +++ b/bin/rt_launch_edffm.c
 318 @@ -0,0 +1,133 @@
 319 +#include <stdio.h>
 320 +#include <stdlib.h>
 321 +#include <string.h>
 322 +#include <unistd.h>
 323 +#include <limits.h>
 324 +#include <signal.h>
 325 +
 326 +#include "litmus.h"
 327 +#include "common.h"
 328 +
 329 +typedef struct {
 330 +	int  wait;
 331 +	char * exec_path;
 332 +	char ** argv;
 333 +} startup_info_t;
 334 +
 335 +
 336 +int launch(void *task_info_p) {
 337 +	startup_info_t *info = (startup_info_t*) task_info_p;
 338 +	int ret;
 339 +	if (info->wait) {
 340 +		ret = wait_for_ts_release();
 341 +		if (ret != 0)
 342 +			perror("wait_for_ts_release()");
 343 +	}
 344 +	ret = execvp(info->exec_path, info->argv);
 345 +	perror("execv failed");
 346 +	return ret;
 347 +}
 348 +
 349 +void usage(char *error) {
 350 +	fprintf(stderr, "%s\nUsage: rt_launch [-w][-v][-p cpu][-c hrt | srt | be] wcet period"
 351 +			" fracnum1 fracden1 cpu1 fracnum2 fracden2 cpu2 program [arg1 arg2 ...]\n"
 352 +			"\t-w\tSynchronous release\n"
 353 +			"\t-v\tVerbose\n"
 354 +			"\t-p\tcpu (or initial cpu)\n"
 355 +			"\t-c\tClass\n"
 356 +			"\twcet, period in ms\n"
 357 +			"\tprogram to be launched\n",
 358 +			error);
 359 +	exit(1);
 360 +}
 361 +
 362 +
 363 +#define OPTSTR "p:c:vw"
 364 +
 365 +int main(int argc, char** argv) 
 366 +{
 367 +	int ret;
 368 +	lt_t wcet;
 369 +	lt_t period;
 370 +	/* [num,den] */
 371 +	lt_t frac1[2], frac2[2];
 372 +	int cpu1, cpu2;
 373 +	int migrate = 0;
 374 +	int cpu = 0;
 375 +	int opt;
 376 +	int verbose = 0;
 377 +	int wait = 0;
 378 +	startup_info_t info;
 379 +	task_class_t class = RT_CLASS_HARD;
 380 +
 381 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
 382 +		switch (opt) {
 383 +		case 'w':
 384 +			wait = 1;
 385 +			break;
 386 +		case 'v':
 387 +			verbose = 1;
 388 +			break;
 389 +		case 'p':
 390 +			cpu = atoi(optarg);
 391 +			migrate = 1;
 392 +			break;
 393 +		case 'c':
 394 +			class = str2class(optarg);
 395 +			if (class == -1)
 396 +				usage("Unknown task class.");
 397 +			break;
 398 +
 399 +		case ':':
 400 +			usage("Argument missing.");
 401 +			break;
 402 +		case '?':
 403 +		default:
 404 +			usage("Bad argument.");
 405 +			break;
 406 +		}
 407 +	}
 408 +
 409 +	signal(SIGUSR1, SIG_IGN);
 410 +
 411 +	if (argc - optind < 8)
 412 +		usage("Arguments missing.");
 413 +	wcet   = ms2lt(atoi(argv[optind + 0]));
 414 +	period = ms2lt(atoi(argv[optind + 1]));
 415 +	/* frac num, den = 0 means fixed task */
 416 +	frac1[0]  = atoi(argv[optind + 2]);
 417 +	frac1[1]  = atoi(argv[optind + 3]);
 418 +	cpu1 	  = atoi(argv[optind + 4]);
 419 +	frac2[0]  = atoi(argv[optind + 5]);
 420 +	frac2[1]  = atoi(argv[optind + 6]);
 421 +	cpu2	  = atoi(argv[optind + 7]);
 422 +	if (wcet <= 0)
 423 +	usage("The worst-case execution time must be a "
 424 +	      "positive number.");
 425 +	if (period <= 0)
 426 +		usage("The period must be a positive number.");
 427 +	if (wcet > period) {
 428 +		usage("The worst-case execution time must not "
 429 +		      "exceed the period.");
 430 +	}
 431 +	info.exec_path = argv[optind + 8];
 432 +	info.argv      = argv + optind + 8;
 433 +	info.wait      = wait;
 434 +	if (migrate) {
 435 +		ret = be_migrate_to(cpu);
 436 +		if (ret < 0)
 437 +			bail_out("could not migrate to target partition");
 438 +	}
 439 +	/* create in src/task.c a new wrapper for the __launch_rt_task
 440 +	 * which takes the fraction and the cpus */
 441 +	ret = __create_rt_task_edffm(launch, &info, cpu, wcet, period, frac1,
 442 +			frac2, cpu1, cpu2, class);
 443 +
 444 +
 445 +	if (ret < 0)
 446 +		bail_out("could not create rt child process");
 447 +	else if (verbose)
 448 +		printf("%d\n", ret);
 449 +
 450 +	return 0;
 451 +}
 452 diff --git a/bin/rt_launch_edfos.c b/bin/rt_launch_edfos.c
 453 new file mode 100644
 454 index 0000000..2b26fb2
 455 --- /dev/null
 456 +++ b/bin/rt_launch_edfos.c
 457 @@ -0,0 +1,135 @@
 458 +#include <stdio.h>
 459 +#include <stdlib.h>
 460 +#include <string.h>
 461 +#include <unistd.h>
 462 +#include <limits.h>
 463 +#include <signal.h>
 464 +
 465 +#include "litmus.h"
 466 +#include "common.h"
 467 +
 468 +typedef struct {
 469 +	int  wait;
 470 +	char * exec_path;
 471 +	char ** argv;
 472 +} startup_info_t;
 473 +
 474 +
 475 +int launch(void *task_info_p) {
 476 +	startup_info_t *info = (startup_info_t*) task_info_p;
 477 +	int ret;
 478 +	if (info->wait) {
 479 +		ret = wait_for_ts_release();
 480 +		if (ret != 0)
 481 +			perror("wait_for_ts_release()");
 482 +	}
 483 +	ret = execvp(info->exec_path, info->argv);
 484 +	perror("execv failed");
 485 +	return ret;
 486 +}
 487 +
 488 +void usage(char *error) {
 489 +	fprintf(stderr, "%s\nUsage: rt_launch [-w][-v][-p cpu][-c hrt | srt | be] wcet period"
 490 +			" fracnum1 fracden1 cpu1 fracnum2 fracden2 cpu2 program [arg1 arg2 ...]\n"
 491 +			"\t-w\tSynchronous release\n"
 492 +			"\t-v\tVerbose\n"
 493 +			"\t-p\tcpu (or initial cpu)\n"
 494 +			"\t-c\tClass\n"
 495 +			"\twcet, period in ms\n"
 496 +			"\tprogram to be launched\n",
 497 +			error);
 498 +	exit(1);
 499 +}
 500 +
 501 +
 502 +#define OPTSTR "p:c:vw"
 503 +
 504 +int main(int argc, char** argv) 
 505 +{
 506 +	int ret;
 507 +	lt_t wcet;
 508 +	lt_t period;
 509 +	/* [num,den] */
 510 +	lt_t fracs[NR_CPUS_EDF_OS][2];
 511 +	int cpu = -1;
 512 +	int opt;
 513 +	int verbose = 0;
 514 +	int wait = 0;
 515 +	int i;
 516 +	startup_info_t info;
 517 +	task_class_t class = RT_CLASS_HARD;
 518 +
 519 +	for (i = 0; i < NR_CPUS_EDF_OS; i++) {
 520 +		fracs[i][0] = 0;
 521 +		fracs[i][1] = 0;
 522 +	}
 523 +
 524 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
 525 +		switch (opt) {
 526 +		case 'w':
 527 +			wait = 1;
 528 +			break;
 529 +		case 'v':
 530 +			verbose = 1;
 531 +			break;
 532 +		case 'p':
 533 +			cpu = atoi(optarg);
 534 +			fracs[cpu][0] = 1;
 535 +			fracs[cpu][1] = 1;
 536 +			break;
 537 +		case 'c':
 538 +			class = str2class(optarg);
 539 +			if (class == -1)
 540 +				usage("Unknown task class.");
 541 +			break;
 542 +		case ':':
 543 +			usage("Argument missing.");
 544 +			break;
 545 +		case '?':
 546 +		default:
 547 +			usage("Bad argument.");
 548 +			break;
 549 +		}
 550 +	}
 551 +
 552 +	signal(SIGUSR1, SIG_IGN);
 553 +
 554 +	if ((argc - (optind + 2)) % 3 != 0)
 555 +		usage("Arguments missing.");
 556 +	wcet   = ms2lt(atoi(argv[optind + 0]));
 557 +	period = ms2lt(atoi(argv[optind + 1]));
 558 +
 559 +	for (i = optind + 1; i < argc; i+= 3) {
 560 +		cpu = atoi(argv[i+2]);
 561 +		fracs[cpu][0] = atoi(argv[i]);
 562 +		fracs[cpu][1] = atoi(argv[i+1]);
 563 +	}
 564 +	if (cpu == -1)
 565 +		cpu = compute_initial_cpu_edfos(fracs);
 566 +	if (wcet <= 0)
 567 +		usage("The worst-case execution time must be a "
 568 +		      "positive number.");
 569 +	if (period <= 0)
 570 +		usage("The period must be a positive number.");
 571 +	if (wcet > period) {
 572 +		usage("The worst-case execution time must not "
 573 +		      "exceed the period.");
 574 +	}
 575 +	info.exec_path = argv[optind + 8];
 576 +	info.argv      = argv + optind + 8;
 577 +	info.wait      = wait;
 578 +	ret = be_migrate_to(cpu);
 579 +	if (ret < 0)
 580 +		bail_out("could not migrate to target partition");
 581 +	/* create in src/task.c a new wrapper for the __launch_rt_task
 582 +	 * which takes the fraction and the cpus */
 583 +	ret = __create_rt_task_edfos(launch, &info, cpu, wcet, period, fracs,
 584 +			class);
 585 +
 586 +	if (ret < 0)
 587 +		bail_out("could not create rt child process");
 588 +	else if (verbose)
 589 +		printf("%d\n", ret);
 590 +
 591 +	return 0;
 592 +}
 593 diff --git a/bin/rt_launch_edfwm.c b/bin/rt_launch_edfwm.c
 594 new file mode 100644
 595 index 0000000..9e8a322
 596 --- /dev/null
 597 +++ b/bin/rt_launch_edfwm.c
 598 @@ -0,0 +1,98 @@
 599 +#include <stdio.h>
 600 +#include <stdlib.h>
 601 +#include <string.h>
 602 +#include <unistd.h>
 603 +#include <limits.h>
 604 +#include <signal.h>
 605 +
 606 +#include "litmus.h"
 607 +#include "common.h"
 608 +
 609 +typedef struct {
 610 +	int  wait;
 611 +	char * exec_path;
 612 +	char ** argv;
 613 +} startup_info_t;
 614 +
 615 +
 616 +int launch(void *task_info_p) {
 617 +	startup_info_t *info = (startup_info_t*) task_info_p;
 618 +	int ret;
 619 +	if (info->wait) {
 620 +		ret = wait_for_ts_release();
 621 +		if (ret != 0)
 622 +			perror("wait_for_ts_release()");
 623 +	}
 624 +	ret = execvp(info->exec_path, info->argv);
 625 +	perror("execv failed");
 626 +	return ret;
 627 +}
 628 +
 629 +void usage(char *error) {
 630 +	fprintf(stderr, "%s\nUsage: rt_launch [-w] task_parameters_file "
 631 +			"program [arg1 arg2 ...]\n"
 632 +			"\t-w\tSynchronous release\n"
 633 +			"\tprogram to be launched\n",
 634 +			error);
 635 +	exit(1);
 636 +}
 637 +
 638 +#define OPTSTR "w"
 639 +
 640 +int main(int argc, char** argv)
 641 +{
 642 +	int ret;
 643 +	int wait = 0;
 644 +	int opt;
 645 +	startup_info_t info;
 646 +
 647 +	struct rt_task rt;
 648 +	FILE *file;
 649 +
 650 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
 651 +		switch (opt) {
 652 +		case 'w':
 653 +			wait = 1;
 654 +			break;
 655 +		case ':':
 656 +			usage("Argument missing.");
 657 +			break;
 658 +		case '?':
 659 +		default:
 660 +			usage("Bad argument.");
 661 +			break;
 662 +		}
 663 +	}
 664 +
 665 +	signal(SIGUSR1, SIG_IGN);
 666 +
 667 +	if (argc - optind < 2)
 668 +		usage("Arguments missing.");
 669 +
 670 +	if ((file = fopen(argv[optind + 0], "r")) == NULL) {
 671 +		fprintf(stderr, "Cannot open %s\n", argv[1]);
 672 +		return -1;
 673 +	}
 674 +
 675 +	memset(&rt, 0, sizeof(struct rt_task));
 676 +
 677 +	if (parse_edfwm_ts_file(file, &rt) < 0)
 678 +		bail_out("Could not parse file\n");
 679 +
 680 +	if (sporadic_task_ns_semi(&rt) < 0)
 681 +		bail_out("could not setup rt task params");
 682 +
 683 +	fclose(file);
 684 +
 685 +	info.exec_path = argv[optind + 1];
 686 +	info.argv      = argv + optind + 1;
 687 +	info.wait      = wait;
 688 +
 689 +	ret = create_rt_task_semi(launch, &info, &rt);
 690 +
 691 +	if (ret < 0)
 692 +		bail_out("could not create rt child process");
 693 +
 694 +	return 0;
 695 +}
 696 +
 697 diff --git a/bin/rt_launch_npsf.c b/bin/rt_launch_npsf.c
 698 new file mode 100644
 699 index 0000000..97ad361
 700 --- /dev/null
 701 +++ b/bin/rt_launch_npsf.c
 702 @@ -0,0 +1,110 @@
 703 +#include <stdio.h>
 704 +#include <stdlib.h>
 705 +#include <string.h>
 706 +#include <unistd.h>
 707 +#include <limits.h>
 708 +#include <signal.h>
 709 +
 710 +#include "litmus.h"
 711 +#include "common.h"
 712 +
 713 +typedef struct {
 714 +	int  wait;
 715 +	char * exec_path;
 716 +	char ** argv;
 717 +} startup_info_t;
 718 +
 719 +
 720 +int launch(void *task_info_p) {
 721 +	startup_info_t *info = (startup_info_t*) task_info_p;
 722 +	int ret;
 723 +	if (info->wait) {
 724 +		ret = wait_for_ts_release();
 725 +		if (ret != 0)
 726 +			perror("wait_for_ts_release()");
 727 +	}
 728 +	ret = execvp(info->exec_path, info->argv);
 729 +	perror("execv failed");
 730 +	return ret;
 731 +}
 732 +
 733 +void usage(char *error) {
 734 +	fprintf(stderr, "%s\nUsage: rt_launch [-w][-v] wcet period cpu npsf-id program [arg1 arg2 ...]\n"
 735 +			"\t-w\tSynchronous release\n"
 736 +			"\t-v\tVerbose\n"
 737 +			"\twcet, period in ms\n"
 738 +			"\tprogram to be launched\n",
 739 +			error);
 740 +	exit(1);
 741 +}
 742 +
 743 +
 744 +#define OPTSTR "vw"
 745 +
 746 +int main(int argc, char** argv)
 747 +{
 748 +	int ret;
 749 +	lt_t wcet;
 750 +	lt_t period;
 751 +	int migrate = 0;
 752 +	int cpu = 0;
 753 +	int npsf_id;
 754 +	int opt;
 755 +	int verbose = 0;
 756 +	int wait = 0;
 757 +	startup_info_t info;
 758 +
 759 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
 760 +		switch (opt) {
 761 +		case 'w':
 762 +			wait = 1;
 763 +			break;
 764 +		case 'v':
 765 +			verbose = 1;
 766 +			break;
 767 +		case ':':
 768 +			usage("Argument missing.");
 769 +			break;
 770 +		case '?':
 771 +		default:
 772 +			usage("Bad argument.");
 773 +			break;
 774 +		}
 775 +	}
 776 +
 777 +	signal(SIGUSR1, SIG_IGN);
 778 +
 779 +	if (argc - optind < 5)
 780 +		usage("Arguments missing.");
 781 +	wcet   = ms2lt(atoi(argv[optind + 0]));
 782 +	period = ms2lt(atoi(argv[optind + 1]));
 783 +	cpu = atoi(argv[optind + 2]);
 784 +	migrate = 1;
 785 +	npsf_id = atoi(argv[optind + 3]);
 786 +	if (wcet <= 0)
 787 +	usage("The worst-case execution time must be a "
 788 +	      "positive number.");
 789 +	if (period <= 0)
 790 +		usage("The period must be a positive number.");
 791 +	if (wcet > period) {
 792 +		usage("The worst-case execution time must not "
 793 +		      "exceed the period.");
 794 +	}
 795 +	info.exec_path = argv[optind + 4];
 796 +	info.argv      = argv + optind + 4;
 797 +	info.wait      = wait;
 798 +	if (migrate) {
 799 +		ret = be_migrate_to(cpu);
 800 +		if (ret < 0)
 801 +			bail_out("could not migrate to target partition");
 802 +	}
 803 +	ret = __create_rt_task_npsf(launch, &info, cpu, wcet, period, npsf_id, RT_CLASS_HARD);
 804 +
 805 +
 806 +	if (ret < 0)
 807 +		bail_out("could not create rt child process");
 808 +	else if (verbose)
 809 +		printf("%d\n", ret);
 810 +
 811 +	return 0;
 812 +}
 813 diff --git a/bin/rtspin_edffm.c b/bin/rtspin_edffm.c
 814 new file mode 100644
 815 index 0000000..5db79b8
 816 --- /dev/null
 817 +++ b/bin/rtspin_edffm.c
 818 @@ -0,0 +1,263 @@
 819 +#include <sys/time.h>
 820 +
 821 +#include <stdio.h>
 822 +#include <stdlib.h>
 823 +#include <unistd.h>
 824 +#include <time.h>
 825 +
 826 +
 827 +#include "litmus.h"
 828 +#include "common.h"
 829 +
 830 +
 831 +static double cputime()
 832 +{
 833 +	struct timespec ts;
 834 +	int err;
 835 +	err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
 836 +	if (err != 0)
 837 +		perror("clock_gettime");
 838 +	return (ts.tv_sec + 1E-9 * ts.tv_nsec);
 839 +}
 840 +
 841 +static double wctime()
 842 +{
 843 +	struct timeval tv;
 844 +	gettimeofday(&tv, NULL);
 845 +	return (tv.tv_sec + 1E-6 * tv.tv_usec);
 846 +}
 847 +
 848 +void usage(char *error) {
 849 +	fprintf(stderr, "Error: %s\n", error);
 850 +	fprintf(stderr,
 851 +		"Usage: rt_spin [-w] [-p PARTITION] [-c CLASS] WCET PERIOD DURATION fracnum1 fracden1 cpu1 fracnum2 fracden2 cpu2\n"
 852 +		"       rt_spin -l\n");
 853 +	exit(1);
 854 +}
 855 +
 856 +#define NUMS 4096
 857 +static int num[NUMS];
 858 +static double loop_length = 1.0;
 859 +static char* progname;
 860 +
 861 +static int loop_once(void)
 862 +{
 863 +	int i, j = 0;
 864 +	for (i = 0; i < NUMS; i++)
 865 +		j += num[i]++;
 866 +	return j;
 867 +}
 868 +
 869 +static int loop_for(double exec_time)
 870 +{
 871 +	double t = 0;
 872 +	int tmp = 0;
 873 +/*	while (t + loop_length < exec_time) {
 874 +		tmp += loop_once();
 875 +		t += loop_length;
 876 +	}
 877 +*/
 878 +	double start = cputime();
 879 +	double now = cputime();
 880 +	while (now + loop_length < start + exec_time) {
 881 +		tmp += loop_once();
 882 +		t += loop_length;
 883 +		now = cputime();
 884 +	}
 885 +
 886 +	return tmp;
 887 +}
 888 +
 889 +static void fine_tune(double interval)
 890 +{
 891 +	double start, end, delta;
 892 +
 893 +	start = wctime();
 894 +	loop_for(interval);
 895 +	end = wctime();
 896 +	delta = (end - start - interval) / interval;
 897 +	if (delta != 0)
 898 +		loop_length = loop_length / (1 - delta);
 899 +}
 900 +
 901 +static void configure_loop(void)
 902 +{
 903 +	double start;
 904 +
 905 +	/* prime cache */
 906 +	loop_once();
 907 +	loop_once();
 908 +	loop_once();
 909 +
 910 +	/* measure */
 911 +	start = wctime();
 912 +	loop_once(); /* hope we didn't get preempted  */
 913 +	loop_length = wctime();
 914 +	loop_length -= start;
 915 +
 916 +	/* fine tune */
 917 +	fine_tune(0.1);
 918 +	fine_tune(0.1);
 919 +	fine_tune(0.1);
 920 +}
 921 +
 922 +static void show_loop_length(void)
 923 +{
 924 +	printf("%s/%d: loop_length=%f (%ldus)\n",
 925 +	       progname, getpid(), loop_length,
 926 +	       (long) (loop_length * 1000000));
 927 +}
 928 +
 929 +static void debug_delay_loop(void)
 930 +{
 931 +	double start, end, delay;
 932 +	show_loop_length();
 933 +	while (1) {
 934 +		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
 935 +			start = wctime();
 936 +			loop_for(delay);
 937 +			end = wctime();
 938 +			printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
 939 +			       delay,
 940 +			       end - start,
 941 +			       end - start - delay,
 942 +			       100 * (end - start - delay) / delay);
 943 +		}
 944 +	}
 945 +}
 946 +
 947 +static int job(double exec_time)
 948 +{
 949 +	loop_for(exec_time);
 950 +	sleep_next_period();
 951 +	return 0;
 952 +}
 953 +
 954 +#define OPTSTR "p:c:wld:v"
 955 +
 956 +int main(int argc, char** argv)
 957 +{
 958 +	int ret;
 959 +	lt_t wcet;
 960 +	lt_t period;
 961 +	/* [num,den] */
 962 +	lt_t frac1[2], frac2[2];
 963 +	int cpu1, cpu2;
 964 +	double wcet_ms, period_ms;
 965 +	int migrate = 0;
 966 +	int cpu = 0;
 967 +	int opt;
 968 +	int wait = 0;
 969 +	int test_loop = 0;
 970 +	int skip_config = 0;
 971 +	int verbose = 0;
 972 +	double duration, start;
 973 +	task_class_t class = RT_CLASS_HARD;
 974 +
 975 +	progname = argv[0];
 976 +
 977 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
 978 +		switch (opt) {
 979 +		case 'w':
 980 +			wait = 1;
 981 +			break;
 982 +		case 'p':
 983 +			cpu = atoi(optarg);
 984 +			migrate = 1;
 985 +			break;
 986 +		case 'c':
 987 +			class = str2class(optarg);
 988 +			if (class == -1)
 989 +				usage("Unknown task class.");
 990 +			break;
 991 +		case 'l':
 992 +			test_loop = 1;
 993 +			break;
 994 +		case 'd':
 995 +			/* manually configure delay per loop iteration
 996 +			 * unit: microseconds */
 997 +			loop_length = atof(optarg) / 1000000;
 998 +			skip_config = 1;
 999 +			break;
1000 +		case 'v':
1001 +			verbose = 1;
1002 +			break;
1003 +		case ':':
1004 +			usage("Argument missing.");
1005 +			break;
1006 +		case '?':
1007 +		default:
1008 +			usage("Bad argument.");
1009 +			break;
1010 +		}
1011 +	}
1012 +
1013 +
1014 +	if (!skip_config)
1015 +		configure_loop();
1016 +
1017 +	if (test_loop) {
1018 +		debug_delay_loop();
1019 +		return 0;
1020 +	}
1021 +
1022 +	if (argc - optind < 9)
1023 +		usage("Arguments missing.");
1024 +	wcet_ms   = atof(argv[optind + 0]);
1025 +	period_ms = atof(argv[optind + 1]);
1026 +	duration  = atof(argv[optind + 2]);
1027 +	/* frac num, den = 0 means fixed task */
1028 +	frac1[0]  = atoi(argv[optind + 3]);
1029 +	frac1[1]  = atoi(argv[optind + 4]);
1030 +	cpu1 	  = atoi(argv[optind + 5]);
1031 +	frac2[0]  = atoi(argv[optind + 6]);
1032 +	frac2[1]  = atoi(argv[optind + 7]);
1033 +	cpu2	  = atoi(argv[optind + 8]);
1034 +	wcet   = wcet_ms * __NS_PER_MS;
1035 +	period = period_ms * __NS_PER_MS;
1036 +	if (wcet <= 0)
1037 +		usage("The worst-case execution time must be a "
1038 +		      "positive number.");
1039 +	if (period <= 0)
1040 +		usage("The period must be a positive number.");
1041 +	if (wcet > period) {
1042 +		usage("The worst-case execution time must not "
1043 +		      "exceed the period.");
1044 +	}
1045 +
1046 +	if (migrate) {
1047 +		ret = be_migrate_to(cpu);
1048 +		if (ret < 0)
1049 +			bail_out("could not migrate to target partition");
1050 +	}
1051 +
1052 +	ret = sporadic_task_ns_edffm(wcet, period, 0, cpu,
1053 +			frac1, frac2, cpu1, cpu2,
1054 +			class, NO_ENFORCEMENT, migrate);
1055 +
1056 +	if (ret < 0)
1057 +		bail_out("could not setup rt task params");
1058 +
1059 +	if (verbose)
1060 +		show_loop_length();
1061 +
1062 +	init_litmus();
1063 +
1064 +	ret = task_mode(LITMUS_RT_TASK);
1065 +	if (ret != 0)
1066 +		bail_out("could not become RT task");
1067 +
1068 +	if (wait) {
1069 +		ret = wait_for_ts_release();
1070 +		if (ret != 0)
1071 +			bail_out("wait_for_ts_release()");
1072 +	}
1073 +
1074 +	start = wctime();
1075 +
1076 +	while (start + duration > wctime()) {
1077 +		job(wcet_ms * 0.0009); /* 90% wcet, in seconds */
1078 +	}
1079 +
1080 +	return 0;
1081 +}
1082 diff --git a/bin/rtspin_edfos.c b/bin/rtspin_edfos.c
1083 new file mode 100644
1084 index 0000000..3ea41c7
1085 --- /dev/null
1086 +++ b/bin/rtspin_edfos.c
1087 @@ -0,0 +1,267 @@
1088 +#include <sys/time.h>
1089 +
1090 +#include <stdio.h>
1091 +#include <stdlib.h>
1092 +#include <unistd.h>
1093 +#include <time.h>
1094 +
1095 +
1096 +#include "litmus.h"
1097 +#include "common.h"
1098 +
1099 +
1100 +static double cputime()
1101 +{
1102 +	struct timespec ts;
1103 +	int err;
1104 +	err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
1105 +	if (err != 0)
1106 +		perror("clock_gettime");
1107 +	return (ts.tv_sec + 1E-9 * ts.tv_nsec);
1108 +}
1109 +
1110 +static double wctime()
1111 +{
1112 +	struct timeval tv;
1113 +	gettimeofday(&tv, NULL);
1114 +	return (tv.tv_sec + 1E-6 * tv.tv_usec);
1115 +}
1116 +
1117 +void usage(char *error) {
1118 +	fprintf(stderr, "Error: %s\n", error);
1119 +	fprintf(stderr,
1120 +		"Usage: rt_spin [-w] [-p PARTITION] [-c CLASS] WCET PERIOD DURATION fracnum1 fracden1 cpu1 fracnum2 fracden2 cpu2\n"
1121 +		"       rt_spin -l\n");
1122 +	exit(1);
1123 +}
1124 +
1125 +#define NUMS 4096
1126 +static int num[NUMS];
1127 +static double loop_length = 1.0;
1128 +static char* progname;
1129 +
1130 +static int loop_once(void)
1131 +{
1132 +	int i, j = 0;
1133 +	for (i = 0; i < NUMS; i++)
1134 +		j += num[i]++;
1135 +	return j;
1136 +}
1137 +
1138 +static int loop_for(double exec_time)
1139 +{
1140 +	double t = 0;
1141 +	int tmp = 0;
1142 +/*	while (t + loop_length < exec_time) {
1143 +		tmp += loop_once();
1144 +		t += loop_length;
1145 +	}
1146 +*/
1147 +	double start = cputime();
1148 +	double now = cputime();
1149 +	while (now + loop_length < start + exec_time) {
1150 +		tmp += loop_once();
1151 +		t += loop_length;
1152 +		now = cputime();
1153 +	}
1154 +
1155 +	return tmp;
1156 +}
1157 +
1158 +static void fine_tune(double interval)
1159 +{
1160 +	double start, end, delta;
1161 +
1162 +	start = wctime();
1163 +	loop_for(interval);
1164 +	end = wctime();
1165 +	delta = (end - start - interval) / interval;
1166 +	if (delta != 0)
1167 +		loop_length = loop_length / (1 - delta);
1168 +}
1169 +
1170 +static void configure_loop(void)
1171 +{
1172 +	double start;
1173 +
1174 +	/* prime cache */
1175 +	loop_once();
1176 +	loop_once();
1177 +	loop_once();
1178 +
1179 +	/* measure */
1180 +	start = wctime();
1181 +	loop_once(); /* hope we didn't get preempted  */
1182 +	loop_length = wctime();
1183 +	loop_length -= start;
1184 +
1185 +	/* fine tune */
1186 +	fine_tune(0.1);
1187 +	fine_tune(0.1);
1188 +	fine_tune(0.1);
1189 +}
1190 +
1191 +static void show_loop_length(void)
1192 +{
1193 +	printf("%s/%d: loop_length=%f (%ldus)\n",
1194 +	       progname, getpid(), loop_length,
1195 +	       (long) (loop_length * 1000000));
1196 +}
1197 +
1198 +static void debug_delay_loop(void)
1199 +{
1200 +	double start, end, delay;
1201 +	show_loop_length();
1202 +	while (1) {
1203 +		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
1204 +			start = wctime();
1205 +			loop_for(delay);
1206 +			end = wctime();
1207 +			printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
1208 +			       delay,
1209 +			       end - start,
1210 +			       end - start - delay,
1211 +			       100 * (end - start - delay) / delay);
1212 +		}
1213 +	}
1214 +}
1215 +
1216 +static int job(double exec_time)
1217 +{
1218 +	loop_for(exec_time);
1219 +	sleep_next_period();
1220 +	return 0;
1221 +}
1222 +
1223 +#define OPTSTR "p:c:wld:v"
1224 +
1225 +int main(int argc, char** argv)
1226 +{
1227 +	int ret;
1228 +	lt_t wcet;
1229 +	lt_t period;
1230 +	/* [num,den] */
1231 +	lt_t fracs[NR_CPUS_EDF_OS][2];
1232 +	double wcet_ms, period_ms;
1233 +	int cpu = -1;
1234 +	int ccpu;
1235 +	int opt;
1236 +	int wait = 0;
1237 +	int test_loop = 0;
1238 +	int skip_config = 0;
1239 +	int verbose = 0;
1240 +	int i;
1241 +	double duration, start;
1242 +	task_class_t class = RT_CLASS_HARD;
1243 +
1244 +	progname = argv[0];
1245 +
1246 +	for (i = 0; i < NR_CPUS_EDF_OS; i++) {
1247 +		fracs[i][0] = 0;
1248 +		fracs[i][1] = 0;
1249 +	}
1250 +
1251 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1252 +		switch (opt) {
1253 +		case 'w':
1254 +			wait = 1;
1255 +			break;
1256 +		case 'p':
1257 +			cpu = atoi(optarg);
1258 +			fracs[cpu][0] = 1;
1259 +			fracs[cpu][1] = 1;
1260 +			break;
1261 +		case 'c':
1262 +			class = str2class(optarg);
1263 +			if (class == -1)
1264 +				usage("Unknown task class.");
1265 +			break;
1266 +		case 'l':
1267 +			test_loop = 1;
1268 +			break;
1269 +		case 'd':
1270 +			/* manually configure delay per loop iteration
1271 +			 * unit: microseconds */
1272 +			loop_length = atof(optarg) / 1000000;
1273 +			skip_config = 1;
1274 +			break;
1275 +		case 'v':
1276 +			verbose = 1;
1277 +			break;
1278 +		case ':':
1279 +			usage("Argument missing.");
1280 +			break;
1281 +		case '?':
1282 +		default:
1283 +			usage("Bad argument.");
1284 +			break;
1285 +		}
1286 +	}
1287 +
1288 +
1289 +	if (!skip_config)
1290 +		configure_loop();
1291 +
1292 +	if (test_loop) {
1293 +		debug_delay_loop();
1294 +		return 0;
1295 +	}
1296 +
1297 +	if ((argc - (optind + 3)) % 3 != 0)
1298 +		usage("Arguments missing.");
1299 +	wcet_ms   = atof(argv[optind + 0]);
1300 +	period_ms = atof(argv[optind + 1]);
1301 +	duration  = atof(argv[optind + 2]);
1302 +	/* frac num, den = 0 means fixed task */
1303 +	for (i = optind + 3; i < argc; i += 3) {
1304 +		ccpu = atof(argv[i]);
1305 +		fracs[ccpu][0] = argv[i+1];
1306 +		fracs[ccpu][1] = argv[i+2];
1307 +	}
1308 +	if (cpu == -1)
1309 +		cpu = compute_initial_cpu_edfos(fracs);
1310 +	wcet   = wcet_ms * __NS_PER_MS;
1311 +	period = period_ms * __NS_PER_MS;
1312 +	if (wcet <= 0)
1313 +		usage("The worst-case execution time must be a "
1314 +		      "positive number.");
1315 +	if (period <= 0)
1316 +		usage("The period must be a positive number.");
1317 +	if (wcet > period) {
1318 +		usage("The worst-case execution time must not "
1319 +		      "exceed the period.");
1320 +	}
1321 +
1322 +	ret = be_migrate_to(cpu);
1323 +	if (ret < 0)
1324 +		bail_out("could not migrate to target partition");
1325 +
1326 +	ret = sporadic_task_ns_edfos(wcet, period, 0, cpu, fracs, class,
1327 +				NO_ENFORCEMENT);
1328 +
1329 +	if (ret < 0)
1330 +		bail_out("could not setup rt task params");
1331 +
1332 +	if (verbose)
1333 +		show_loop_length();
1334 +
1335 +	init_litmus();
1336 +
1337 +	ret = task_mode(LITMUS_RT_TASK);
1338 +	if (ret != 0)
1339 +		bail_out("could not become RT task");
1340 +
1341 +	if (wait) {
1342 +		ret = wait_for_ts_release();
1343 +		if (ret != 0)
1344 +			bail_out("wait_for_ts_release()");
1345 +	}
1346 +
1347 +	start = wctime();
1348 +
1349 +	while (start + duration > wctime()) {
1350 +		job(wcet_ms * 0.0009); /* 90% wcet, in seconds */
1351 +	}
1352 +
1353 +	return 0;
1354 +}
1355 diff --git a/bin/rtspin_edfwm.c b/bin/rtspin_edfwm.c
1356 new file mode 100644
1357 index 0000000..21a5f3b
1358 --- /dev/null
1359 +++ b/bin/rtspin_edfwm.c
1360 @@ -0,0 +1,233 @@
1361 +#include <sys/time.h>
1362 +
1363 +#include <stdio.h>
1364 +#include <stdlib.h>
1365 +#include <unistd.h>
1366 +#include <time.h>
1367 +#include <string.h>
1368 +
1369 +#include "litmus.h"
1370 +#include "common.h"
1371 +
1372 +
1373 +static double cputime()
1374 +{
1375 +	struct timespec ts;
1376 +	int err;
1377 +	err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
1378 +	if (err != 0)
1379 +		perror("clock_gettime");
1380 +	return (ts.tv_sec + 1E-9 * ts.tv_nsec);
1381 +}
1382 +
1383 +static double wctime()
1384 +{
1385 +	struct timeval tv;
1386 +	gettimeofday(&tv, NULL);
1387 +	return (tv.tv_sec + 1E-6 * tv.tv_usec);
1388 +}
1389 +
1390 +void usage(char *error) {
1391 +	fprintf(stderr, "Error: %s\n", error);
1392 +	fprintf(stderr,
1393 +		"Usage: rt_spin [-w] task_parameters_file duration\n"
1394 +		"       rt_spin -l\n");
1395 +	exit(1);
1396 +}
1397 +
1398 +#define NUMS 4096
1399 +static int num[NUMS];
1400 +static double loop_length = 1.0;
1401 +static char* progname;
1402 +
1403 +static int loop_once(void)
1404 +{
1405 +	int i, j = 0;
1406 +	for (i = 0; i < NUMS; i++)
1407 +		j += num[i]++;
1408 +	return j;
1409 +}
1410 +
1411 +static int loop_for(double exec_time)
1412 +{
1413 +	double t = 0;
1414 +	int tmp = 0;
1415 +/*	while (t + loop_length < exec_time) {
1416 +		tmp += loop_once();
1417 +		t += loop_length;
1418 +	}
1419 +*/
1420 +	double start = cputime();
1421 +	double now = cputime();
1422 +	while (now + loop_length < start + exec_time) {
1423 +		tmp += loop_once();
1424 +		t += loop_length;
1425 +		now = cputime();
1426 +	}
1427 +
1428 +	return tmp;
1429 +}
1430 +
1431 +static void fine_tune(double interval)
1432 +{
1433 +	double start, end, delta;
1434 +
1435 +	start = wctime();
1436 +	loop_for(interval);
1437 +	end = wctime();
1438 +	delta = (end - start - interval) / interval;
1439 +	if (delta != 0)
1440 +		loop_length = loop_length / (1 - delta);
1441 +}
1442 +
1443 +static void configure_loop(void)
1444 +{
1445 +	double start;
1446 +
1447 +	/* prime cache */
1448 +	loop_once();
1449 +	loop_once();
1450 +	loop_once();
1451 +
1452 +	/* measure */
1453 +	start = wctime();
1454 +	loop_once(); /* hope we didn't get preempted  */
1455 +	loop_length = wctime();
1456 +	loop_length -= start;
1457 +
1458 +	/* fine tune */
1459 +	fine_tune(0.1);
1460 +	fine_tune(0.1);
1461 +	fine_tune(0.1);
1462 +}
1463 +
1464 +static void show_loop_length(void)
1465 +{
1466 +	printf("%s/%d: loop_length=%f (%ldus)\n",
1467 +	       progname, getpid(), loop_length,
1468 +	       (long) (loop_length * 1000000));
1469 +}
1470 +
1471 +static void debug_delay_loop(void)
1472 +{
1473 +	double start, end, delay;
1474 +	show_loop_length();
1475 +	while (1) {
1476 +		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
1477 +			start = wctime();
1478 +			loop_for(delay);
1479 +			end = wctime();
1480 +			printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
1481 +			       delay,
1482 +			       end - start,
1483 +			       end - start - delay,
1484 +			       100 * (end - start - delay) / delay);
1485 +		}
1486 +	}
1487 +}
1488 +
1489 +static int job(double exec_time)
1490 +{
1491 +	loop_for(exec_time);
1492 +	sleep_next_period();
1493 +	return 0;
1494 +}
1495 +
1496 +#define OPTSTR "wld:v"
1497 +
1498 +int main(int argc, char** argv)
1499 +{
1500 +	int ret;
1501 +
1502 +	int opt;
1503 +	int wait = 0;
1504 +	int test_loop = 0;
1505 +	int skip_config = 0;
1506 +	int verbose = 0;
1507 +	double wcet_ms;
1508 +	double duration, start;
1509 +
1510 +	struct rt_task rt;
1511 +	FILE *file;
1512 +
1513 +	progname = argv[0];
1514 +
1515 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1516 +		switch (opt) {
1517 +		case 'w':
1518 +			wait = 1;
1519 +			break;
1520 +		case 'l':
1521 +			test_loop = 1;
1522 +			break;
1523 +		case 'd':
1524 +			/* manually configure delay per loop iteration
1525 +			 * unit: microseconds */
1526 +			loop_length = atof(optarg) / 1000000;
1527 +			skip_config = 1;
1528 +			break;
1529 +		case 'v':
1530 +			verbose = 1;
1531 +			break;
1532 +		case ':':
1533 +			usage("Argument missing.");
1534 +			break;
1535 +		case '?':
1536 +		default:
1537 +			usage("Bad argument.");
1538 +			break;
1539 +		}
1540 +	}
1541 +
1542 +
1543 +	if (!skip_config)
1544 +		configure_loop();
1545 +
1546 +	if (test_loop) {
1547 +		debug_delay_loop();
1548 +		return 0;
1549 +	}
1550 +
1551 +	if (argc - optind < 2)
1552 +		usage("Arguments missing.");
1553 +
1554 +	if ((file = fopen(argv[optind + 0], "r")) == NULL) {
1555 +		fprintf(stderr, "Cannot open %s\n", argv[1]);
1556 +		return -1;
1557 +	}
1558 +	duration = atof(argv[optind + 1]);
1559 +
1560 +	memset(&rt, 0, sizeof(struct rt_task));
1561 +
1562 +	if (parse_edfwm_ts_file(file, &rt) < 0)
1563 +		bail_out("Could not parse file\n");
1564 +
1565 +	if (sporadic_task_ns_semi(&rt) < 0)
1566 +		bail_out("could not setup rt task params");
1567 +
1568 +	fclose(file);
1569 +
1570 +	if (verbose)
1571 +		show_loop_length();
1572 +
1573 +	init_litmus();
1574 +
1575 +	ret = task_mode(LITMUS_RT_TASK);
1576 +	if (ret != 0)
1577 +		bail_out("could not become RT task");
1578 +
1579 +	if (wait) {
1580 +		ret = wait_for_ts_release();
1581 +		if (ret != 0)
1582 +			bail_out("wait_for_ts_release()");
1583 +	}
1584 +
1585 +	wcet_ms = ((double) rt.exec_cost ) / __NS_PER_MS;
1586 +	start = wctime();
1587 +
1588 +	while (start + duration > wctime()) {
1589 +		job(wcet_ms * 0.0009); /* 90% wcet, in seconds */
1590 +	}
1591 +
1592 +	return 0;
1593 +}
1594 diff --git a/bin/rtspin_npsf.c b/bin/rtspin_npsf.c
1595 new file mode 100644
1596 index 0000000..d5dff3d
1597 --- /dev/null
1598 +++ b/bin/rtspin_npsf.c
1599 @@ -0,0 +1,252 @@
1600 +#include <sys/time.h>
1601 +
1602 +#include <stdio.h>
1603 +#include <stdlib.h>
1604 +#include <unistd.h>
1605 +#include <time.h>
1606 +
1607 +
1608 +#include "litmus.h"
1609 +#include "common.h"
1610 +
1611 +
1612 +static double cputime()
1613 +{
1614 +	struct timespec ts;
1615 +	int err;
1616 +	err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
1617 +	if (err != 0)
1618 +		perror("clock_gettime");
1619 +	return (ts.tv_sec + 1E-9 * ts.tv_nsec);
1620 +}
1621 +
1622 +static double wctime()
1623 +{
1624 +	struct timeval tv;
1625 +	gettimeofday(&tv, NULL);
1626 +	return (tv.tv_sec + 1E-6 * tv.tv_usec);
1627 +}
1628 +
1629 +void usage(char *error) {
1630 +	fprintf(stderr, "Error: %s\n", error);
1631 +	fprintf(stderr,
1632 +		"Usage: rt_spin [-w] WCET PERIOD DURATION CPU NPSF-ID\n"
1633 +		"       rt_spin -l\n");
1634 +	exit(1);
1635 +}
1636 +
1637 +#define NUMS 4096
1638 +static int num[NUMS];
1639 +static double loop_length = 1.0;
1640 +static char* progname;
1641 +
1642 +static int loop_once(void)
1643 +{
1644 +	int i, j = 0;
1645 +	for (i = 0; i < NUMS; i++)
1646 +		j += num[i]++;
1647 +	return j;
1648 +}
1649 +
1650 +static int loop_for(double exec_time)
1651 +{
1652 +	double t = 0;
1653 +	int tmp = 0;
1654 +/*	while (t + loop_length < exec_time) {
1655 +		tmp += loop_once();
1656 +		t += loop_length;
1657 +	}
1658 +*/
1659 +	double start = cputime();
1660 +	double now = cputime();
1661 +	while (now + loop_length < start + exec_time) {
1662 +		tmp += loop_once();
1663 +		t += loop_length;
1664 +		now = cputime();
1665 +	}
1666 +
1667 +	return tmp;
1668 +}
1669 +
1670 +static void fine_tune(double interval)
1671 +{
1672 +	double start, end, delta;
1673 +
1674 +	start = wctime();
1675 +	loop_for(interval);
1676 +	end = wctime();
1677 +	delta = (end - start - interval) / interval;
1678 +	if (delta != 0)
1679 +		loop_length = loop_length / (1 - delta);
1680 +}
1681 +
1682 +static void configure_loop(void)
1683 +{
1684 +	double start;
1685 +
1686 +	/* prime cache */
1687 +	loop_once();
1688 +	loop_once();
1689 +	loop_once();
1690 +
1691 +	/* measure */
1692 +	start = wctime();
1693 +	loop_once(); /* hope we didn't get preempted  */
1694 +	loop_length = wctime();
1695 +	loop_length -= start;
1696 +
1697 +	/* fine tune */
1698 +	fine_tune(0.1);
1699 +	fine_tune(0.1);
1700 +	fine_tune(0.1);
1701 +}
1702 +
1703 +static void show_loop_length(void)
1704 +{
1705 +	printf("%s/%d: loop_length=%f (%ldus)\n",
1706 +	       progname, getpid(), loop_length,
1707 +	       (long) (loop_length * 1000000));
1708 +}
1709 +
1710 +static void debug_delay_loop(void)
1711 +{
1712 +	double start, end, delay;
1713 +	show_loop_length();
1714 +	while (1) {
1715 +		for (delay = 0.5; delay > 0.01; delay -= 0.01) {
1716 +			start = wctime();
1717 +			loop_for(delay);
1718 +			end = wctime();
1719 +			printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n",
1720 +			       delay,
1721 +			       end - start,
1722 +			       end - start - delay,
1723 +			       100 * (end - start - delay) / delay);
1724 +		}
1725 +	}
1726 +}
1727 +
1728 +static int job(double exec_time)
1729 +{
1730 +	loop_for(exec_time);
1731 +	sleep_next_period();
1732 +	return 0;
1733 +}
1734 +
1735 +#define OPTSTR "c:wld:v"
1736 +
1737 +int main(int argc, char** argv)
1738 +{
1739 +	int ret;
1740 +	lt_t wcet;
1741 +	lt_t period;
1742 +	double wcet_ms, period_ms;
1743 +	int migrate = 0;
1744 +	int cpu = 0;
1745 +	int npsf_id = 0;
1746 +	int opt;
1747 +	int wait = 0;
1748 +	int test_loop = 0;
1749 +	int skip_config = 0;
1750 +	int verbose = 0;
1751 +	double duration, start;
1752 +	task_class_t class = RT_CLASS_HARD;
1753 +
1754 +	progname = argv[0];
1755 +
1756 +	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
1757 +		switch (opt) {
1758 +		case 'w':
1759 +			wait = 1;
1760 +			break;
1761 +		case 'c':
1762 +			class = str2class(optarg);
1763 +			if (class == -1)
1764 +				usage("Unknown task class.");
1765 +			break;
1766 +		case 'l':
1767 +			test_loop = 1;
1768 +			break;
1769 +		case 'd':
1770 +			/* manually configure delay per loop iteration
1771 +			 * unit: microseconds */
1772 +			loop_length = atof(optarg) / 1000000;
1773 +			skip_config = 1;
1774 +			break;
1775 +		case 'v':
1776 +			verbose = 1;
1777 +			break;
1778 +		case ':':
1779 +			usage("Argument missing.");
1780 +			break;
1781 +		case '?':
1782 +		default:
1783 +			usage("Bad argument.");
1784 +			break;
1785 +		}
1786 +	}
1787 +
1788 +
1789 +	if (!skip_config)
1790 +		configure_loop();
1791 +
1792 +	if (test_loop) {
1793 +		debug_delay_loop();
1794 +		return 0;
1795 +	}
1796 +
1797 +	if (argc - optind < 5)
1798 +		usage("Arguments missing.");
1799 +	wcet_ms   = atof(argv[optind + 0]);
1800 +	period_ms = atof(argv[optind + 1]);
1801 +	duration  = atof(argv[optind + 2]);
1802 +	cpu = atoi(argv[optind + 3]);
1803 +	migrate = 1;
1804 +	npsf_id = atoi(argv[optind + 4]);
1805 +	wcet   = wcet_ms * __NS_PER_MS;
1806 +	period = period_ms * __NS_PER_MS;
1807 +	if (wcet <= 0)
1808 +		usage("The worst-case execution time must be a "
1809 +		      "positive number.");
1810 +	if (period <= 0)
1811 +		usage("The period must be a positive number.");
1812 +	if (wcet > period) {
1813 +		usage("The worst-case execution time must not "
1814 +		      "exceed the period.");
1815 +	}
1816 +
1817 +	if (migrate) {
1818 +		ret = be_migrate_to(cpu);
1819 +		if (ret < 0)
1820 +			bail_out("could not migrate to target partition");
1821 +	}
1822 +
1823 +	ret = sporadic_task_ns_npsf(wcet, period, 0, cpu, class, npsf_id,
1824 +			NO_ENFORCEMENT, migrate);
1825 +
1826 +	if (ret < 0)
1827 +		bail_out("could not setup rt task params");
1828 +
1829 +	if (verbose)
1830 +		show_loop_length();
1831 +
1832 +	init_litmus();
1833 +
1834 +	ret = task_mode(LITMUS_RT_TASK);
1835 +	if (ret != 0)
1836 +		bail_out("could not become RT task");
1837 +
1838 +	if (wait) {
1839 +		ret = wait_for_ts_release();
1840 +		if (ret != 0)
1841 +			bail_out("wait_for_ts_release()");
1842 +	}
1843 +
1844 +	start = wctime();
1845 +
1846 +	while (start + duration > wctime()) {
1847 +		job(wcet_ms * 0.0009); /* 90% wcet, in seconds */
1848 +	}
1849 +
1850 +	return 0;
1851 +}
1852 diff --git a/include/common.h b/include/common.h
1853 index d1234ba..dbcfd34 100644
1854 --- a/include/common.h
1855 +++ b/include/common.h
1856 @@ -1,7 +1,11 @@
1857  #ifndef COMMON_H
1858  #define COMMON_H
1859  
1860 +#include "litmus.h"
1861  
1862  void bail_out(const char* msg);
1863  
1864 +/* EDF-WM helper functions to parse task parameters from file */
1865 +int parse_edfwm_ts_file(FILE *ts, struct rt_task *rt);
1866 +
1867  #endif
1868 diff --git a/include/litmus.h b/include/litmus.h
1869 index b798c92..0139d25 100644
1870 --- a/include/litmus.h
1871 +++ b/include/litmus.h
1872 @@ -5,10 +5,12 @@
1873  extern "C" {
1874  #endif
1875  
1876 +#include <limits.h>
1877  /* Include kernel header.
1878   * This is required for the rt_param
1879   * and control_page structures.
1880   */
1881 +#include <linux/threads.h>
1882  #include <litmus/rt_param.h>
1883  
1884  #include <sys/types.h>
1885 @@ -28,6 +30,8 @@ int get_rt_task_param(pid_t pid, struct rt_task* param);
1886  
1887  /* setup helper */
1888  
1889 +unsigned int compute_initial_cpu_edfos(lt_t fracs[][2]);
1890 +
1891  /* times are given in ms */
1892  int sporadic_task(
1893  		lt_t e, lt_t p, lt_t phase,
1894 @@ -40,6 +44,23 @@ int sporadic_task_ns(
1895  		int cpu, task_class_t cls,
1896  		budget_policy_t budget_policy, int set_cpu_set);
1897  
1898 +int sporadic_task_ns_edffm(lt_t e, lt_t p, lt_t phase, int cpu,
1899 +		lt_t *frac1, lt_t *frac2, int cpu1, int cpu2,
1900 +		task_class_t cls, budget_policy_t budget_policy,
1901 +		int set_cpu_set);
1902 +
1903 +int sporadic_task_ns_edfos(lt_t e, lt_t p, lt_t phase, int cpu,
1904 +		lt_t fracs[][2], task_class_t cls,
1905 +		budget_policy_t budget_policy);
1906 +
1907 +int sporadic_task_ns_npsf(
1908 +		lt_t e, lt_t p, lt_t phase,
1909 +		int cpu, task_class_t cls, int npsf_id,
1910 +		budget_policy_t budget_policy, int set_cpu_set);
1911 +
1912 +/* times are in ns, specific helper for semi-partitioned algos */
1913 +int sporadic_task_ns_semi(struct rt_task *rt);
1914 +
1915  /* budget enforcement off by default in these macros */
1916  #define sporadic_global(e, p) \
1917  	sporadic_task(e, p, 0, 0, RT_CLASS_SOFT, NO_ENFORCEMENT, 0)
1918 @@ -85,6 +106,19 @@ typedef int (*rt_fn_t)(void*);
1919  int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period);
1920  int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
1921  		     int period, task_class_t cls);
1922 +int __create_rt_task_edffm(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
1923 +		int period, lt_t *frac1, lt_t *frac2,
1924 +		int cpu1, int cpu2, task_class_t class);
1925 +int __create_rt_task_edfos(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
1926 +		int period, lt_t fracs[][2], task_class_t class);
1927 +int __create_rt_task_npsf(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
1928 +		int period, int npsf_id, task_class_t class);
1929 +
1930 +/* wrapper to mask __launch_rt_task() for semi-partitioned algorithms
1931 + * (it can be extended to cover all algorithms that directly submit
1932 + * an rt_task structure instead of a set of values).
1933 + */
1934 +int create_rt_task_semi(rt_fn_t rt_prog, void *arg, struct rt_task *params);
1935  
1936  /*	per-task modes */
1937  enum rt_task_mode_t {
1938 @@ -134,6 +168,21 @@ int null_call(cycles_t *timestamp);
1939   */
1940  struct control_page* get_ctrl_page(void);
1941  
1942 +/* NPS-F syscall to add a notional processor (a server) to a cpu.
1943 + * A notional processor may span across multiple cpu.
1944 + *
1945 + * @npsf_id:	a "unique" identifier for the notional processor.
1946 + * @budgets:	array of (cpu, budget-ns) that describes this np.
1947 + * 		on possibly more than one cpu.
1948 + * @last:	marks the end of servers initialization and trigger
1949 + * 		the switching of servers in the plugin.
1950 + * 		Should be set to 1 only once at the end of the sequence
1951 + * 		of add_server() calls
1952 + *
1953 + * Currently implemented on x86_64 only.
1954 + */
1955 +int add_server(int *npsf_id, struct npsf_budgets *budgets, int last);
1956 +
1957  #ifdef __cplusplus
1958  }
1959  #endif
1960 diff --git a/src/litmus.c b/src/litmus.c
1961 index d3cc6bb..f7c91de 100644
1962 --- a/src/litmus.c
1963 +++ b/src/litmus.c
1964 @@ -29,8 +29,6 @@ task_class_t str2class(const char* str)
1965  		return -1;
1966  }
1967  
1968 -#define NS_PER_MS 1000000
1969 -
1970  /* only for best-effort execution: migrate to target_cpu */
1971  int be_migrate_to(int target_cpu)
1972  {
1973 @@ -41,11 +39,38 @@ int be_migrate_to(int target_cpu)
1974  	return sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set);
1975  }
1976  
1977 +static unsigned int compute_pfair_deadline(lt_t wt_num, lt_t wt_den)
1978 +{
1979 +	int dead;
1980 +	dead = wt_den / wt_num;
1981 +	if (wt_den % wt_num > 0)
1982 +		dead++;
1983 +	return dead;
1984 +}
1985 +
1986 +unsigned int compute_initial_cpu_edfos(lt_t fracs[][2])
1987 +{
1988 +	int initial_cpu = -1;
1989 +	int lowest_deadline = UINT_MAX;
1990 +	int current_deadline, i;
1991 +	for (i = 0; i < NR_CPUS_EDF_OS; i++) {
1992 +		if (fracs[i][0] > 0) {
1993 +			current_deadline = compute_pfair_deadline(fracs[i][0],
1994 +								  fracs[i][1]);
1995 +			if (current_deadline < lowest_deadline) {
1996 +				lowest_deadline = current_deadline;
1997 +				initial_cpu = i;
1998 +			}
1999 +		}
2000 +	}
2001 +	return initial_cpu;
2002 +}
2003 +
2004  int sporadic_task(lt_t e, lt_t p, lt_t phase,
2005  		  int cpu, task_class_t cls,
2006  		  budget_policy_t budget_policy, int set_cpu_set)
2007  {
2008 -	return sporadic_task_ns(e * NS_PER_MS, p * NS_PER_MS, phase * NS_PER_MS,
2009 +	return sporadic_task_ns(e * __NS_PER_MS, p * __NS_PER_MS, phase * __NS_PER_MS,
2010  				cpu, cls, budget_policy, set_cpu_set);
2011  }
2012  
2013 @@ -75,6 +100,101 @@ int sporadic_task_ns(lt_t e, lt_t p, lt_t phase,
2014  	return set_rt_task_param(gettid(), &param);
2015  }
2016  
2017 +int sporadic_task_ns_edffm(lt_t e, lt_t p, lt_t phase, int cpu,
2018 +		lt_t *frac1, lt_t *frac2, int cpu1, int cpu2,
2019 +		task_class_t cls, budget_policy_t budget_policy,
2020 +		int set_cpu_set)
2021 +{
2022 +	struct rt_task param;
2023 +	struct edffm_params fm;
2024 +	int ret;
2025 +	param.exec_cost = e;
2026 +	param.period    = p;
2027 +	param.cpu       = cpu;
2028 +	/* check on denominators */
2029 +	if (frac1[1] != 0 && frac2[1] != 0) {
2030 +		/* edf-fm migrat task */
2031 +		fm.nr_cpus = 1;
2032 +		fm.cpus[0] = cpu1;
2033 +		fm.cpus[1] = cpu2;
2034 +		fm.fraction[0][0] = frac1[0];
2035 +		fm.fraction[1][0] = frac1[1];
2036 +		fm.fraction[0][1] = frac2[0];
2037 +		fm.fraction[1][1] = frac2[1];
2038 +	}
2039 +	param.semi_part.fm = fm;
2040 +	param.cls       = cls;
2041 +	param.phase	= phase;
2042 +	param.budget_policy = budget_policy;
2043 +
2044 +	if (set_cpu_set) {
2045 +		ret = be_migrate_to(cpu);
2046 +		check("migrate to cpu");
2047 +	}
2048 +	return set_rt_task_param(gettid(), &param);
2049 +}
2050 +
2051 +int sporadic_task_ns_edfos(lt_t e, lt_t p, lt_t phase, int cpu,
2052 +		lt_t fracs[][2], task_class_t cls,
2053 +		budget_policy_t budget_policy)
2054 +{
2055 +	struct rt_task param;
2056 +	struct edfos_params os;
2057 +	int ret, i;
2058 +	os.migrat = 0;
2059 +	os.first_cpu = UINT_MAX;
2060 +	param.exec_cost = e;
2061 +	param.period    = p;
2062 +	param.cpu = cpu;
2063 +	for (i = 0; i < NR_CPUS_EDF_OS; i++) {
2064 +		if (fracs[i][0] > 0) {
2065 +			os.migrat++;
2066 +			if (os.first_cpu == UINT_MAX)
2067 +				os.first_cpu = i;
2068 +		}
2069 +		os.fraction[i][0] = fracs[i][0];
2070 +		os.fraction[i][1] = fracs[i][1];
2071 +	}
2072 +	param.semi_part.os = os;
2073 +	param.cls       = cls;
2074 +	param.phase	= phase;
2075 +	param.budget_policy = budget_policy;
2076 +
2077 +	return set_rt_task_param(gettid(), &param);
2078 +}
2079 +
2080 +int sporadic_task_ns_npsf(lt_t e, lt_t p, lt_t phase,
2081 +		int cpu, task_class_t cls, int npsf_id,
2082 +		budget_policy_t budget_policy, int set_cpu_set)
2083 +{
2084 +	struct rt_task param;
2085 +	int ret;
2086 +	param.exec_cost = e;
2087 +	param.period    = p;
2088 +	param.cpu       = cpu;
2089 +	param.cls       = cls;
2090 +	param.phase	= phase;
2091 +	param.budget_policy = budget_policy;
2092 +	param.semi_part.npsf_id = (int) npsf_id;
2093 +
2094 +	if (set_cpu_set) {
2095 +		ret = be_migrate_to(cpu);
2096 +		check("migrate to cpu");
2097 +	}
2098 +	return set_rt_task_param(gettid(), &param);
2099 +}
2100 +
2101 +/* Sporadic task helper function for Semi-Partitioned algorithms. */
2102 +int sporadic_task_ns_semi(struct rt_task *param)
2103 +{
2104 +	int ret;
2105 +
2106 +	ret = be_migrate_to(param->cpu);
2107 +	check("migrate to cpu");
2108 +
2109 +	return set_rt_task_param(gettid(), param);
2110 +}
2111 +
2112  int init_kernel_iface(void);
2113  
2114  int init_litmus(void)
2115 diff --git a/src/syscalls.c b/src/syscalls.c
2116 index 77a6277..7ac488a 100644
2117 --- a/src/syscalls.c
2118 +++ b/src/syscalls.c
2119 @@ -95,3 +95,8 @@ int null_call(cycles_t *timestamp)
2120  {
2121  	return syscall(__NR_null_call, timestamp);
2122  }
2123 +
2124 +int add_server(int *npsf_id, struct npsf_budgets *budgets, int last)
2125 +{
2126 +	return syscall(__NR_add_server, npsf_id, budgets, last);
2127 +}
2128 diff --git a/src/task.c b/src/task.c
2129 index 4d237bd..8b4287c 100644
2130 --- a/src/task.c
2131 +++ b/src/task.c
2132 @@ -40,6 +40,85 @@ int __launch_rt_task(rt_fn_t rt_prog, void *rt_arg, rt_setup_fn_t setup,
2133  	return rt_task;
2134  }
2135  
2136 +int __create_rt_task_edffm(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
2137 +			int period, lt_t *frac1, lt_t *frac2,
2138 +			int cpu1, int cpu2, task_class_t class)
2139 +{
2140 +	struct rt_task params;
2141 +	struct edffm_params fm;
2142 +	params.cpu       = cpu;
2143 +	params.period    = period;
2144 +	params.exec_cost = wcet;
2145 +	params.cls       = class;
2146 +	params.phase     = 0;
2147 +	/* enforce budget for tasks that might not use sleep_next_period() */
2148 +	params.budget_policy = QUANTUM_ENFORCEMENT;
2149 +
2150 +	/* edf-fm check on denominators for migratory tasks */
2151 +	if (frac1[1] != 0 && frac2[1] != 0) {
2152 +		/* edf-fm migrat task */
2153 +		fm.nr_cpus = 1;
2154 +		fm.cpus[0] = cpu1;
2155 +		fm.cpus[1] = cpu2;
2156 +		fm.fraction[0][0] = frac1[0];
2157 +		fm.fraction[1][0] = frac1[1];
2158 +		fm.fraction[0][1] = frac2[0];
2159 +		fm.fraction[1][1] = frac2[1];
2160 +	}
2161 +	params.semi_part.fm = fm;
2162 +
2163 +	return __launch_rt_task(rt_prog, arg,
2164 +				(rt_setup_fn_t) set_rt_task_param, &params);
2165 +}
2166 +
2167 +int __create_rt_task_edfos(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
2168 +			int period, lt_t fracs[][2], task_class_t class)
2169 +{
2170 +	struct rt_task params;
2171 +	struct edfos_params os;
2172 +	int i;
2173 +	params.cpu 	 = cpu;
2174 +	params.period    = period;
2175 +	params.exec_cost = wcet;
2176 +	params.cls       = class;
2177 +	params.phase     = 0;
2178 +	/* enforce budget for tasks that might not use sleep_next_period() */
2179 +	params.budget_policy = QUANTUM_ENFORCEMENT;
2180 +
2181 +	os.migrat = 0;
2182 +	os.first_cpu = UINT_MAX;
2183 +	for (i = 0; i < NR_CPUS_EDF_OS; i++) {
2184 +		if (fracs[i][0] > 0) {
2185 +			os.migrat++;
2186 +			if (os.first_cpu == UINT_MAX)
2187 +				os.first_cpu = i;
2188 +		}
2189 +		os.fraction[i][0] = fracs[i][0];
2190 +		os.fraction[i][1] = fracs[i][1];
2191 +	}
2192 +	params.semi_part.os = os;
2193 +
2194 +	return __launch_rt_task(rt_prog, arg,
2195 +				(rt_setup_fn_t) set_rt_task_param, &params);
2196 +}
2197 +
2198 +int __create_rt_task_npsf(rt_fn_t rt_prog, void *arg, int cpu, int wcet,
2199 +		int period, int npsf_id, task_class_t class)
2200 +{
2201 +	struct rt_task params;
2202 +	params.cpu       = cpu;
2203 +	params.period    = period;
2204 +	params.exec_cost = wcet;
2205 +	params.cls       = class;
2206 +	params.phase     = 0;
2207 +	/* enforce budget for tasks that might not use sleep_next_period() */
2208 +	params.budget_policy = QUANTUM_ENFORCEMENT;
2209 +	params.semi_part.npsf_id = (int) npsf_id;
2210 +
2211 +	return __launch_rt_task(rt_prog, arg,
2212 +				(rt_setup_fn_t) set_rt_task_param, &params);
2213 +}
2214 +
2215  int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period,
2216  		     task_class_t class)
2217  {
2218 @@ -60,6 +139,11 @@ int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period) {
2219  	return __create_rt_task(rt_prog, arg, cpu, wcet, period, RT_CLASS_HARD);
2220  }
2221  
2222 +int create_rt_task_semi(rt_fn_t rt_prog, void *arg, struct rt_task *params)
2223 +{
2224 +	return __launch_rt_task(rt_prog, arg,
2225 +			(rt_setup_fn_t) set_rt_task_param, params);
2226 +}
2227  
2228  #define SCHED_NORMAL 0
2229  #define SCHED_LITMUS 6

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.