#include #include #include #include #include #include #include #include #include #include "litmus.h" #include "common.h" extern int main_job(void); static char* progname; int loops = 10; //struct timeval t1, t2; static void usage(char *error) { fprintf(stderr, "Error: %s\n", error); fprintf(stderr, "Usage:\n" " rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n" " rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n" " rt_spin -l\n" "\n" "COMMON-OPTS = [-w] [-s SCALE]\n" " [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n" "\n" "WCET and PERIOD are microseconds, DURATION is seconds.\n"); exit(EXIT_FAILURE); } inline unsigned long get_cyclecount (void) { unsigned long value; // Read CCNT Register asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value)); return value; } static int job(double exec_time, double program_end) { if (wctime() > program_end) return 0; else { register int iter = 0; //register unsigned long t; //t = get_cyclecount(); //gettimeofday(&t1, NULL); while (iter++ < loops) { main_job(); } //t = get_cyclecount() - t; //printf("%ld cycles\n", t); //gettimeofday(&t2, NULL); //printf("%ld us\n", ((t2.tv_sec * 1000000 + t2.tv_usec) - (t1.tv_sec * 1000000 + t1.tv_usec))); sleep_next_period(); return 1; } } #define OPTSTR "p:wves:l:m:i:b:k:" int main(int argc, char** argv) { int ret; lt_t wcet; lt_t period; lt_t budget; double wcet_us, period_us, budget_us; unsigned int priority = LITMUS_NO_PRIORITY; int migrate = 0; int cluster = 0; int opt; int wait = 0; int want_enforcement = 0; double duration = 0, start = 0; double scale = 1.0; task_class_t class = RT_CLASS_HARD; struct rt_task param; struct mc2_task mc2_param; struct reservation_config config; int res_type = PERIODIC_POLLING; uint32_t mode_mask = (1 << 0); int i; unsigned int job_no; progname = argv[0]; /* default for reservation */ config.id = 0; config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */ config.cpu = -1; mc2_param.crit = CRIT_LEVEL_C; budget_us = 10000; while ((opt = getopt(argc, argv, OPTSTR)) != -1) { switch (opt) { case 'w': wait = 1; break; case 'p': cluster = atoi(optarg); migrate = 1; config.cpu = cluster; break; case 'e': want_enforcement = 1; break; case 's': scale = atof(optarg); break; case 'l': loops = atoi(optarg); break; case 'm': mc2_param.crit = atoi(optarg); if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) { usage("Invalid criticality level."); } res_type = PERIODIC_POLLING; break; case 'b': budget_us = atof(optarg); break; case 'i': config.priority = atoi(optarg); break; case 'k': mode_mask = atoi(optarg); case ':': usage("Argument missing."); break; case '?': default: usage("Bad argument."); break; } } if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY) usage("Bad criticailty level or priority"); if (argc - optind < 3) usage("Arguments missing."); wcet_us = atof(argv[optind + 0]); period_us = atof(argv[optind + 1]); wcet = us2ns(wcet_us); period = us2ns(period_us); budget = us2ns(budget_us); if (wcet <= 0) usage("The worst-case execution time must be a " "positive number."); if (period <= 0) usage("The period must be a positive number."); if (wcet > period) { usage("The worst-case execution time must not " "exceed the period."); } duration = atof(argv[optind + 2]); if (migrate) { ret = be_migrate_to_domain(cluster); if (ret < 0) bail_out("could not migrate to target partition or cluster."); } /* reservation config */ config.id = gettid(); config.polling_params.budget = budget; config.polling_params.period = period; config.polling_params.offset = 0; config.polling_params.relative_deadline = 0; if (config.polling_params.budget > config.polling_params.period) { usage("The budget must not exceed the period."); } /* create reservations */ for(i = 0; i < 32; i++){ if ( !((1 << i) & mode_mask ) ) continue; config.mode = i; ret = reservation_create(res_type, &config); if (ret < 0) { bail_out("failed to create reservation."); } } init_rt_task_param(¶m); param.exec_cost = wcet; param.period = period; param.priority = priority; param.cls = class; param.release_policy = TASK_PERIODIC; param.budget_policy = (want_enforcement) ? PRECISE_ENFORCEMENT : NO_ENFORCEMENT; if (migrate) { param.cpu = gettid(); } ret = set_rt_task_param(gettid(), ¶m); if (ret < 0) bail_out("could not setup rt task params"); mc2_param.res_id = gettid(); mc2_param.mode_mask = mode_mask; ret = set_mc2_task_param(gettid(), &mc2_param); //printf("SET_MC2_TASK\n"); if (ret < 0) bail_out("could not setup mc2 task params"); init_litmus(); //printf("CALL\n"); if (mc2_param.crit == CRIT_LEVEL_C) set_page_color(8); else if (mc2_param.crit < CRIT_LEVEL_C) set_page_color(config.cpu*2 + mc2_param.crit); //printf("CALL\n"); //printf("INIT_LITMUS\n"); start = wctime(); ret = task_mode(LITMUS_RT_TASK); //printf("TASK_MODE\n"); if (ret != 0) bail_out("could not become RT task"); if (wait) { //printf("BEFORE WAIT\n"); ret = wait_for_ts_release(); if (ret != 0) bail_out("wait_for_ts_release()"); start = wctime(); } while (job(wcet_us * 0.000001 * scale, start + duration)) {}; ret = task_mode(BACKGROUND_TASK); if (ret != 0) bail_out("could not become regular task (huh?)"); reservation_destroy(gettid(), config.cpu); printf("%s/%d finished.\n",progname, gettid()); return 0; }