diff options
| author | Namhoon Kim <namhoonk@cs.unc.edu> | 2017-05-01 16:02:05 -0400 |
|---|---|---|
| committer | Namhoon Kim <namhoonk@cs.unc.edu> | 2017-05-01 16:02:05 -0400 |
| commit | 11765fcf37057053065abd3715cf9cb46f2fa4db (patch) | |
| tree | 8403d716bbcbd96493c481a82e7e02b5da9231e8 /bin/test1.c | |
| parent | bfee87a910560e022b04c81a026b1f88522cd62f (diff) | |
RTSS17 submitwip-modechange
Diffstat (limited to 'bin/test1.c')
| -rw-r--r-- | bin/test1.c | 453 |
1 files changed, 0 insertions, 453 deletions
diff --git a/bin/test1.c b/bin/test1.c deleted file mode 100644 index a38d402..0000000 --- a/bin/test1.c +++ /dev/null | |||
| @@ -1,453 +0,0 @@ | |||
| 1 | #include <sys/time.h> | ||
| 2 | |||
| 3 | #include <stdio.h> | ||
| 4 | #include <stdlib.h> | ||
| 5 | #include <unistd.h> | ||
| 6 | #include <time.h> | ||
| 7 | #include <string.h> | ||
| 8 | #include <assert.h> | ||
| 9 | #include <limits.h> | ||
| 10 | #include <sys/mman.h> | ||
| 11 | #include <sys/types.h> | ||
| 12 | #include <sys/stat.h> | ||
| 13 | #include <fcntl.h> | ||
| 14 | |||
| 15 | #include "litmus.h" | ||
| 16 | #include "common.h" | ||
| 17 | |||
| 18 | |||
| 19 | |||
| 20 | static void usage(char *error) { | ||
| 21 | fprintf(stderr, "Error: %s\n", error); | ||
| 22 | fprintf(stderr, | ||
| 23 | "Usage:\n" | ||
| 24 | " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n" | ||
| 25 | " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n" | ||
| 26 | " rt_spin -l\n" | ||
| 27 | "\n" | ||
| 28 | "COMMON-OPTS = [-w] [-s SCALE]\n" | ||
| 29 | " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS]\n" | ||
| 30 | " [-X LOCKING-PROTOCOL] [-L CRITICAL SECTION LENGTH] [-Q RESOURCE-ID]" | ||
| 31 | "\n" | ||
| 32 | "WCET and PERIOD are milliseconds, DURATION is seconds.\n" | ||
| 33 | "CRITICAL SECTION LENGTH is in milliseconds.\n"); | ||
| 34 | exit(EXIT_FAILURE); | ||
| 35 | } | ||
| 36 | |||
| 37 | /* | ||
| 38 | * returns the character that made processing stop, newline or EOF | ||
| 39 | */ | ||
| 40 | static int skip_to_next_line(FILE *fstream) | ||
| 41 | { | ||
| 42 | int ch; | ||
| 43 | for (ch = fgetc(fstream); ch != EOF && ch != '\n'; ch = fgetc(fstream)); | ||
| 44 | return ch; | ||
| 45 | } | ||
| 46 | |||
| 47 | static void skip_comments(FILE *fstream) | ||
| 48 | { | ||
| 49 | int ch; | ||
| 50 | for (ch = fgetc(fstream); ch == '#'; ch = fgetc(fstream)) | ||
| 51 | skip_to_next_line(fstream); | ||
| 52 | ungetc(ch, fstream); | ||
| 53 | } | ||
| 54 | |||
| 55 | static void get_exec_times(const char *file, const int column, | ||
| 56 | int *num_jobs, double **exec_times) | ||
| 57 | { | ||
| 58 | FILE *fstream; | ||
| 59 | int cur_job, cur_col, ch; | ||
| 60 | *num_jobs = 0; | ||
| 61 | |||
| 62 | fstream = fopen(file, "r"); | ||
| 63 | if (!fstream) | ||
| 64 | bail_out("could not open execution time file"); | ||
| 65 | |||
| 66 | /* figure out the number of jobs */ | ||
| 67 | do { | ||
| 68 | skip_comments(fstream); | ||
| 69 | ch = skip_to_next_line(fstream); | ||
| 70 | if (ch != EOF) | ||
| 71 | ++(*num_jobs); | ||
| 72 | } while (ch != EOF); | ||
| 73 | |||
| 74 | if (-1 == fseek(fstream, 0L, SEEK_SET)) | ||
| 75 | bail_out("rewinding file failed"); | ||
| 76 | |||
| 77 | /* allocate space for exec times */ | ||
| 78 | *exec_times = calloc(*num_jobs, sizeof(*exec_times)); | ||
| 79 | if (!*exec_times) | ||
| 80 | bail_out("couldn't allocate memory"); | ||
| 81 | |||
| 82 | for (cur_job = 0; cur_job < *num_jobs && !feof(fstream); ++cur_job) { | ||
| 83 | |||
| 84 | skip_comments(fstream); | ||
| 85 | |||
| 86 | for (cur_col = 1; cur_col < column; ++cur_col) { | ||
| 87 | /* discard input until we get to the column we want */ | ||
| 88 | int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,"); | ||
| 89 | } | ||
| 90 | |||
| 91 | /* get the desired exec. time */ | ||
| 92 | if (1 != fscanf(fstream, "%lf", (*exec_times)+cur_job)) { | ||
| 93 | fprintf(stderr, "invalid execution time near line %d\n", | ||
| 94 | cur_job); | ||
| 95 | exit(EXIT_FAILURE); | ||
| 96 | } | ||
| 97 | |||
| 98 | skip_to_next_line(fstream); | ||
| 99 | } | ||
| 100 | |||
| 101 | assert(cur_job == *num_jobs); | ||
| 102 | fclose(fstream); | ||
| 103 | } | ||
| 104 | |||
| 105 | #define NUMS 4096 | ||
| 106 | static int num[NUMS]; | ||
| 107 | static char* progname; | ||
| 108 | static char* smem; | ||
| 109 | static int access_type; /* 0: read 1: write */ | ||
| 110 | |||
| 111 | static int loop_once(void) | ||
| 112 | { | ||
| 113 | int i, j = 0; | ||
| 114 | for (i = 0; i < NUMS; i++) { | ||
| 115 | j += num[i]++; | ||
| 116 | if (access_type == 1) { | ||
| 117 | smem[i] = j%255; | ||
| 118 | printf("Write %d at [%d]\n", smem[i], i); | ||
| 119 | } else { | ||
| 120 | char tmp = smem[i]; | ||
| 121 | printf("Read %d at [%d]\n", tmp, i); | ||
| 122 | } | ||
| 123 | } | ||
| 124 | return j; | ||
| 125 | } | ||
| 126 | |||
| 127 | static int loop_for(double exec_time, double emergency_exit) | ||
| 128 | { | ||
| 129 | double last_loop = 0, loop_start; | ||
| 130 | int tmp = 0; | ||
| 131 | |||
| 132 | double start = cputime(); | ||
| 133 | double now = cputime(); | ||
| 134 | |||
| 135 | while (now + last_loop < start + exec_time) { | ||
| 136 | loop_start = now; | ||
| 137 | tmp += loop_once(); | ||
| 138 | now = cputime(); | ||
| 139 | last_loop = now - loop_start; | ||
| 140 | if (emergency_exit && wctime() > emergency_exit) { | ||
| 141 | /* Oops --- this should only be possible if the execution time tracking | ||
| 142 | * is broken in the LITMUS^RT kernel. */ | ||
| 143 | fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid()); | ||
| 144 | fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n"); | ||
| 145 | break; | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | return tmp; | ||
| 150 | } | ||
| 151 | |||
| 152 | |||
| 153 | static void debug_delay_loop(void) | ||
| 154 | { | ||
| 155 | double start, end, delay; | ||
| 156 | |||
| 157 | while (1) { | ||
| 158 | for (delay = 0.5; delay > 0.01; delay -= 0.01) { | ||
| 159 | start = wctime(); | ||
| 160 | loop_for(delay, 0); | ||
| 161 | end = wctime(); | ||
| 162 | printf("%6.4fs: looped for %10.8fs, delta=%11.8fs, error=%7.4f%%\n", | ||
| 163 | delay, | ||
| 164 | end - start, | ||
| 165 | end - start - delay, | ||
| 166 | 100 * (end - start - delay) / delay); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | static int job(double exec_time, double program_end, int lock_od, double cs_length) | ||
| 172 | { | ||
| 173 | double chunk1, chunk2; | ||
| 174 | |||
| 175 | if (wctime() > program_end) | ||
| 176 | return 0; | ||
| 177 | else { | ||
| 178 | if (lock_od >= 0) { | ||
| 179 | /* simulate critical section somewhere in the middle */ | ||
| 180 | chunk1 = drand48() * (exec_time - cs_length); | ||
| 181 | chunk2 = exec_time - cs_length - chunk1; | ||
| 182 | |||
| 183 | /* non-critical section */ | ||
| 184 | loop_for(chunk1, program_end + 1); | ||
| 185 | |||
| 186 | /* critical section */ | ||
| 187 | litmus_lock(lock_od); | ||
| 188 | loop_for(cs_length, program_end + 1); | ||
| 189 | litmus_unlock(lock_od); | ||
| 190 | |||
| 191 | /* non-critical section */ | ||
| 192 | loop_for(chunk2, program_end + 2); | ||
| 193 | } else { | ||
| 194 | //loop_for(exec_time, program_end + 1); | ||
| 195 | loop_once(); | ||
| 196 | } | ||
| 197 | sleep_next_period(); | ||
| 198 | return 1; | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | #define OPTSTR "p:c:wlveo:f:s:q:r:X:L:Q:vt:" | ||
| 203 | int main(int argc, char** argv) | ||
| 204 | { | ||
| 205 | int ret; | ||
| 206 | lt_t wcet; | ||
| 207 | lt_t period; | ||
| 208 | double wcet_ms, period_ms; | ||
| 209 | unsigned int priority = LITMUS_NO_PRIORITY; | ||
| 210 | int migrate = 0; | ||
| 211 | int cluster = 0; | ||
| 212 | int reservation = -1; | ||
| 213 | int opt; | ||
| 214 | int wait = 0; | ||
| 215 | int test_loop = 0; | ||
| 216 | int column = 1; | ||
| 217 | const char *file = NULL; | ||
| 218 | int want_enforcement = 0; | ||
| 219 | double duration = 0, start = 0; | ||
| 220 | double *exec_times = NULL; | ||
| 221 | double scale = 1.0; | ||
| 222 | task_class_t class = RT_CLASS_HARD; | ||
| 223 | int cur_job = 0, num_jobs = 0; | ||
| 224 | struct rt_task param; | ||
| 225 | |||
| 226 | int verbose = 0; | ||
| 227 | unsigned int job_no; | ||
| 228 | |||
| 229 | /* locking */ | ||
| 230 | int lock_od = -1; | ||
| 231 | int resource_id = 0; | ||
| 232 | const char *lock_namespace = "./rtspin-locks"; | ||
| 233 | int protocol = -1; | ||
| 234 | double cs_length = 1; /* millisecond */ | ||
| 235 | int fd; | ||
| 236 | |||
| 237 | progname = argv[0]; | ||
| 238 | |||
| 239 | while ((opt = getopt(argc, argv, OPTSTR)) != -1) { | ||
| 240 | switch (opt) { | ||
| 241 | case 'w': | ||
| 242 | wait = 1; | ||
| 243 | break; | ||
| 244 | case 'p': | ||
| 245 | cluster = atoi(optarg); | ||
| 246 | migrate = 1; | ||
| 247 | break; | ||
| 248 | case 'r': | ||
| 249 | reservation = atoi(optarg); | ||
| 250 | break; | ||
| 251 | case 'q': | ||
| 252 | priority = atoi(optarg); | ||
| 253 | if (!litmus_is_valid_fixed_prio(priority)) | ||
| 254 | usage("Invalid priority."); | ||
| 255 | break; | ||
| 256 | case 'c': | ||
| 257 | class = str2class(optarg); | ||
| 258 | if (class == -1) | ||
| 259 | usage("Unknown task class."); | ||
| 260 | break; | ||
| 261 | case 'e': | ||
| 262 | want_enforcement = 1; | ||
| 263 | break; | ||
| 264 | case 'l': | ||
| 265 | test_loop = 1; | ||
| 266 | break; | ||
| 267 | case 'o': | ||
| 268 | column = atoi(optarg); | ||
| 269 | break; | ||
| 270 | case 'f': | ||
| 271 | file = optarg; | ||
| 272 | break; | ||
| 273 | case 's': | ||
| 274 | scale = atof(optarg); | ||
| 275 | break; | ||
| 276 | case 'X': | ||
| 277 | protocol = lock_protocol_for_name(optarg); | ||
| 278 | if (protocol < 0) | ||
| 279 | usage("Unknown locking protocol specified."); | ||
| 280 | break; | ||
| 281 | case 'L': | ||
| 282 | cs_length = atof(optarg); | ||
| 283 | if (cs_length <= 0) | ||
| 284 | usage("Invalid critical section length."); | ||
| 285 | break; | ||
| 286 | case 'Q': | ||
| 287 | resource_id = atoi(optarg); | ||
| 288 | if (resource_id <= 0 && strcmp(optarg, "0")) | ||
| 289 | usage("Invalid resource ID."); | ||
| 290 | break; | ||
| 291 | case 'v': | ||
| 292 | verbose = 1; | ||
| 293 | break; | ||
| 294 | case 't': | ||
| 295 | access_type = atoi(optarg); | ||
| 296 | if (access_type != 0 && access_type != 1) | ||
| 297 | usage("Wrong SHM access type."); | ||
| 298 | break; | ||
| 299 | case ':': | ||
| 300 | usage("Argument missing."); | ||
| 301 | break; | ||
| 302 | case '?': | ||
| 303 | default: | ||
| 304 | usage("Bad argument."); | ||
| 305 | break; | ||
| 306 | } | ||
| 307 | } | ||
| 308 | |||
| 309 | if (test_loop) { | ||
| 310 | debug_delay_loop(); | ||
| 311 | return 0; | ||
| 312 | } | ||
| 313 | |||
| 314 | srand(getpid()); | ||
| 315 | |||
| 316 | if (file) { | ||
| 317 | get_exec_times(file, column, &num_jobs, &exec_times); | ||
| 318 | |||
| 319 | if (argc - optind < 2) | ||
| 320 | usage("Arguments missing."); | ||
| 321 | |||
| 322 | for (cur_job = 0; cur_job < num_jobs; ++cur_job) { | ||
| 323 | /* convert the execution time to seconds */ | ||
| 324 | duration += exec_times[cur_job] * 0.001; | ||
| 325 | } | ||
| 326 | } else { | ||
| 327 | /* | ||
| 328 | * if we're not reading from the CSV file, then we need | ||
| 329 | * three parameters | ||
| 330 | */ | ||
| 331 | if (argc - optind < 3) | ||
| 332 | usage("Arguments missing."); | ||
| 333 | } | ||
| 334 | |||
| 335 | wcet_ms = atof(argv[optind + 0]); | ||
| 336 | period_ms = atof(argv[optind + 1]); | ||
| 337 | |||
| 338 | wcet = ms2ns(wcet_ms); | ||
| 339 | period = ms2ns(period_ms); | ||
| 340 | if (wcet <= 0) | ||
| 341 | usage("The worst-case execution time must be a " | ||
| 342 | "positive number."); | ||
| 343 | if (period <= 0) | ||
| 344 | usage("The period must be a positive number."); | ||
| 345 | if (!file && wcet > period) { | ||
| 346 | usage("The worst-case execution time must not " | ||
| 347 | "exceed the period."); | ||
| 348 | } | ||
| 349 | |||
| 350 | if (!file) | ||
| 351 | duration = atof(argv[optind + 2]); | ||
| 352 | else if (file && num_jobs > 1) | ||
| 353 | duration += period_ms * 0.001 * (num_jobs - 1); | ||
| 354 | |||
| 355 | if (migrate) { | ||
| 356 | ret = be_migrate_to_domain(cluster); | ||
| 357 | if (ret < 0) | ||
| 358 | bail_out("could not migrate to target partition or cluster."); | ||
| 359 | } | ||
| 360 | |||
| 361 | |||
| 362 | /* allocate shared memory */ | ||
| 363 | fd = open("/dev/shm/region1", O_CREAT|O_RDWR|O_TRUNC, 0666); | ||
| 364 | if (fd == -1) | ||
| 365 | bail_out("could not open /dev/shm."); | ||
| 366 | |||
| 367 | fallocate(fd, 0, 0, 4096); | ||
| 368 | smem = NULL; | ||
| 369 | if (access_type == 1) { | ||
| 370 | printf("open write mmap now.\n"); | ||
| 371 | smem = (char*) mmap(NULL, 4096, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0); | ||
| 372 | if (smem == MAP_FAILED) | ||
| 373 | bail_out("mmap error."); | ||
| 374 | close(fd); | ||
| 375 | } | ||
| 376 | else { | ||
| 377 | printf("open read mmap now.\n"); | ||
| 378 | smem = (char*) mmap(NULL, 4096, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0); | ||
| 379 | if (smem == MAP_FAILED) | ||
| 380 | bail_out("mmap error."); | ||
| 381 | close(fd); | ||
| 382 | } | ||
| 383 | printf("smem addr = %p\n", smem); | ||
| 384 | init_rt_task_param(¶m); | ||
| 385 | param.exec_cost = wcet; | ||
| 386 | param.period = period; | ||
| 387 | param.priority = priority; | ||
| 388 | param.cls = class; | ||
| 389 | param.budget_policy = (want_enforcement) ? | ||
| 390 | PRECISE_ENFORCEMENT : NO_ENFORCEMENT; | ||
| 391 | if (migrate) { | ||
| 392 | if (reservation >= 0) | ||
| 393 | param.cpu = reservation; | ||
| 394 | else | ||
| 395 | param.cpu = domain_to_first_cpu(cluster); | ||
| 396 | } | ||
| 397 | ret = set_rt_task_param(gettid(), ¶m); | ||
| 398 | if (ret < 0) | ||
| 399 | bail_out("could not setup rt task params"); | ||
| 400 | |||
| 401 | init_litmus(); | ||
| 402 | //test_call(0); | ||
| 403 | start = wctime(); | ||
| 404 | ret = task_mode(LITMUS_RT_TASK); | ||
| 405 | if (ret != 0) | ||
| 406 | bail_out("could not become RT task"); | ||
| 407 | |||
| 408 | if (protocol >= 0) { | ||
| 409 | /* open reference to semaphore */ | ||
| 410 | lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster); | ||
| 411 | if (lock_od < 0) { | ||
| 412 | perror("litmus_open_lock"); | ||
| 413 | usage("Could not open lock."); | ||
| 414 | } | ||
| 415 | } | ||
| 416 | |||
| 417 | |||
| 418 | if (wait) { | ||
| 419 | ret = wait_for_ts_release(); | ||
| 420 | if (ret != 0) | ||
| 421 | bail_out("wait_for_ts_release()"); | ||
| 422 | start = wctime(); | ||
| 423 | } | ||
| 424 | |||
| 425 | if (file) { | ||
| 426 | /* use times read from the CSV file */ | ||
| 427 | for (cur_job = 0; cur_job < num_jobs; ++cur_job) { | ||
| 428 | /* convert job's length to seconds */ | ||
| 429 | job(exec_times[cur_job] * 0.001 * scale, | ||
| 430 | start + duration, | ||
| 431 | lock_od, cs_length * 0.001); | ||
| 432 | } | ||
| 433 | } else { | ||
| 434 | do { | ||
| 435 | if (verbose) { | ||
| 436 | get_job_no(&job_no); | ||
| 437 | printf("rtspin/%d:%u @ %.4fms\n", gettid(), | ||
| 438 | job_no, (wctime() - start) * 1000); | ||
| 439 | } | ||
| 440 | /* convert to seconds and scale */ | ||
| 441 | } while (job(wcet_ms * 0.001 * scale, start + duration, | ||
| 442 | lock_od, cs_length * 0.001)); | ||
| 443 | } | ||
| 444 | |||
| 445 | ret = task_mode(BACKGROUND_TASK); | ||
| 446 | if (ret != 0) | ||
| 447 | bail_out("could not become regular task (huh?)"); | ||
| 448 | |||
| 449 | if (file) | ||
| 450 | free(exec_times); | ||
| 451 | |||
| 452 | return 0; | ||
| 453 | } | ||
