diff options
| author | Joshua Bakita <jbakita@cs.unc.edu> | 2020-10-16 16:55:14 -0400 |
|---|---|---|
| committer | Joshua Bakita <jbakita@cs.unc.edu> | 2020-10-16 16:55:14 -0400 |
| commit | 6ea9939e0610a809f6f47d13ec68df00d1ca0afc (patch) | |
| tree | fe4a2eee3ddcf77e2367309dcd75a232b76dcd62 /dis/random_walk.c | |
| parent | e9285d0cdea756a2830f0ace378e4197b36869aa (diff) | |
Move the DIS benchmarks up a directory and update hardcoded paths
Note that this repo does not attempt to keep a copy of the original
DIS benchmark distributions. UNC real-time has another repo for that.
Diffstat (limited to 'dis/random_walk.c')
| -rw-r--r-- | dis/random_walk.c | 550 |
1 files changed, 550 insertions, 0 deletions
diff --git a/dis/random_walk.c b/dis/random_walk.c new file mode 100644 index 0000000..9f907bb --- /dev/null +++ b/dis/random_walk.c | |||
| @@ -0,0 +1,550 @@ | |||
| 1 | #include <sys/time.h> | ||
| 2 | #include <sys/mman.h> | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdlib.h> | ||
| 6 | #include <unistd.h> | ||
| 7 | #include <time.h> | ||
| 8 | #include <string.h> | ||
| 9 | #include <inttypes.h> | ||
| 10 | #include <assert.h> | ||
| 11 | #include <limits.h> | ||
| 12 | #include <fcntl.h> | ||
| 13 | #include <errno.h> | ||
| 14 | /* | ||
| 15 | #include "litmus.h" | ||
| 16 | #include "common.h" | ||
| 17 | */ | ||
| 18 | /* CPU time consumed so far in seconds */ | ||
| 19 | double cputime(void) | ||
| 20 | { | ||
| 21 | struct timespec ts; | ||
| 22 | int err; | ||
| 23 | err = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts); | ||
| 24 | if (err != 0) | ||
| 25 | perror("clock_gettime"); | ||
| 26 | return (ts.tv_sec + 1E-9 * ts.tv_nsec); | ||
| 27 | } | ||
| 28 | |||
| 29 | /* wall-clock time in seconds */ | ||
| 30 | double wctime(void) | ||
| 31 | { | ||
| 32 | struct timeval tv; | ||
| 33 | gettimeofday(&tv, NULL); | ||
| 34 | return (tv.tv_sec + 1E-6 * tv.tv_usec); | ||
| 35 | } | ||
| 36 | |||
| 37 | void bail_out(const char* msg) | ||
| 38 | { | ||
| 39 | perror(msg); | ||
| 40 | exit(-1 * errno); | ||
| 41 | } | ||
| 42 | |||
| 43 | #include "extra.h" | ||
| 44 | |||
| 45 | #define PAGE_SIZE (4096) | ||
| 46 | #define CACHELINE_SIZE 64 | ||
| 47 | #define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int)) | ||
| 48 | #define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t)) | ||
| 49 | #define INTS_IN_1KB (1024 / sizeof(int)) | ||
| 50 | |||
| 51 | typedef struct cacheline | ||
| 52 | { | ||
| 53 | int line[INTS_IN_CACHELINE]; | ||
| 54 | } __attribute__((aligned(CACHELINE_SIZE))) cacheline_t; | ||
| 55 | |||
| 56 | static volatile cacheline_t* arena = NULL; | ||
| 57 | |||
| 58 | #define UNCACHE_DEV "/dev/litmus/uncache" | ||
| 59 | #define FAKE_DEV "/dev/litmus/fakedev0" | ||
| 60 | |||
| 61 | static cacheline_t* alloc_arena(size_t size, int use_huge_pages, int use_uncache_pages) | ||
| 62 | { | ||
| 63 | int flags = MAP_PRIVATE | MAP_POPULATE; | ||
| 64 | cacheline_t* arena = NULL; | ||
| 65 | int fd; | ||
| 66 | |||
| 67 | if(use_huge_pages) | ||
| 68 | flags |= MAP_HUGETLB; | ||
| 69 | |||
| 70 | if(use_uncache_pages == 1) { | ||
| 71 | fd = open(UNCACHE_DEV, O_RDWR|O_SYNC); | ||
| 72 | if (fd == -1) | ||
| 73 | bail_out("Failed to open uncache device. Are you running the LITMUS^RT kernel?"); | ||
| 74 | } else if (use_uncache_pages == 2) { | ||
| 75 | fd = open(FAKE_DEV, O_RDWR|O_SYNC); | ||
| 76 | if (fd == -1) | ||
| 77 | bail_out("Failed to open fake device. Are you running the LITMUS^RT kernel?"); | ||
| 78 | } else { | ||
| 79 | fd = -1; | ||
| 80 | flags |= MAP_ANONYMOUS; | ||
| 81 | } | ||
| 82 | |||
| 83 | arena = (cacheline_t*)mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0); | ||
| 84 | |||
| 85 | if(use_uncache_pages) | ||
| 86 | close(fd); | ||
| 87 | |||
| 88 | assert(arena); | ||
| 89 | |||
| 90 | return arena; | ||
| 91 | } | ||
| 92 | |||
| 93 | static void dealloc_arena(cacheline_t* arena, size_t size) | ||
| 94 | { | ||
| 95 | int ret = munmap((void*)arena, size); | ||
| 96 | if(ret != 0) | ||
| 97 | bail_out("munmap() error"); | ||
| 98 | } | ||
| 99 | |||
| 100 | static int randrange(int min, int max) | ||
| 101 | { | ||
| 102 | // Range is [min, max) | ||
| 103 | assert(max - min - 1 <= RAND_MAX); | ||
| 104 | return rand() % (max - min) + min; | ||
| 105 | //return (rand() % (max - min + 1)) + min; | ||
| 106 | /* generate a random number on the range [min, max) w/o skew */ | ||
| 107 | /*int limit = max - min; | ||
| 108 | int devisor = RAND_MAX/limit; | ||
| 109 | int retval; | ||
| 110 | |||
| 111 | do { | ||
| 112 | retval = rand() / devisor; | ||
| 113 | } while(retval == limit); | ||
| 114 | retval += min; | ||
| 115 | |||
| 116 | return retval;*/ | ||
| 117 | } | ||
| 118 | |||
| 119 | static void init_arena(volatile cacheline_t* arena, size_t size) | ||
| 120 | { | ||
| 121 | int i; | ||
| 122 | size_t num_arena_elem = size / sizeof(cacheline_t); | ||
| 123 | |||
| 124 | /* Generate a cycle among the cache lines using Sattolo's algorithm. | ||
| 125 | Every int in the cache line points to the same cache line. | ||
| 126 | Note: Sequential walk doesn't care about these values. */ | ||
| 127 | for (i = 0; i < num_arena_elem; i++) { | ||
| 128 | int j; | ||
| 129 | for(j = 0; j < INTS_IN_CACHELINE; j++) | ||
| 130 | arena[i].line[j] = i; | ||
| 131 | arena[i].line[1] = 0; | ||
| 132 | } | ||
| 133 | /*while(1 < i--) { | ||
| 134 | int j = randrange(0, i); | ||
| 135 | cacheline_t temp = arena[j]; | ||
| 136 | arena[j] = arena[i]; | ||
| 137 | arena[i] = temp; | ||
| 138 | }*/ | ||
| 139 | for (int j = 0; j < num_arena_elem-1; j++) { | ||
| 140 | int k = randrange(j+1, num_arena_elem); | ||
| 141 | cacheline_t temp = arena[j]; | ||
| 142 | arena[j] = arena[k]; | ||
| 143 | arena[k] = temp; | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | /* Random walk around the arena in cacheline-sized chunks. | ||
| 148 | Cacheline-sized chucks ensures the same utilization of each | ||
| 149 | hit line as sequential read. (Otherwise, our utilization | ||
| 150 | would only be 1/INTS_IN_CACHELINE.) */ | ||
| 151 | static int random_walk(volatile cacheline_t *mem, int wss, int write_cycle) | ||
| 152 | { | ||
| 153 | /* a random cycle among the cache lines was set up by init_arena(). */ | ||
| 154 | int sum, i, next; | ||
| 155 | |||
| 156 | // Always do the same number of hops | ||
| 157 | int numlines = 33554432 / CACHELINE_SIZE;//wss * CACHELINES_IN_1KB; | ||
| 158 | |||
| 159 | sum = 0; | ||
| 160 | |||
| 161 | /* contents of arena is structured s.t. offsets are all | ||
| 162 | w.r.t. to start of arena, so compute the initial offset */ | ||
| 163 | next = mem - arena; | ||
| 164 | |||
| 165 | if (write_cycle == 0) { | ||
| 166 | for (i = 0; i < numlines; i++) { | ||
| 167 | next = arena[next].line[0]; | ||
| 168 | arena[next].line[1] = 1; // Record that we touched this line | ||
| 169 | sum += next; | ||
| 170 | for (int j = 2; j < INTS_IN_CACHELINE; j++) | ||
| 171 | arena[next].line[j]++; | ||
| 172 | } | ||
| 173 | } else { | ||
| 174 | int w, which_line; | ||
| 175 | for (i = 0, w = 0; i < numlines; i++) { | ||
| 176 | which_line = next; | ||
| 177 | next = arena[next].line[0]; | ||
| 178 | if((w % write_cycle) != (write_cycle - 1)) { // This is equivalent to 1 % 1 != 1 - 1 which is always false | ||
| 179 | sum += next; | ||
| 180 | } | ||
| 181 | else { | ||
| 182 | // I /think/ that this just writes back to the address it read from | ||
| 183 | arena[which_line].line[0] = next; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | } | ||
| 187 | return sum; | ||
| 188 | } | ||
| 189 | |||
| 190 | volatile static cacheline_t* random_start(int wss) | ||
| 191 | { | ||
| 192 | return arena + randrange(0, ((wss * 1024)/sizeof(cacheline_t))); | ||
| 193 | } | ||
| 194 | /* | ||
| 195 | static int sequential_walk(cacheline_t *_mem, int wss, int write_cycle) | ||
| 196 | { | ||
| 197 | int sum = 0, i; | ||
| 198 | int* mem = (int*)_mem; // treat as raw buffer of ints | ||
| 199 | int num_ints = wss * INTS_IN_1KB; | ||
| 200 | |||
| 201 | if (write_cycle > 0) { | ||
| 202 | for (i = 0; i < num_ints; i++) { | ||
| 203 | if (i % write_cycle == (write_cycle - 1)) | ||
| 204 | mem[i]++; | ||
| 205 | else | ||
| 206 | sum += mem[i]; | ||
| 207 | } | ||
| 208 | } else { | ||
| 209 | // sequential access, pure read | ||
| 210 | for (i = 0; i < num_ints; i++) | ||
| 211 | sum += mem[i]; | ||
| 212 | } | ||
| 213 | return sum; | ||
| 214 | } | ||
| 215 | |||
| 216 | static cacheline_t* sequential_start(int wss) | ||
| 217 | { | ||
| 218 | static int pos = 0; | ||
| 219 | |||
| 220 | int num_cachelines = wss * CACHELINES_IN_1KB; | ||
| 221 | |||
| 222 | cacheline_t *mem; | ||
| 223 | |||
| 224 | * Don't allow re-use between allocations. | ||
| 225 | * At most half of the arena may be used | ||
| 226 | * at any one time. | ||
| 227 | * | ||
| 228 | if (num_cachelines * 2 > ((wss * 1024)/sizeof(cacheline_t))) | ||
| 229 | ;//bail_out("static memory arena too small"); | ||
| 230 | |||
| 231 | if (pos + num_cachelines > ((wss * 1024)/sizeof(cacheline_t))) { | ||
| 232 | // wrap to beginning | ||
| 233 | mem = arena; | ||
| 234 | pos = num_cachelines; | ||
| 235 | } else { | ||
| 236 | mem = arena + pos; | ||
| 237 | pos += num_cachelines; | ||
| 238 | } | ||
| 239 | |||
| 240 | return mem; | ||
| 241 | } | ||
| 242 | */ | ||
| 243 | static volatile int dont_optimize_me = 0; | ||
| 244 | |||
| 245 | #define RANDOM_WALK 1 | ||
| 246 | static int loop_once(int wss, int write) | ||
| 247 | { | ||
| 248 | volatile cacheline_t *mem; | ||
| 249 | int temp; | ||
| 250 | |||
| 251 | #ifdef RANDOM_WALK | ||
| 252 | mem = random_start(wss); | ||
| 253 | // printf("Using start offset %ld. Data here is %d. data size: %ld\n", mem-arena, mem->line[0], sizeof(mem->line[0])); | ||
| 254 | temp = random_walk(mem, wss, write); | ||
| 255 | #else | ||
| 256 | mem = sequential_start(wss); | ||
| 257 | temp = sequential_walk(mem, wss, write); | ||
| 258 | #endif | ||
| 259 | dont_optimize_me = temp; | ||
| 260 | // printf("%d", dont_optimize_me); | ||
| 261 | return dont_optimize_me; | ||
| 262 | } | ||
| 263 | |||
| 264 | int main(int argc, char** argv) { | ||
| 265 | SET_UP | ||
| 266 | int write; | ||
| 267 | long wss; | ||
| 268 | double duration; | ||
| 269 | double program_end; | ||
| 270 | // Reads in benchmark params from stdin | ||
| 271 | // <long: wss in bytes> <float: duration in seconds> <bool: if we should also write> | ||
| 272 | if (scanf("%ld %lf %d", &wss, &duration, &write) != 3) { | ||
| 273 | fprintf(stderr, "Bad input, please enter 3 parameters: <WSS (Int)> <Duration (Double)> <Write (Bool)>.\n"); | ||
| 274 | exit(1); | ||
| 275 | } | ||
| 276 | printf("random_walk: Using parameters: %ld, %lf, %d\n", wss, duration, write); | ||
| 277 | wss /= 1024; | ||
| 278 | program_end = duration + wctime(); | ||
| 279 | // Initialize memory | ||
| 280 | size_t arena_sz = wss*1024; | ||
| 281 | arena = alloc_arena(arena_sz*2, 0, 0); | ||
| 282 | init_arena(arena, arena_sz); | ||
| 283 | loop_once(wss, write); | ||
| 284 | // This loop contains the original content of job(int wss, int write, double exec_time, double program_end) | ||
| 285 | while (1) { | ||
| 286 | double emergency_exit = program_end + 1; | ||
| 287 | |||
| 288 | if (wctime() > program_end) { | ||
| 289 | break; | ||
| 290 | } else { | ||
| 291 | double last_loop = 0, loop_start; | ||
| 292 | int tmp = 0; | ||
| 293 | |||
| 294 | double start = cputime(); | ||
| 295 | double now = cputime(); | ||
| 296 | |||
| 297 | //while (now + last_loop < start) {// + exec_time) { | ||
| 298 | loop_start = now; | ||
| 299 | START_LOOP | ||
| 300 | tmp += loop_once(wss, write); | ||
| 301 | STOP_LOOP | ||
| 302 | now = cputime(); | ||
| 303 | last_loop = now - loop_start; | ||
| 304 | if (emergency_exit && wctime() > emergency_exit) { | ||
| 305 | /* Oops --- this should only be possible if the execution time tracking | ||
| 306 | * is broken in the LITMUS^RT kernel. */ | ||
| 307 | fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid()); | ||
| 308 | fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n"); | ||
| 309 | break; | ||
| 310 | } | ||
| 311 | long sum = 0; | ||
| 312 | // Verify that we actually traversed the whole wss | ||
| 313 | for (volatile cacheline_t* loc = arena; loc < arena + (wss*1024)/sizeof(cacheline_t); loc++) { | ||
| 314 | sum += loc->line[1]; | ||
| 315 | } | ||
| 316 | if (sum != wss * CACHELINES_IN_1KB) { | ||
| 317 | fprintf(stderr, "We hopped the wrong number of times! Hops: %ld, should have been: %ld\n", sum, wss * CACHELINES_IN_1KB); | ||
| 318 | } | ||
| 319 | //} | ||
| 320 | |||
| 321 | //sleep_next_period(); | ||
| 322 | continue; | ||
| 323 | } | ||
| 324 | } | ||
| 325 | WRITE_TO_FILE | ||
| 326 | printf("random_walk: done walking %ldKiB.\n", wss); | ||
| 327 | return 0; | ||
| 328 | } | ||
| 329 | /* | ||
| 330 | #define OPTSTR "p:wl:m:i:b:k:u:r:" | ||
| 331 | int main(int argc, char** argv) | ||
| 332 | { | ||
| 333 | int ret; | ||
| 334 | lt_t wcet, period, budget; | ||
| 335 | double wcet_ms, period_ms, budget_ms; | ||
| 336 | unsigned int priority = LITMUS_NO_PRIORITY; | ||
| 337 | int migrate = 0; | ||
| 338 | int cluster = 0; | ||
| 339 | int opt; | ||
| 340 | int wait = 0; | ||
| 341 | double duration = 0, start = 0; | ||
| 342 | struct rt_task param; | ||
| 343 | struct mc2_task mc2_param; | ||
| 344 | struct reservation_config config; | ||
| 345 | int res_type = PERIODIC_POLLING; | ||
| 346 | size_t arena_sz; | ||
| 347 | int wss; | ||
| 348 | int uncacheable = 0; | ||
| 349 | int read_access = 0, write; | ||
| 350 | int verbose = 0; | ||
| 351 | unsigned int job_no; | ||
| 352 | struct control_page* cp; | ||
| 353 | |||
| 354 | * default for reservation * | ||
| 355 | config.id = 0; | ||
| 356 | config.cpu = -1; | ||
| 357 | |||
| 358 | mc2_param.crit = CRIT_LEVEL_C; | ||
| 359 | |||
| 360 | budget_ms = 1000; | ||
| 361 | wss = 32; | ||
| 362 | |||
| 363 | while ((opt = getopt(argc, argv, OPTSTR)) != -1) { | ||
| 364 | switch (opt) { | ||
| 365 | case 'w': | ||
| 366 | wait = 1; | ||
| 367 | break; | ||
| 368 | case 'p': | ||
| 369 | cluster = atoi(optarg); | ||
| 370 | migrate = 1; | ||
| 371 | config.cpu = cluster; | ||
| 372 | break; | ||
| 373 | case 'k': | ||
| 374 | wss = atoi(optarg); | ||
| 375 | break; | ||
| 376 | case 'm': | ||
| 377 | mc2_param.crit = atoi(optarg); | ||
| 378 | if ((mc2_param.crit >= CRIT_LEVEL_A) && (mc2_param.crit <= CRIT_LEVEL_C)) { | ||
| 379 | res_type = PERIODIC_POLLING; | ||
| 380 | } | ||
| 381 | else | ||
| 382 | usage("Invalid criticality level."); | ||
| 383 | break; | ||
| 384 | case 'b': | ||
| 385 | budget_ms = atof(optarg); | ||
| 386 | break; | ||
| 387 | case 'r': | ||
| 388 | read_access = atoi(optarg); | ||
| 389 | break; | ||
| 390 | case 'q': | ||
| 391 | priority = want_non_negative_int(optarg, "-q"); | ||
| 392 | if (!litmus_is_valid_fixed_prio(priority)) | ||
| 393 | usage("Invalid priority"); | ||
| 394 | config.priority = atoi(optarg); | ||
| 395 | break; | ||
| 396 | case 'u': | ||
| 397 | uncacheable = atoi(optarg); | ||
| 398 | break; | ||
| 399 | case 'v': | ||
| 400 | verbose = 1; | ||
| 401 | break; | ||
| 402 | case ':': | ||
| 403 | usage("Argument missing."); | ||
| 404 | break; | ||
| 405 | case '?': | ||
| 406 | default: | ||
| 407 | usage("Bad argument."); | ||
| 408 | break; | ||
| 409 | } | ||
| 410 | } | ||
| 411 | srand(getpid()); | ||
| 412 | if (read_access == 1) | ||
| 413 | write = 0; | ||
| 414 | else | ||
| 415 | write = 1; | ||
| 416 | * | ||
| 417 | * We need three parameters | ||
| 418 | * | ||
| 419 | if (argc - optind < 3) | ||
| 420 | usage("Arguments missing."); | ||
| 421 | |||
| 422 | wcet_ms = atof(argv[optind + 0]); | ||
| 423 | period_ms = atof(argv[optind + 1]); | ||
| 424 | |||
| 425 | wcet = ms2ns(wcet_ms); | ||
| 426 | period = ms2ns(period_ms); | ||
| 427 | budget = ms2ns(budget_ms); | ||
| 428 | if (wcet <= 0) | ||
| 429 | usage("The worst-case execution time must be a " | ||
| 430 | "positive number."); | ||
| 431 | if (period <= 0) | ||
| 432 | usage("The period must be a positive number."); | ||
| 433 | if (wcet > period) { | ||
| 434 | usage("The worst-case execution time must not " | ||
| 435 | "exceed the period."); | ||
| 436 | } | ||
| 437 | |||
| 438 | duration = atof(argv[optind + 2]); | ||
| 439 | |||
| 440 | if (migrate) { | ||
| 441 | ret = be_migrate_to_domain(cluster); | ||
| 442 | if (ret < 0) | ||
| 443 | bail_out("could not migrate to target partition or cluster."); | ||
| 444 | } | ||
| 445 | |||
| 446 | * reservation config * | ||
| 447 | config.id = gettid(); | ||
| 448 | config.priority = priority; | ||
| 449 | config.polling_params.budget = budget; | ||
| 450 | config.polling_params.period = period; | ||
| 451 | config.polling_params.offset = 0; | ||
| 452 | config.polling_params.relative_deadline = 0; | ||
| 453 | |||
| 454 | if (config.polling_params.budget > config.polling_params.period) { | ||
| 455 | usage("The budget must not exceed the period."); | ||
| 456 | } | ||
| 457 | |||
| 458 | * create a reservation * | ||
| 459 | ret = reservation_create(res_type, &config); | ||
| 460 | if (ret < 0) { | ||
| 461 | bail_out("failed to create reservation."); | ||
| 462 | } | ||
| 463 | |||
| 464 | init_rt_task_param(¶m); | ||
| 465 | param.exec_cost = wcet; | ||
| 466 | param.period = period; | ||
| 467 | param.phase = 0; | ||
| 468 | param.relative_deadline = 0; | ||
| 469 | param.priority = priority == LITMUS_NO_PRIORITY ? LITMUS_LOWEST_PRIORITY : priority; | ||
| 470 | param.cls = RT_CLASS_HARD; | ||
| 471 | param.budget_policy = NO_ENFORCEMENT; | ||
| 472 | param.release_policy = TASK_PERIODIC; | ||
| 473 | if (migrate) { | ||
| 474 | param.cpu = gettid(); | ||
| 475 | } | ||
| 476 | ret = set_rt_task_param(gettid(), ¶m); | ||
| 477 | if (ret < 0) | ||
| 478 | bail_out("could not setup rt task params"); | ||
| 479 | |||
| 480 | mc2_param.res_id = gettid(); | ||
| 481 | ret = set_mc2_task_param(gettid(), &mc2_param); | ||
| 482 | if (ret < 0) | ||
| 483 | bail_out("could not setup mc2 task params"); | ||
| 484 | |||
| 485 | arena_sz = wss*1024; | ||
| 486 | arena = alloc_arena(arena_sz*2, 0, uncacheable); | ||
| 487 | init_arena(arena, arena_sz); | ||
| 488 | loop_once(wss, write); | ||
| 489 | |||
| 490 | ret = init_litmus(); | ||
| 491 | if (ret != 0) | ||
| 492 | bail_out("init_litmus() failed\n"); | ||
| 493 | |||
| 494 | mlockall(MCL_CURRENT | MCL_FUTURE); | ||
| 495 | |||
| 496 | if (mc2_param.crit == CRIT_LEVEL_C) | ||
| 497 | set_page_color(-1); | ||
| 498 | else | ||
| 499 | set_page_color(config.cpu); | ||
| 500 | |||
| 501 | start = wctime(); | ||
| 502 | ret = task_mode(LITMUS_RT_TASK); | ||
| 503 | if (ret != 0) | ||
| 504 | bail_out("could not become RT task"); | ||
| 505 | |||
| 506 | if (wait) { | ||
| 507 | ret = wait_for_ts_release(); | ||
| 508 | if (ret != 0) | ||
| 509 | bail_out("wait_for_ts_release()"); | ||
| 510 | start = wctime(); | ||
| 511 | } | ||
| 512 | cp = get_ctrl_page(); | ||
| 513 | |||
| 514 | while (job(wss, write, wcet_ms * 0.001, start + duration)) { | ||
| 515 | if (verbose) { | ||
| 516 | get_job_no(&job_no); | ||
| 517 | fprintf(stderr, "rtspin/%d:%u @ %.4fms\n", gettid(), | ||
| 518 | job_no, (wctime() - start) * 1000); | ||
| 519 | if (cp) { | ||
| 520 | double deadline, current, release; | ||
| 521 | lt_t now = litmus_clock(); | ||
| 522 | deadline = ns2s((double) cp->deadline); | ||
| 523 | current = ns2s((double) now); | ||
| 524 | release = ns2s((double) cp->release); | ||
| 525 | fprintf(stderr, | ||
| 526 | "\trelease: %" PRIu64 "ns (=%.2fs)\n", | ||
| 527 | (uint64_t) cp->release, release); | ||
| 528 | fprintf(stderr, | ||
| 529 | "\tdeadline: %" PRIu64 "ns (=%.2fs)\n", | ||
| 530 | (uint64_t) cp->deadline, deadline); | ||
| 531 | fprintf(stderr, | ||
| 532 | "\tcur time: %" PRIu64 "ns (=%.2fs)\n", | ||
| 533 | (uint64_t) now, current); | ||
| 534 | fprintf(stderr, | ||
| 535 | "\ttime until deadline: %.2fms\n", | ||
| 536 | (deadline - current) * 1000); | ||
| 537 | } | ||
| 538 | } | ||
| 539 | }; | ||
| 540 | |||
| 541 | ret = task_mode(BACKGROUND_TASK); | ||
| 542 | if (ret != 0) | ||
| 543 | bail_out("could not become regular task (huh?)"); | ||
| 544 | |||
| 545 | reservation_destroy(gettid(), config.cpu); | ||
| 546 | dealloc_arena(arena, arena_sz*2); | ||
| 547 | printf("%s finished.\n", argv[0]); | ||
| 548 | return 0; | ||
| 549 | } | ||
| 550 | */ | ||
