From edb491490ccd0cae4bd28ca9c9a7e095a47c749b Mon Sep 17 00:00:00 2001 From: Joshua Bakita Date: Wed, 21 Oct 2020 14:09:25 -0400 Subject: Fix infinite looping with libextra --- extra.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'extra.h') diff --git a/extra.h b/extra.h index a15313a..30940df 100644 --- a/extra.h +++ b/extra.h @@ -125,7 +125,7 @@ static void _rt_load_params_itrl(int argc, char **argv) { _rt_will_output = atoi(argv[5]); #endif /* PAIRED */ if (_rt_max_jobs < 0 && _rt_will_output != 0) { - fprintf(stderr, "Infinite loops only supported when _rt_will_output is disabled!\n"); + fprintf(stderr, "Infinite loops only supported when output is disabled!\n"); exit(1); } if (strlen(_rt_run_id) + 5 > _RT_FILENAME_LEN) { @@ -326,28 +326,28 @@ static void _rt_load_params_itrl(int argc, char **argv) { // 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); } - if (_rt_jobs_complete > -1 && _rt_will_output) { #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_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; #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; + _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 - } + _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 @@ -465,7 +465,7 @@ static void _rt_stop_loop() { * result. We use this to call our void function from inside a comparison. */ #define for_each_job \ - for (; _rt_jobs_complete < _rt_max_jobs && (_rt_start_loop(),1); \ + for (; (_rt_max_jobs == -1 || _rt_jobs_complete < _rt_max_jobs) && (_rt_start_loop(),1); \ _rt_stop_loop()) /****** Legacy API ****** -- cgit v1.2.2 From d17b33131c14864bd1eae275f49a3f148e21cf29 Mon Sep 17 00:00:00 2001 From: Leo Chan Date: Thu, 22 Oct 2020 01:53:21 -0400 Subject: Squashed commit of the sb-vbs branch. Includes the SD-VBS benchmarks modified to: - Use libextra to loop as realtime jobs - Preallocate memory before starting their main computation - Accept input via stdin instead of via argc Does not include the SD-VBS matlab code. Fixes libextra execution in LITMUS^RT. --- extra.h | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) (limited to 'extra.h') diff --git a/extra.h b/extra.h index 30940df..0d700ab 100644 --- a/extra.h +++ b/extra.h @@ -29,7 +29,7 @@ extern int sched_getcpu(); #include #endif -#define LITMUS 0 +#define LITMUS 1 #define MC2 0 #define MMDC_PROF 0 @@ -200,20 +200,6 @@ static void _rt_load_params_itrl(int argc, char **argv) { perror("Unable to migrate to specified CPU"); \ exit(1); \ } \ - struct reservation_config res; \ - res.id = gettid(); \ - res.cpu = cpu; \ - res.priority = LITMUS_HIGHEST_PRIORITY; \ - /* we take over half the CPU time (these are ns) */ \ - res.polling_params.budget = ms2ns(3000); \ - res.polling_params.period = ms2ns(3000); \ - res.polling_params.offset = 0; \ - res.polling_params.relative_deadline = ms2ns(3000); \ - /* Not 100% sure that we should use periodic polling */ \ - if (reservation_create(PERIODIC_POLLING, &res) < 0) { \ - perror("Unable to create reservation"); \ - exit(1); \ - } \ struct rt_task rt_param; \ init_rt_task_param(&rt_param); \ /* Supposedly the next two parameters are irrelevant when reservations are enabled, but I'm leaving them anyway... */ \ @@ -223,7 +209,7 @@ static void _rt_load_params_itrl(int argc, char **argv) { rt_param.cls = RT_CLASS_HARD; \ rt_param.release_policy = TASK_PERIODIC; \ rt_param.budget_policy = NO_ENFORCEMENT; \ - rt_param.cpu = cpu; \ + rt_param.cpu = _rt_core; \ if (set_rt_task_param(gettid(), &rt_param) < 0) { \ perror("Unable to set real-time parameters"); \ exit(1); \ @@ -244,13 +230,7 @@ static void _rt_load_params_itrl(int argc, char **argv) { #if MC2 #define MC2_SETUP \ - struct mc2_task mc2_param; \ - mc2_param.res_id = gettid(); \ - mc2_param.crit = CRIT_LEVEL_A; \ - if (set_mc2_task_param(gettid(), &mc2_param) < 0) { \ - perror("Unable to set MC^2 task params"); \ - exit(1); \ - } \ + set_page_color(rt_param.cpu); #else #define MC2_SETUP @@ -261,7 +241,6 @@ static void _rt_load_params_itrl(int argc, char **argv) { perror("Unable to become a real-time task"); \ exit(1); \ } \ - reservation_destroy(gettid(), rt_param.cpu); #if __arm__ // On ARM, manually flush the cache -- cgit v1.2.2 From 163c440444c74a4e0bbe0a8db3d1ca725413994b Mon Sep 17 00:00:00 2001 From: Joshua Bakita Date: Thu, 22 Oct 2020 03:17:31 -0400 Subject: Make SD-VBS compatible with run_bench.sh and cleanup SD-VBS: - Run silently - Fix some whitespace errors - Don't duplicate extra.h - Auto-detect if building with LITMUS-RT - Disable result checking - Add helper symlinks Misc: - Remove unused code from libextra - Set some missing rt_param fields in libextra - Disable CSV info dump from computeSMTslowdown.sh - Widen scope of .gitignore on .txt files - Include list of 2MB DIS pair benchmarks and inputs --- extra.h | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'extra.h') diff --git a/extra.h b/extra.h index 0d700ab..59ae97a 100644 --- a/extra.h +++ b/extra.h @@ -29,8 +29,7 @@ extern int sched_getcpu(); #include #endif -#define LITMUS 1 -#define MC2 0 +#define LITMUS 0 #define MMDC_PROF 0 #if LITMUS @@ -202,10 +201,11 @@ static void _rt_load_params_itrl(int argc, char **argv) { } \ struct rt_task rt_param; \ init_rt_task_param(&rt_param); \ - /* Supposedly the next two parameters are irrelevant when reservations are enabled, but I'm leaving them anyway... */ \ rt_param.exec_cost = ms2ns(999); \ rt_param.period = ms2ns(1000); \ - rt_param.priority = LITMUS_HIGHEST_PRIORITY; \ + rt_param.deadline = 0; \ + rt_param.phase = 0; \ + rt_param.priority = LITMUS_LOWEST_PRIORITY; \ rt_param.cls = RT_CLASS_HARD; \ rt_param.release_policy = TASK_PERIODIC; \ rt_param.budget_policy = NO_ENFORCEMENT; \ @@ -218,7 +218,6 @@ static void _rt_load_params_itrl(int argc, char **argv) { perror("init_litmus failed"); \ exit(1); \ } \ - MC2_SETUP \ if (task_mode(LITMUS_RT_TASK) != 0) { \ perror("Unable to become real-time task"); \ exit(1); \ @@ -228,14 +227,6 @@ static void _rt_load_params_itrl(int argc, char **argv) { exit(1); \ } -#if MC2 -#define MC2_SETUP \ - - set_page_color(rt_param.cpu); -#else -#define MC2_SETUP -#endif - #define CLEANUP_LITMUS \ if (task_mode(BACKGROUND_TASK) != 0) { \ perror("Unable to become a real-time task"); \ -- cgit v1.2.2 From a7c3210215bd1181ae93b23c313941dfb44519fb Mon Sep 17 00:00:00 2001 From: Joshua Bakita Date: Thu, 22 Oct 2020 22:46:39 -0400 Subject: Transform LITMUS-RT support in libextra to imply case-study mode Adds and parameters to benchmarks and disables cache flushing when compiled with LITMUS. Also fixes build with LITMUS enabled on yamaha.cs.unc.edu. Also allows output to be disabled, automatically infers _rt_lock_id, and allows for a specific pair ID for paired tasks. (The pair ID is added to all the semaphore and shared memory names, allowing multiple pairs to run in the system at a time.) --- extra.h | 197 ++++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 117 insertions(+), 80 deletions(-) (limited to 'extra.h') diff --git a/extra.h b/extra.h index 59ae97a..233cf3b 100644 --- a/extra.h +++ b/extra.h @@ -29,6 +29,7 @@ extern int sched_getcpu(); #include #endif +// This is a proxy for "case study mode" now #define LITMUS 0 #define MMDC_PROF 0 @@ -40,18 +41,6 @@ extern int sched_getcpu(); #include "/media/speedy/litmus/tools/mmdc/mmdc.h" #endif -#if LITMUS -#define SET_UP LOAD_PARAMS SETUP_LITMUS -#else -#define SET_UP LOAD_PARAMS -#endif - -#if MMDC_PROF -#define LOAD_PARAMS LOAD_PARAMS_ITRL SETUP_MMDC -#else -#define LOAD_PARAMS LOAD_PARAMS_ITRL -#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 @@ -81,47 +70,69 @@ char *_rt_other_core; 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 +long unsigned int _rt_period; #endif static void _rt_load_params_itrl(int argc, char **argv) { #ifdef PAIRED - if (argc != 8) { - fprintf(stderr, "Usage: %s ", argv[0]); - fprintf(stderr, " string for logging. Name of this task.\n"); - fprintf(stderr, " integer number of iterations. -1 for infinite.\n"); - fprintf(stderr, " UNUSED. Core is now auto-detected.\n"); - fprintf(stderr, " integer for logging. Core of paired task.\n"); - fprintf(stderr, " string for logging. Name of paired task.\n"); - fprintf(stderr, " string to append with .txt to yield output file name.\n"); - fprintf(stderr, " 1 to indicate this is pair member 1, otherwise pair member 2.\n"); - exit(1); - } + if (argc != (8 + LITMUS*2) && argc != (9 + LITMUS*2)) { + fprintf(stderr, "Usage: %s ", argv[0]); #else - if (argc != 6) { + if (argc != (6 + LITMUS*2)) { 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, " UNUSED. Core is now auto-detected.\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"); +#endif /* LITMUS */ exit(1); } -#endif _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_lock_id = atoi(argv[7]); - // The paired version doesn't support disabling output (legacy compatibility) - _rt_will_output = 1; + _rt_will_output = atoi(argv[7]); + char *pairId; + int end; + if (argc > 8) { + pairId = argv[8]; + end = 8; + } else { + pairId = "none"; + end = 9; + } #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"); @@ -132,32 +143,54 @@ static void _rt_load_params_itrl(int argc, char **argv) { 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)); if (!_rt_end_time || !_rt_start_time) { perror("Unable to allocate buffers for execution times"); exit(1); } - _rt_first_sem = sem_open("/_libextra_first_sem", O_CREAT, 644, 0); - _rt_second_sem = sem_open("/_libextra_second_sem", O_CREAT, 644, 0); + // 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); } - int barrier_file = shm_open("/_libextra_barrier", O_CREAT | O_RDWR, 644); + // 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, 1) == -1) { + if (ftruncate(barrier_file, 2) == -1) { perror("Error while setting size of shared memory for barrier synchronization"); exit(1); } - _rt_barrier = mmap(NULL, 1, PROT_WRITE, MAP_SHARED, barrier_file, 0); + _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_exec_time = calloc(_rt_max_jobs * _rt_will_output, sizeof(float)); @@ -168,8 +201,46 @@ static void _rt_load_params_itrl(int argc, char **argv) { #endif /* PAIRED */ _rt_jobs_complete = 0; mlockall(MCL_CURRENT || MCL_FUTURE); +#if LITMUS + _rt_period = strtoul(argv[end], NULL, 10); + unsigned int crit = atoi(argv[end+1]); + 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); + rt_param.exec_cost = 0; // We disable budget enforcement, so this doesn't matter + rt_param.period = ms2ns(_rt_period); + rt_param.relative_deadline = 0; + rt_param.phase = 0; + rt_param.priority = LITMUS_LOWEST_PRIORITY; + rt_param.cls = crit; + rt_param.release_policy = TASK_PERIODIC; + rt_param.budget_policy = NO_ENFORCEMENT; + rt_param.cpu = _rt_core; + 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); + } + 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 LOAD_PARAMS_ITRL _rt_load_params_itrl(argc, argv); #define SETUP_MMDC \ _rt_mmdc_read = calloc(_rt_max_jobs * _rt_will_output, sizeof(float));\ @@ -193,46 +264,6 @@ static void _rt_load_params_itrl(int argc, char **argv) { mmdc->madpcr1 = axi_arm1;\ msync(&(mmdc->madpcr1),4,MS_SYNC); -#define SETUP_LITMUS \ - unsigned int wait = 0; \ - 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); \ - rt_param.exec_cost = ms2ns(999); \ - rt_param.period = ms2ns(1000); \ - rt_param.deadline = 0; \ - rt_param.phase = 0; \ - rt_param.priority = LITMUS_LOWEST_PRIORITY; \ - rt_param.cls = RT_CLASS_HARD; \ - rt_param.release_policy = TASK_PERIODIC; \ - rt_param.budget_policy = NO_ENFORCEMENT; \ - rt_param.cpu = _rt_core; \ - 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); \ - } \ - if (wait && wait_for_ts_release() != 0) { \ - perror("Unable to wait for taskset release"); \ - exit(1); \ - } - -#define CLEANUP_LITMUS \ - if (task_mode(BACKGROUND_TASK) != 0) { \ - perror("Unable to become a real-time task"); \ - exit(1); \ - } \ - #if __arm__ // On ARM, manually flush the cache #define FLUSH_CACHES \ @@ -356,13 +387,16 @@ static void _rt_write_to_file() { fclose(fp); out: #if LITMUS - CLEANUP_LITMUS + if (task_mode(BACKGROUND_TASK) != 0) { + perror("Unable to become a real-time task"); + exit(1); + } #endif /* LITMUS */ #ifdef PAIRED - munmap(_rt_barrier, 1); - shm_unlink("/_libextra_barrier"); - sem_unlink("/_libextra_first_sem"); - sem_unlink("/_libextra_second_sem"); + 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 @@ -387,7 +421,9 @@ static void _rt_start_loop() { FIRST_UNLOCK FIRST_LOCK #endif /* PAIRED */ +#if !LITMUS FLUSH_CACHES +#endif #ifdef PAIRED BARRIER_SYNC #endif /* PAIRED */ @@ -457,6 +493,7 @@ static void _rt_stop_loop() { * able to read them. */ static int jobsComplete = 0; +#define SET_UP _rt_load_params_itrl(argc, argv); #define START_LOOP _rt_start_loop(); #define STOP_LOOP _rt_stop_loop(); #define WRITE_TO_FILE _rt_write_to_file(); -- cgit v1.2.2