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.) --- SD-VBS/common/makefiles/Makefile.common | 4 +- all_pairs/Makefile | 6 +- baseline/Makefile | 6 +- dis/Makefile | 6 +- extra.h | 197 +++++++++++++++++++------------- 5 files changed, 128 insertions(+), 91 deletions(-) diff --git a/SD-VBS/common/makefiles/Makefile.common b/SD-VBS/common/makefiles/Makefile.common index 9c28cfc..964ece6 100644 --- a/SD-VBS/common/makefiles/Makefile.common +++ b/SD-VBS/common/makefiles/Makefile.common @@ -30,8 +30,8 @@ BMARK_DIR := $(TOP_DIR)/benchmarks/$(BMARK) TOOL_DIR := $(TOP_DIR)/tools LIBLITMUS ?= /home/litmus/liblitmus ifneq ($(shell grep "define LITMUS 1" ../../../../../extra.h),) - CFLAGS += -I${LIBLITMUS}/include - LDFLAGS += -L${LIBLITMUS} -llitmus + override CFLAGS += -I${LIBLITMUS}/include -I${LIBLITMUS}/arch/arm/include + override LDFLAGS += -L${LIBLITMUS} -llitmus endif #The options set below and specific to each benchmark. Disparity takes 2 input images, whereas Tracking can take any >1 input images =. diff --git a/all_pairs/Makefile b/all_pairs/Makefile index f0b284e..592db70 100644 --- a/all_pairs/Makefile +++ b/all_pairs/Makefile @@ -1,4 +1,4 @@ -LIBLITMUS ?= /media/speedy/litmus/liblitmus +LIBLITMUS ?= /playpen/mc2/liblitmus CC ?= gcc override CFLAGS += -pthread -O2 -I.. -DPAIRED LDFLAGS += -lrt @@ -11,8 +11,8 @@ endif # Include all the LITMUS^RT headers if we're using it ifneq ($(shell grep "define LITMUS 1" ../extra.h),) - CFLAGS += -I${LIBLITMUS}/include -I${LIBLITMUS}/arch/arm/include - LDFLAGS += -L${LIBLITMUS} -llitmus + override CFLAGS += -I${LIBLITMUS}/include -I${LIBLITMUS}/arch/arm/include + override LDFLAGS += -L${LIBLITMUS} -llitmus endif all: bin/cjpeg_wrbmp bin/huff_enc bin/gsm_enc bin/dijkstra bin/h264_dec bin/susan bin/adpcm_enc bin/rijndael_dec bin/huff_dec bin/rijndael_enc bin/gsm_dec bin/anagram bin/epic bin/ammunition bin/g723_enc bin/ndes bin/petrinet bin/statemate bin/cjpeg_transupp bin/mpeg2 bin/fmref bin/audiobeam bin/adpcm_dec diff --git a/baseline/Makefile b/baseline/Makefile index d6ab976..a929bc6 100644 --- a/baseline/Makefile +++ b/baseline/Makefile @@ -1,4 +1,4 @@ -LIBLITMUS ?= /media/speedy/litmus/liblitmus +LIBLITMUS ?= /playpen/mc2/liblitmus CC ?= gcc override CFLAGS = -pthread -O2 -I.. LDFLAGS = -lrt @@ -11,8 +11,8 @@ endif # Include all the LITMUS^RT headers if we're using it ifneq ($(shell grep "define LITMUS 1" ../extra.h),) - CFLAGS += -I${LIBLITMUS}/include -I${LIBLITMUS}/arch/arm/include - LDFLAGS += -L${LIBLITMUS} -llitmus + override CFLAGS += -I${LIBLITMUS}/include -I${LIBLITMUS}/arch/arm/include + override LDFLAGS += -L${LIBLITMUS} -llitmus endif all: bin/cjpeg_wrbmp bin/huff_enc bin/gsm_enc bin/dijkstra bin/h264_dec bin/susan bin/adpcm_enc bin/rijndael_dec bin/huff_dec bin/rijndael_enc bin/gsm_dec bin/anagram bin/epic bin/ammunition bin/g723_enc bin/ndes bin/petrinet bin/statemate bin/cjpeg_transupp bin/mpeg2 bin/fmref bin/audiobeam bin/adpcm_dec diff --git a/dis/Makefile b/dis/Makefile index 88fa7c2..d18761b 100755 --- a/dis/Makefile +++ b/dis/Makefile @@ -2,7 +2,7 @@ # Build the DIS benchmarks with all-pairs or unpaired instrumentation # (I know that this Makefile is mildly evil and breaks so many rules # that a good Makefile should follow. Sorry - at least I have one.) -LIBLITMUS ?= /media/speedy/litmus/liblitmus +LIBLITMUS ?= /playpen/mc2/liblitmus CC ?= gcc override CFLAGS += -pthread -O2 -I.. LDFLAGS = -lrt -lm @@ -15,8 +15,8 @@ endif # Include all the LITMUS^RT headers if we're using it ifneq ($(shell grep "define LITMUS 1" ../extra.h),) - CFLAGS += -I${LIBLITMUS}/include -I${LIBLITMUS}/arch/arm/include - LDFLAGS += -L${LIBLITMUS} -llitmus + override CFLAGS += -I${LIBLITMUS}/include -I${LIBLITMUS}/arch/arm/include + override LDFLAGS += -L${LIBLITMUS} -llitmus endif all: baseline 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