From edfb01f94b56fcc3e3bc7098e233fcbbb862b462 Mon Sep 17 00:00:00 2001 From: leochanj105 Date: Thu, 28 Oct 2021 11:15:36 -0400 Subject: fix stitch and loc, added flush --- dag | 2 +- dag_example | 5 +- extra.h | 102 ++++----- extra_prev.h | 601 ++++++++++++++++++++++++++++++++++++++++++++++++++ run_case_study_dag.py | 13 +- tmp | 1 + 6 files changed, 649 insertions(+), 75 deletions(-) create mode 100644 extra_prev.h create mode 100644 tmp diff --git a/dag b/dag index bb0a8cf..9180799 100644 --- a/dag +++ b/dag @@ -1 +1 @@ -1,disparity_qcif, dis001, 2, 1, 5, 1, 15, 1, 0, 12, 14, mser_qcif, mser001, 5, 9 \ No newline at end of file +0, localization_qcif, loc001, 100, 15, loc, 1, 50, 1, 0, 50, 50 \ No newline at end of file diff --git a/dag_example b/dag_example index ce39489..05a7c3f 100644 --- a/dag_example +++ b/dag_example @@ -1,4 +1 @@ -1, mser_qcif, mser001, 5, 1, 1, 1, 100, 1, 0, sift_qcif, sift001 -0, mser_qcif, mser002, 3, 2, 2, 1, 10, 1, 0 -1, svm_qcif, svm001, 6, 2, 3, 1, 50, 1, 0, localization_qcif, localization001 -0, tracking_qcif, tracking001, 3, 3, 4, 1, 20, 1, 17 +0, stitch_qcif, stitch001, 10, 2, stitch, 1, 50, 1, 17, 15, 16 \ No newline at end of file diff --git a/extra.h b/extra.h index fce8c3f..9da536d 100644 --- a/extra.h +++ b/extra.h @@ -30,7 +30,7 @@ extern int sched_getcpu(); #endif // This is a proxy for "case study mode" now -#define LITMUS 0 +#define LITMUS 0 #define MMDC_PROF 0 #if LITMUS @@ -60,6 +60,8 @@ int _rt_core; int _rt_will_output; struct timespec _rt_start, _rt_end; +int first_job; + char *_rt_run_id; char *_rt_our_prog_name; char *_rt_other_prog_name; @@ -78,10 +80,10 @@ char _rt_shm_name[_ID_SZ] = "/_libextra_barrier-"; #if LITMUS lt_t _rt_period; +int _rt_crit; lt_t _rt_phase; lt_t _rt_cost; lt_t _rt_deadline; -int _rt_crit; struct control_page *_rt_cp; #endif @@ -108,7 +110,7 @@ static void _rt_load_params_itrl(int argc, char **argv) { #if LITMUS fprintf(stderr, " in ms\n"); fprintf(stderr, " 0 for Level-A, 1 for Level-B, 2 for Level-C\n"); - fprintf(stderr, " in ms\n"); + fprintf(stderr, " in ms\n"); fprintf(stderr, " in ms\n"); fprintf(stderr, " in ms\n"); #endif /* LITMUS */ @@ -150,19 +152,23 @@ static void _rt_load_params_itrl(int argc, char **argv) { fprintf(stderr, "Run ID is too large! Keep it to less than %d characters.\n", _RT_FILENAME_LEN); exit(1); } -#ifdef PAIRED - // __rt_sem2_name happens to be the longest - if (strlen(pairId) + strlen(_rt_sem2_name) > _ID_SZ) { - fprintf(stderr, "PairID is too long! Maximum length is %ld characters.\n", _ID_SZ - strlen(_rt_sem2_name)); - exit(1); - } _rt_start_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(long long)); _rt_end_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(long long)); - _rt_exec_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(float)); if (!_rt_end_time || !_rt_start_time) { perror("Unable to allocate buffers for execution times"); exit(1); } + _rt_exec_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(float)); + if (!_rt_exec_time) { + perror("Unable to allocate buffer for execution times"); + exit(1); + } +#ifdef PAIRED + // __rt_sem2_name happens to be the longest + if (strlen(pairId) + strlen(_rt_sem2_name) > _ID_SZ) { + fprintf(stderr, "PairID is too long! Maximum length is %ld characters.\n", _ID_SZ - strlen(_rt_sem2_name)); + exit(1); + } // Use PairID to create unique semaphore and shared memory paths strcat(_rt_sem1_name, pairId); strcat(_rt_sem2_name, pairId); @@ -201,16 +207,11 @@ static void _rt_load_params_itrl(int argc, char **argv) { exit(1); } *_rt_barrier = 0; -#else - _rt_start_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(long long)); - _rt_end_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(long long)); - _rt_exec_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(float)); - if (!_rt_exec_time) { - perror("Unable to allocate buffer for execution times"); - exit(1); - } +// #else + #endif /* PAIRED */ _rt_jobs_complete = 0; + first_job = 1; mlockall(MCL_CURRENT || MCL_FUTURE); #if LITMUS _rt_period = ms2ns(strtoul(argv[end], NULL, 10)); @@ -218,7 +219,6 @@ static void _rt_load_params_itrl(int argc, char **argv) { _rt_phase = ms2ns(strtoul(argv[end+2], NULL, 10)); _rt_cost = ms2ns(strtoul(argv[end+3], NULL, 10)); _rt_deadline = ms2ns(strtoul(argv[end+4], NULL, 10)); - // _rt_phase = 0; unsigned int wait = 1; if (be_migrate_to_domain(_rt_core) < 0) { perror("Unable to migrate to specified CPU"); @@ -232,7 +232,6 @@ static void _rt_load_params_itrl(int argc, char **argv) { rt_param.relative_deadline = _rt_deadline; rt_param.phase = _rt_phase; rt_param.priority = LITMUS_LOWEST_PRIORITY; - // rt_param.priority = ns2ms(_rt_phase); rt_param.cls = _rt_crit; rt_param.budget_policy = NO_ENFORCEMENT; rt_param.cpu = _rt_core; @@ -358,21 +357,10 @@ static void _rt_save_job_result() { _rt_end_time[_rt_jobs_complete] = _rt_end.tv_sec; _rt_end_time[_rt_jobs_complete] *= _BILLION; _rt_end_time[_rt_jobs_complete] += _rt_end.tv_nsec; - +// #else _rt_exec_time[_rt_jobs_complete] = _rt_end.tv_sec - _rt_start.tv_sec; _rt_exec_time[_rt_jobs_complete] *= _BILLION; _rt_exec_time[_rt_jobs_complete] += _rt_end.tv_nsec - _rt_start.tv_nsec; -// #else -// _rt_start_time[_rt_jobs_complete] = _rt_start.tv_sec; -// _rt_start_time[_rt_jobs_complete] *= _BILLION; -// _rt_start_time[_rt_jobs_complete] += _rt_start.tv_nsec; -// _rt_end_time[_rt_jobs_complete] = _rt_end.tv_sec; -// _rt_end_time[_rt_jobs_complete] *= _BILLION; -// _rt_end_time[_rt_jobs_complete] += _rt_end.tv_nsec; - -// _rt_exec_time[_rt_jobs_complete] = _rt_end.tv_sec - _rt_start.tv_sec; -// _rt_exec_time[_rt_jobs_complete] *= _BILLION; -// _rt_exec_time[_rt_jobs_complete] += _rt_end.tv_nsec - _rt_start.tv_nsec; // #endif /* PAIRED */ #if MMDC_PROF _rt_mmdc_read[_rt_jobs_complete] = mmdc_res.read_bytes; @@ -439,7 +427,12 @@ out: // Start a job static void _rt_start_loop() { + // Let the first job run before synchrnous release --- make sure we have no further page faults + if(first_job){ + return; + } #if LITMUS + // static lt_t last = 0; if (_rt_jobs_complete == 0) { if(wait_for_ts_release() != 0){ perror("Unable to wait for taskset release"); @@ -451,45 +444,27 @@ static void _rt_start_loop() { perror("Unable to sleep for next period"); } } - // static lt_t last = 0; - // lt_t now = litmus_clock(); - // fprintf(stderr, "current now : %llu\n", now); - // if (now > _rt_cp->deadline) { - // fprintf(stderr, "(%s/%d:%lu) ", _rt_our_prog_name, gettid(), _rt_cp->job_index); - // // if (_rt_crit == 0) - // // fprintf(stderr, "CATASTROPHIC: Level-A"); - // // else if (_rt_crit == 1) - // // fprintf(stderr, "HAZARDOUS: Level-B"); - // // else - // // fprintf(stderr, "MAJOR: Level-C"); - // fprintf(stderr, " tardy %llu ns, " - // "relative tardiness %f\n", - // now - _rt_cp->deadline, - // (now - _rt_cp->deadline) / (double)_rt_period); - // } + // if (last == 0) { // last = now; - // } - // else if (now > last + 60ull * _BILLION && _rt_crit >= 2) { + // } else if (now > last + 60ull * _BILLION && _rt_crit >= 2) { // last = now; // fprintf(stderr, "(%s/%d:%lu) Ping\n", _rt_our_prog_name, gettid(), _rt_cp->job_index); // } - // lt_t now = litmus_clock(); - // if(_rt_jobs_complete != 0){ - // fprintf(stderr, "in start before sleep: release: %llu, deadline: %llu, now: %llu\n", _rt_cp->release ,_rt_cp->deadline, litmus_clock()); - - // fprintf(stderr, "in start after sleep: release: %llu, deadline: %llu, now: %llu\n", _rt_cp->release ,_rt_cp->deadline, litmus_clock()); + // if (sleep_next_period() != 0) { + // perror("Unable to sleep for next period"); // } #else sched_yield(); + // sleep(1); #endif /* LITMUS */ #ifdef PAIRED FIRST_UNLOCK FIRST_LOCK #endif /* PAIRED */ -#if !LITMUS +// #if !LITMUS FLUSH_CACHES -#endif +// #endif #ifdef PAIRED BARRIER_SYNC #endif /* PAIRED */ @@ -503,6 +478,11 @@ static void _rt_start_loop() { // Complete a job static void _rt_stop_loop() { clock_gettime(CLOCK_MONOTONIC, &_rt_end); + // Set first_job == 0 + if(first_job){ + first_job = 0; + return; + } #if MMDC_PROF /* This freezes the profiling and makes results available */ pause_mmdc_profiling(mmdc); @@ -513,16 +493,10 @@ static void _rt_stop_loop() { long long end = _rt_end_time[_rt_jobs_complete]; if (end > _rt_cp->deadline) { fprintf(stderr, "(%s/%d:%lu) ", _rt_our_prog_name, gettid(), _rt_cp->job_index); - // if (_rt_crit == 0) - // fprintf(stderr, "CATASTROPHIC: Level-A"); - // else if (_rt_crit == 1) - // fprintf(stderr, "HAZARDOUS: Level-B"); - // else - // fprintf(stderr, "MAJOR: Level-C"); fprintf(stderr, " tardy %llu ns, " "relative tardiness %f\n", end - _rt_cp->deadline, - (end - _rt_cp->deadline) / (double)_rt_period); + (end - _rt_cp->deadline) / (double)_rt_deadline); } #endif _rt_jobs_complete++; diff --git a/extra_prev.h b/extra_prev.h new file mode 100644 index 0000000..64d334f --- /dev/null +++ b/extra_prev.h @@ -0,0 +1,601 @@ +/** + * Copyright 2019 Sims Hill Osborne and 2020 Joshua Bakita + * + * This header provides facilities by which to separably run and time TACLeBench + * To use this for paired task timing, define PAIRED (pass CFLAGS=-DPAIRED to make) + **/ +#define _GNU_SOURCE +#include // For O_CREAT and O_RDWR +#include // For sched_yield() +#include // For sem_{open, post, wait}() +#include +#include // For exit() +#include // For strlen() +#include // For mlockall() +#include // For ftruncate() +#include + +// This is only visible if _GNU_SOURCE is defined, and that define does not +// come along to places where this file is included. Address this by manually +// forcing it into the global namespace. +extern int sched_getcpu(); + +// These constants correspond to the imx6q-sabredb platform +#define LINE_SIZE 32 +#define L2_SIZE 16*2048*32 + +#if __arm__ +#include +#include +#endif + +// This is a proxy for "case study mode" now +#define LITMUS 0 +#define MMDC_PROF 0 + +#if LITMUS +#include +#endif + +#if MMDC_PROF +#include "/media/speedy/litmus/tools/mmdc/mmdc.h" +#endif + +// Store state globally so that the job can be outside main() +// Arrays use float as a comprimise between overflow and size +// Paired arrays use long longs as precision is more important for those times +// #ifdef PAIRED +long long *_rt_start_time; +long long *_rt_end_time; +// #else +float *_rt_exec_time; +// #endif +#if MMDC_PERF +float *_rt_mmdc_read; +float *_rt_mmdc_write; +#endif +long _rt_jobs_complete; +long _rt_max_jobs; +int _rt_core; +int _rt_will_output; +struct timespec _rt_start, _rt_end; + +char *_rt_run_id; +char *_rt_our_prog_name; +char *_rt_other_prog_name; +char *_rt_other_core; +#define _RT_FILENAME_LEN 64 +#define _BILLION (1000*1000*1000) +#ifdef PAIRED +char *_rt_barrier; +sem_t *_rt_first_sem, *_rt_second_sem; +int _rt_lock_id; +#define _ID_SZ 128 +char _rt_sem1_name[_ID_SZ] = "/_libextra_first_sem-"; +char _rt_sem2_name[_ID_SZ] = "/_libextra_second_sem-"; +char _rt_shm_name[_ID_SZ] = "/_libextra_barrier-"; +#endif /* PAIRED */ + +#if LITMUS +lt_t _rt_period; +lt_t _rt_phase; +lt_t _rt_cost; +lt_t _rt_deadline; +int _rt_crit; +struct control_page *_rt_cp; +#endif + +static void _rt_load_params_itrl(int argc, char **argv) { +#ifdef PAIRED + if (argc != (8 + LITMUS*5) && argc != (9 + LITMUS*5)) { + fprintf(stderr, "Usage: %s \n", argv[0]); +#else + if (argc != (6 + LITMUS*5)) { + fprintf(stderr, "Usage: %s \n", argv[0]); +#endif /* PAIRED */ + fprintf(stderr, " string for logging. Name of this task.\n"); + fprintf(stderr, " integer number of iterations. -1 for infinite.\n"); + fprintf(stderr, " integer core number. Only used for LITMUS-RT.\n"); +#ifdef PAIRED + fprintf(stderr, " integer for logging. Core of paired task.\n"); + fprintf(stderr, " string for logging. Name of paired task.\n"); +#endif /* PAIRED */ + fprintf(stderr, " string to append with .txt to yield output file name.\n"); + fprintf(stderr, " 1 to save results, 0 to discard.\n"); +#ifdef PAIRED + fprintf(stderr, " (optional).\n"); +#endif +#if LITMUS + fprintf(stderr, " in ms\n"); + fprintf(stderr, " 0 for Level-A, 1 for Level-B, 2 for Level-C\n"); + fprintf(stderr, " in ms\n"); + fprintf(stderr, " in ms\n"); + fprintf(stderr, " in ms\n"); +#endif /* LITMUS */ + exit(1); + } + _rt_our_prog_name = argv[1]; + _rt_max_jobs = atol(argv[2]); +#if !LITMUS + _rt_core = sched_getcpu(); +#else + _rt_core = atoi(argv[3]); +#endif +#ifdef PAIRED + _rt_other_core = argv[4]; + _rt_other_prog_name = argv[5]; + _rt_run_id = argv[6]; + _rt_will_output = atoi(argv[7]); + char *pairId; + int end; + if (argc > 8) { + pairId = argv[8]; + end = 9; + } else { + pairId = "none"; + end = 8; + } +#else + _rt_other_core = "none"; + _rt_other_prog_name = "none"; + _rt_run_id = argv[4]; + _rt_will_output = atoi(argv[5]); + int end = 6; +#endif /* PAIRED */ + if (_rt_max_jobs < 0 && _rt_will_output != 0) { + fprintf(stderr, "Infinite loops only supported when output is disabled!\n"); + exit(1); + } + if (strlen(_rt_run_id) + 5 > _RT_FILENAME_LEN) { + fprintf(stderr, "Run ID is too large! Keep it to less than %d characters.\n", _RT_FILENAME_LEN); + exit(1); + } +#ifdef PAIRED + // __rt_sem2_name happens to be the longest + if (strlen(pairId) + strlen(_rt_sem2_name) > _ID_SZ) { + fprintf(stderr, "PairID is too long! Maximum length is %ld characters.\n", _ID_SZ - strlen(_rt_sem2_name)); + exit(1); + } + _rt_start_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(long long)); + _rt_end_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(long long)); + _rt_exec_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(float)); + if (!_rt_end_time || !_rt_start_time) { + perror("Unable to allocate buffers for execution times"); + exit(1); + } + // Use PairID to create unique semaphore and shared memory paths + strcat(_rt_sem1_name, pairId); + strcat(_rt_sem2_name, pairId); + strcat(_rt_shm_name, pairId); + _rt_first_sem = sem_open(_rt_sem1_name, O_CREAT, 644, 0); + _rt_second_sem = sem_open(_rt_sem2_name, O_CREAT, 644, 0); + if (_rt_first_sem == SEM_FAILED || _rt_second_sem == SEM_FAILED) { + perror("Error while creating semaphores"); + exit(1); + } + // Create shared memory for barrier synchronization and infer lock ID + int barrier_file = shm_open(_rt_shm_name, O_CREAT | O_RDWR | O_EXCL, 644); + if (barrier_file == -1) { + // File already existed - we're the 2nd program and thus lock ID 2 + _rt_lock_id = 2; + barrier_file = shm_open(_rt_shm_name, O_CREAT | O_RDWR, 644); + } else { + _rt_lock_id = 1; + } + if (barrier_file == -1) { + perror("Error while creating shared memory for barrier synchronization"); + exit(1); + } + if (ftruncate(barrier_file, 2) == -1) { + perror("Error while setting size of shared memory for barrier synchronization"); + exit(1); + } + _rt_barrier = mmap(NULL, 2, PROT_WRITE, MAP_SHARED, barrier_file, 0); + if (_rt_barrier == MAP_FAILED) { + perror("Error while mapping shared memory for barrier synchronization"); + exit(1); + } + // If we're the 2nd user of this barrier, mark it as in-use + if (_rt_lock_id == 2 && !__sync_bool_compare_and_swap(_rt_barrier+1, 0, 1)) { + fprintf(stderr, "Pair ID already in use!\n"); + exit(1); + } + *_rt_barrier = 0; +#else + _rt_start_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(long long)); + _rt_end_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(long long)); + _rt_exec_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(float)); + if (!_rt_exec_time) { + perror("Unable to allocate buffer for execution times"); + exit(1); + } +#endif /* PAIRED */ + _rt_jobs_complete = 0; + mlockall(MCL_CURRENT || MCL_FUTURE); +#if LITMUS + _rt_period = ms2ns(strtoul(argv[end], NULL, 10)); + _rt_crit = atoi(argv[end+1]); + _rt_phase = ms2ns(strtoul(argv[end+2], NULL, 10)); + _rt_cost = ms2ns(strtoul(argv[end+3], NULL, 10)); + _rt_deadline = ms2ns(strtoul(argv[end+4], NULL, 10)); + // _rt_phase = 0; + unsigned int wait = 1; + if (be_migrate_to_domain(_rt_core) < 0) { + perror("Unable to migrate to specified CPU"); + exit(1); + } + struct rt_task rt_param; + init_rt_task_param(&rt_param); + // Fake exec cost - this value ignored by the MC^2 scheduler + rt_param.exec_cost = _rt_cost; + // rt_param.exec_cost = _rt_period; + rt_param.period = _rt_period; + rt_param.relative_deadline = _rt_deadline; + // rt_param.relative_deadline = 0; + rt_param.phase = _rt_phase; + rt_param.priority = LITMUS_LOWEST_PRIORITY; + // rt_param.priority = ns2ms(_rt_phase); + rt_param.cls = _rt_crit; + rt_param.budget_policy = NO_ENFORCEMENT; + rt_param.cpu = _rt_core; + rt_param.release_policy = TASK_PERIODIC; + if (set_rt_task_param(gettid(), &rt_param) < 0) { + perror("Unable to set real-time parameters"); + exit(1); + } + if (init_litmus() != 0) { + perror("init_litmus failed"); + exit(1); + } + if (task_mode(LITMUS_RT_TASK) != 0) { + perror("Unable to become real-time task"); + exit(1); + } + _rt_cp = get_ctrl_page(); + // if (wait && wait_for_ts_release() != 0) { + // perror("Unable to wait for taskset release"); + // exit(1); + // } +#endif /* LITMUS */ +#if MMDC_PROF + SETUP_MMDC +#endif +} + +#define SETUP_MMDC \ + _rt_mmdc_read = calloc(_rt_max_jobs * _rt_will_output, sizeof(float));\ + _rt_mmdc_write = calloc(_rt_max_jobs * _rt_will_output, sizeof(float));\ + if (!_rt_mmdc_read || !_rt_mmdc_write) {\ + perror("Unable to allocate buffer for MMDC data");\ + exit(1);\ + }\ + MMDC_PROFILE_RES_t mmdc_res;\ + memset(&mmdc_res, 0, sizeof(MMDC_PROFILE_RES_t));\ + int fd = open("/dev/mem", O_RDWR, 0);\ + if (fd < 0) {\ + perror("Unable to open /dev/mem");\ + exit(1);\ + }\ + pMMDC_t mmdc = mmap(NULL, 0x4000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, MMDC_P0_IPS_BASE_ADDR);\ + if (mmdc == MAP_FAILED) {\ + perror("Unable to map MMDC address space");\ + exit(1);\ + }\ + mmdc->madpcr1 = axi_arm1;\ + msync(&(mmdc->madpcr1),4,MS_SYNC); + +#if __arm__ +// On ARM, manually flush the cache +#define FLUSH_CACHES \ + volatile uint8_t buffer[L2_SIZE * 4]; \ + for (uint32_t j = 0; j < 4; j++) \ + for (uint32_t i = 0; i < L2_SIZE * 4; i += LINE_SIZE) \ + buffer[i]++; +#else +// On x86 call the wbinvld instruction (it's in a kernel module due to it being ring-0) +#define FLUSH_CACHES \ + FILE *fp = fopen("/proc/wbinvd", "r");\ + if (fp == NULL) {\ + perror("Cache flush module interface cannot be opened");\ + exit(1);\ + }\ + char dummy;\ + if (fread(&dummy, 1, 1, fp) == 0) {\ + perror("Unable to access cache flush module interface");\ + exit(1);\ + }\ + fclose(fp); +#endif + +// This semaphore-based synchronization is from Sims +#define FIRST_UNLOCK \ + if (_rt_lock_id == 1) {\ + if (sem_post(_rt_second_sem) != 0) {\ + perror("Unable to unlock second semaphore");\ + exit(1);\ + }\ + } \ + else {\ + if (sem_post(_rt_first_sem) != 0) {\ + perror("Unable to unlock first semaphore");\ + exit(1);\ + }\ + } \ + +#define FIRST_LOCK \ + if (_rt_lock_id == 1) {\ + if (sem_wait(_rt_first_sem) != 0) {\ + perror("Unable to wait on first semaphore");\ + exit(1);\ + }\ + }\ + else {\ + if (sem_wait(_rt_second_sem) != 0) {\ + perror("Unable to wait on second semaphore");\ + exit(1);\ + }\ + } + +// This ensures a very low difference between pair member start times +#define BARRIER_SYNC \ + if (__sync_bool_compare_and_swap(_rt_barrier, 0, 1)) {\ + while (!__sync_bool_compare_and_swap(_rt_barrier, 0, 0)) {};\ + }\ + else {\ + __sync_bool_compare_and_swap(_rt_barrier, 1, 0);\ + } + +// Buffer timing result from a single job +static void _rt_save_job_result() { + if (!_rt_will_output) + return; + if (_rt_jobs_complete >= _rt_max_jobs) { + fprintf(stderr, "Max jobs setting too small! Trying to record job #%ld when we only have space for %ld jobs. Exiting...\n", _rt_jobs_complete, _rt_max_jobs); + exit(1); + } +// #ifdef PAIRED + _rt_start_time[_rt_jobs_complete] = _rt_start.tv_sec; + _rt_start_time[_rt_jobs_complete] *= _BILLION; + _rt_start_time[_rt_jobs_complete] += _rt_start.tv_nsec; + _rt_end_time[_rt_jobs_complete] = _rt_end.tv_sec; + _rt_end_time[_rt_jobs_complete] *= _BILLION; + _rt_end_time[_rt_jobs_complete] += _rt_end.tv_nsec; + + _rt_exec_time[_rt_jobs_complete] = _rt_end.tv_sec - _rt_start.tv_sec; + _rt_exec_time[_rt_jobs_complete] *= _BILLION; + _rt_exec_time[_rt_jobs_complete] += _rt_end.tv_nsec - _rt_start.tv_nsec; +// #else +// _rt_start_time[_rt_jobs_complete] = _rt_start.tv_sec; +// _rt_start_time[_rt_jobs_complete] *= _BILLION; +// _rt_start_time[_rt_jobs_complete] += _rt_start.tv_nsec; +// _rt_end_time[_rt_jobs_complete] = _rt_end.tv_sec; +// _rt_end_time[_rt_jobs_complete] *= _BILLION; +// _rt_end_time[_rt_jobs_complete] += _rt_end.tv_nsec; + +// _rt_exec_time[_rt_jobs_complete] = _rt_end.tv_sec - _rt_start.tv_sec; +// _rt_exec_time[_rt_jobs_complete] *= _BILLION; +// _rt_exec_time[_rt_jobs_complete] += _rt_end.tv_nsec - _rt_start.tv_nsec; +// #endif /* PAIRED */ +#if MMDC_PROF + _rt_mmdc_read[_rt_jobs_complete] = mmdc_res.read_bytes; + _rt_mmdc_write[_rt_jobs_complete] = mmdc_res.write_bytes; +#endif /* MMDC_PROF */ +} + +// Save all buffered timing results to disk +static void _rt_write_to_file() { + char fileName[_RT_FILENAME_LEN]; + FILE *fp; + munlockall(); + if (!_rt_will_output) + goto out; + strcpy(fileName, _rt_run_id); + strcat(fileName, ".txt"); + fp = fopen(fileName, "a"); + if (fp == NULL) { + perror("Unable to open output file"); + exit(1); + } + // Baseline output uses a similar format with "none" for unused fields + for (int i = 0; i < _rt_jobs_complete; i++){ + fprintf(fp, "%s %s %u %s %ld", _rt_our_prog_name, _rt_other_prog_name, + _rt_core, _rt_other_core, _rt_max_jobs); +// #if LITMUS +// fprintf(fp, " %lld", _rt_cp->release); +// #endif +// #ifdef PAIRED + // For unclear legacy reasons, paired tasks emit sec and ns separately + fprintf(fp, " %lld %lld %lld %lld", + _rt_start_time[i] / _BILLION, _rt_start_time[i] % _BILLION, + _rt_end_time[i] / _BILLION, _rt_end_time[i] % _BILLION); +// #if LITMUS +// fprintf(fp, " %lld", _rt_cp->deadline); +// #endif +// #else + fprintf(fp, " %.f", _rt_exec_time[i]); +// #endif /* PAIRED */ + fprintf(fp, " %s %d %.f %.f\n", _rt_run_id, i, +#if MMDC_PROF + _rt_mmdc_read[i], _rt_mmdc_write[i]); +#else + 0.0, 0.0); +#endif /* MMDC_PROF */ + } + fclose(fp); +out: +#if LITMUS + if (task_mode(BACKGROUND_TASK) != 0) { + perror("Unable to become a real-time task"); + exit(1); + } +#endif /* LITMUS */ +#ifdef PAIRED + munmap(_rt_barrier, 2); + sem_unlink(_rt_sem1_name); + sem_unlink(_rt_sem2_name); + shm_unlink(_rt_shm_name); + free(_rt_start_time); + free(_rt_end_time); +#else + free(_rt_exec_time); +#endif /* PAIRED */ +#if MMDC_PROF + free(_rt_mmdc_read); + free(_rt_mmdc_write); +#endif /* MMDC_PROF */ +} + +// Start a job +static void _rt_start_loop() { +#if LITMUS + if (_rt_jobs_complete == 0) { + if(wait_for_ts_release() != 0){ + perror("Unable to wait for taskset release"); + exit(1); + } + } + else{ + if (sleep_next_period() != 0) { + perror("Unable to sleep for next period"); + } + } + + // fprintf(stderr, "now: %llu\n", litmus_clock()); + // static lt_t last = 0; + // lt_t now = litmus_clock(); + // if (now > _rt_cp->deadline) { + // fprintf(stderr, "(%s/%d:%lu) ", _rt_our_prog_name, gettid(), _rt_cp->job_index); + // if (_rt_crit == 0) + // fprintf(stderr, "CATASTROPHIC: Level-A"); + // else if (_rt_crit == 1) + // fprintf(stderr, "HAZARDOUS: Level-B"); + // else + // fprintf(stderr, "MAJOR: Level-C"); + // fprintf(stderr, " tardy %llu ns, " + // "relative tardiness %f\n", + // now - _rt_cp->deadline, + // (now - _rt_cp->deadline) / (double)_rt_period); + // } + // if (last == 0) { + // last = now; + // } + // else if (now > last + 60ull * _BILLION && _rt_crit >= 2) { + // last = now; + // fprintf(stderr, "(%s/%d:%lu) Ping\n", _rt_our_prog_name, gettid(), _rt_cp->job_index); + // } + // lt_t now = litmus_clock(); + // if(_rt_jobs_complete != 0){ + // fprintf(stderr, "in start before sleep: release: %llu, deadline: %llu, now: %llu\n", _rt_cp->release ,_rt_cp->deadline, litmus_clock()); + + // fprintf(stderr, "in start after sleep: release: %llu, deadline: %llu, now: %llu\n", _rt_cp->release ,_rt_cp->deadline, litmus_clock()); + // } + // if (sleep_next_period() != 0) { + // perror("Unable to sleep for next period"); + // } +#else + sched_yield(); +#endif /* LITMUS */ +#ifdef PAIRED + FIRST_UNLOCK + FIRST_LOCK +#endif /* PAIRED */ +#if !LITMUS + FLUSH_CACHES +#endif +#ifdef PAIRED + BARRIER_SYNC +#endif /* PAIRED */ +#if MMDC_PROF + /* This disables profiling, resets the counters, clears the overflow bit, and enables profiling */ + start_mmdc_profiling(mmdc); +#endif /* MMDC_PROF */ + clock_gettime(CLOCK_MONOTONIC, &_rt_start); +} + +// Complete a job +static void _rt_stop_loop() { + clock_gettime(CLOCK_MONOTONIC, &_rt_end); +#if MMDC_PROF + /* This freezes the profiling and makes results available */ + pause_mmdc_profiling(mmdc); + get_mmdc_profiling_results(mmdc, &mmdc_res); +#endif /* MMDC_PROF */ + _rt_save_job_result(); +#if LITMUS + long long end = _rt_end_time[_rt_jobs_complete]; + if (end > _rt_cp->deadline) { + fprintf(stderr, "(%s/%d:%lu) ", _rt_our_prog_name, gettid(), _rt_cp->job_index); + // if (_rt_crit == 0) + // fprintf(stderr, "CATASTROPHIC: Level-A"); + // else if (_rt_crit == 1) + // fprintf(stderr, "HAZARDOUS: Level-B"); + // else + // fprintf(stderr, "MAJOR: Level-C"); + fprintf(stderr, " tardy %llu ns, " + "relative tardiness %f\n", + end - _rt_cp->deadline, + (end - _rt_cp->deadline) / (double)_rt_deadline); + } +#endif + _rt_jobs_complete++; +} + +/****** New API ****** + * Intended structure: + * + * |int main(int argc, char **argv) { + * | SET_UP + * | ... + * | for_each_job { + * | tacleInit(); + * | tacleMain(); + * | } + * | WRITE_TO_FILE + * |} + * + * The main() function must call its parameters argc and argv for SET_UP to be + * able to read them. + * Only SET_UP necessarily has to be in main(). + * + * We use some niche C features, here's a quick explaination: + * 1. The && operator doesn't evaluate the right-hand side of the expression + * unless the left side evaluated to true. We use this to only execute + * _rt_start_loop() when the loop will actually run. + * 2. The comma operator executes the first expression and then throws away the + * result. We use this to call our void function from inside a comparison. + */ +#define for_each_job \ + for (; (_rt_max_jobs == -1 || _rt_jobs_complete < _rt_max_jobs) && (_rt_start_loop(),1); \ + _rt_stop_loop()) + +/****** Legacy API ****** + * Intended structure: + * + * |int main(int argc, char **argv) { + * | SET_UP + * | for (jobsComplete=0; jobsComplete /sys/fs/resctrl/core-{}/cpus_list'.format(core,core+16, core)) # run('echo {} > /sys/fs/resctrl/core-{}/cpus_list'.format(core, core)) @@ -156,7 +157,7 @@ def main(pathName): if launch[0] == '0': if LITMUS: binary = binary_path + binary_name + "_single" - # Arg format: + # Arg format: arg = " " + task_name + " " + num_iters +" " + core_num +" " + run_id +" " + save_result+" " + period +" " + crt_level + " "+ phase + " " + cost + " " + deadline bench_tsk = subprocess.Popen(input_cmd[binary_name] + " | numactl --interleave=all " + binary + arg, shell=True, executable='/bin/bash', stderr=stderr_file) @@ -173,7 +174,7 @@ def main(pathName): if not pid_str: print("Unable to launch {} as a solo task! Exiting...".format(task_name)) return 1 - run("echo " + pid_str + " > /sys/fs/resctrl/core-" + str(phys_core) + "/tasks") + # run("echo " + pid_str + " > /sys/fs/resctrl/core-" + str(phys_core) + "/tasks") else: # Paried tasks other_binary_name = launch[OTHER_BINARY_NAME].strip() @@ -193,7 +194,7 @@ def main(pathName): if LITMUS: binary = binary_path + binary_name + "_pair" other_binary = binary_path + other_binary_name + "_pair" - # Arg format: <0 other core> + # Arg format: <0 other core> arg1 = " " + task_name + " " + num_iters +" " + core_num +" " + other_core_num+" "+ other_task_name+" "+ run_id +" " + save_result+" " +str(pairID) +" "+ period +" " + crt_level +" "+phase + " " + cost + " " + deadline arg2 = " " + other_task_name + " " + num_iters +" " + other_core_num +" " + core_num+" "+ task_name+" "+ run_id +" " + save_result+" " +str(pairID) +" "+ period +" " + crt_level+" " +phase + " " + other_cost + " " + other_deadline # print(input_cmd[binary_name] + " | numactl --membind=0 " + binary + arg1) @@ -207,7 +208,7 @@ def main(pathName): arg1 = " " + task_name + " " + num_iters +" " + core_num +" " + other_core_num+" "+ other_task_name+" "+ run_id +" " + save_result+" " +str(pairID) arg2 = " " + other_task_name + " " + num_iters +" " + other_core_num +" " + core_num+" "+ task_name+" "+ run_id +" " + save_result+" " +str(pairID) bench_tsk1 = subprocess.Popen(input_cmd[binary_name] + " | numactl --membind=0 taskset -c " + core_num + " " + binary + arg1, shell=True, executable='/bin/bash', stderr=stderr_file) - bench_tsk2 = subprocess.Popen(input_cmd[other_binary_name] + " | numactl --membind=1 taskset -c " + core_num + " " + other_binary + arg2, shell=True, executable='/bin/bash', stderr=stderr_file) + bench_tsk2 = subprocess.Popen(input_cmd[other_binary_name] + " | numactl --membind=1 taskset -c " + other_core_num + " " + other_binary + arg2, shell=True, executable='/bin/bash', stderr=stderr_file) # print(binary + " " + task_name,other_binary + " " +other_task_name) pid1_str = ID2PID(binary + " " + task_name) pid2_str = ID2PID(other_binary + " " +other_task_name) @@ -215,8 +216,8 @@ def main(pathName): print("Unable to launch {} and {} in a pair! Exiting...".format(task_name, other_task_name)) return 1 - run("echo " + pid1_str + " > /sys/fs/resctrl/core-" + str(phys_core) + "/tasks") - run("echo " + pid2_str + " > /sys/fs/resctrl/core-" + str(phys_core) + "/tasks") + # run("echo " + pid1_str + " > /sys/fs/resctrl/core-" + str(phys_core) + "/tasks") + # run("echo " + pid2_str + " > /sys/fs/resctrl/core-" + str(phys_core) + "/tasks") # run("wait " + pid1_str) # run("wait " + pid2_str) pairID += 1 diff --git a/tmp b/tmp new file mode 100644 index 0000000..105cb46 --- /dev/null +++ b/tmp @@ -0,0 +1 @@ +123123123123123121223 \ No newline at end of file -- cgit v1.2.2