From e616da1f87a23afe1f154dfddc0e2682d2c2835d Mon Sep 17 00:00:00 2001 From: Namhoon Kim Date: Tue, 5 Apr 2016 17:58:55 +0000 Subject: Colored SHM test program. bin/mttest.c --- Makefile | 20 +++- bin/base_mt_task.c | 24 ++++- bin/mc2spin.c | 119 +++++++++++++++--------- bin/mttest.c | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++++ bin/rtspin.c | 4 +- include/color_shm.h | 13 +++ include/litmus.h | 6 +- src/syscalls.c | 12 ++- 8 files changed, 399 insertions(+), 55 deletions(-) create mode 100644 bin/mttest.c create mode 100644 include/color_shm.h diff --git a/Makefile b/Makefile index 70e79d4..c1aecde 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ LITMUS_KERNEL ?= ../litmus-rt # Internal configuration. # compiler flags -flags-debug = -O2 -Wall -Werror -g -Wdeclaration-after-statement +flags-debug = -O0 -Wall -g -Wdeclaration-after-statement flags-api = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE # architecture-specific flags @@ -73,7 +73,7 @@ AR := ${CROSS_COMPILE}${AR} all = lib ${rt-apps} rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \ - base_mt_task uncache runtests resctrl mc2spin + base_mt_task uncache runtests resctrl mc2spin test1 mttest .PHONY: all lib clean dump-config TAGS tags cscope help doc @@ -238,8 +238,22 @@ lib-measure_syscall = -lm obj-resctrl = resctrl.o obj-mc2spin = mc2spin.o common.o -lib-mc2spin = -lrt +lib-mc2spin = -lrt -static +obj-mc2pollute = mc2pollute.o common.o +lib-mc2pollute = -lrt -static + +obj-mc2syn = mc2syn.o common.o +lib-mc2syn = -lrt -static + +obj-memthrash = memthrash.o +lib-memthrash = -lrt + +obj-test1 = test1.o common.o +lib-test1 = -lrt -static + +obj-mttest = mttest.o +ldf-mttest = -pthread # ############################################################################## # Build everything that depends on liblitmus. diff --git a/bin/base_mt_task.c b/bin/base_mt_task.c index aec79a4..1665203 100644 --- a/bin/base_mt_task.c +++ b/bin/base_mt_task.c @@ -29,11 +29,13 @@ /* Let's create 10 threads in the example, * for a total utilization of 1. */ -#define NUM_THREADS 10 +#define NUM_THREADS 3 /* The information passed to each thread. Could be anything. */ struct thread_context { int id; + int cpu; + int job_no; }; /* The real-time thread program. Doesn't have to be the same for @@ -45,7 +47,7 @@ void* rt_thread(void *tcontext); * Returns 1 -> task should exit. * 0 -> task should continue. */ -int job(void); +int job(struct thread_context *tcx); /* Catch errors. @@ -97,6 +99,8 @@ int main(int argc, char** argv) */ for (i = 0; i < NUM_THREADS; i++) { ctx[i].id = i; + ctx[i].cpu = 0; + ctx[i].job_no = 0; pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i)); } @@ -125,6 +129,7 @@ void* rt_thread(void *tcontext) int do_exit; struct thread_context *ctx = (struct thread_context *) tcontext; struct rt_task param; + int ret; /* Set up task parameters */ init_rt_task_param(¶m); @@ -157,6 +162,12 @@ void* rt_thread(void *tcontext) * where CPU ranges from 0 to "Number of CPUs" - 1 before calling * set_rt_task_param(). */ + param.cpu = ctx->cpu; + ret = be_migrate_to_cpu(ctx->cpu); + if (ret < 0) { + printf("RT Thread %d fails to migrate to CPU%d\n", ctx->id, ctx->cpu); + return NULL; + } CALL( set_rt_task_param(gettid(), ¶m) ); /***** @@ -176,7 +187,7 @@ void* rt_thread(void *tcontext) /* Wait until the next job is released. */ sleep_next_period(); /* Invoke job. */ - do_exit = job(); + do_exit = job(ctx); } while (!do_exit); @@ -192,10 +203,13 @@ void* rt_thread(void *tcontext) -int job(void) +int job(struct thread_context *tcx) { /* Do real-time calculation. */ - + printf("Job executinig\n"); + tcx->job_no++; + if (tcx->job_no == 5) + return 1; /* Don't exit. */ return 0; } diff --git a/bin/mc2spin.c b/bin/mc2spin.c index 1ef3082..25b1c58 100644 --- a/bin/mc2spin.c +++ b/bin/mc2spin.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -12,7 +13,11 @@ #include "litmus.h" #include "common.h" +#define PAGE_SIZE 4096 +#define NUM_ITEMS 8192 +int *pages; +unsigned long *access_order; static void usage(char *error) { fprintf(stderr, "Error: %s\n", error); @@ -104,12 +109,42 @@ static void get_exec_times(const char *file, const int column, static int num[NUMS]; static char* progname; +static int randrange(const int max) +{ + return (rand() / (RAND_MAX / max + 1)); +} + +static void sattolo(unsigned long *items, const unsigned long len) +{ + unsigned long i; + /* first set up 0, 1, ..., n - 1 */ + for (i = 0; i < len; i++) + items[i] = i; + /* note: i is now n */ + while (1 < i--) { + /* 0 <= j < i */ + int t, j = randrange(i); + t = items[i]; + items[i] = items[j]; + items[j] = t; + } +} + static int loop_once(void) { int i, j = 0; for (i = 0; i < NUMS; i++) j += num[i]++; return j; +/* + int i, tmp; + for (i = 0; i < NUM_ITEMS; i++) { + tmp = pages[access_order[i]]; + if (access_order[i] % 3 == 0) + pages[access_order[i]] = i+tmp; + } + return 1; +*/ } static int loop_for(double exec_time, double emergency_exit) @@ -138,11 +173,11 @@ static int loop_for(double exec_time, double emergency_exit) } -static void debug_delay_loop(void) +static void debug_delay_loop(int count) { double start, end, delay; - while (1) { + while (count--) { for (delay = 0.5; delay > 0.01; delay -= 0.01) { start = wctime(); loop_for(delay, 0); @@ -249,7 +284,7 @@ int main(int argc, char** argv) lt_t hyperperiod; lt_t budget; double wcet_ms, period_ms, hyperperiod_ms, budget_ms; - unsigned int priority = LITMUS_LOWEST_PRIORITY; + unsigned int priority = LITMUS_NO_PRIORITY; int migrate = 0; int cluster = 0; int opt; @@ -266,7 +301,7 @@ int main(int argc, char** argv) struct rt_task param; struct mc2_task mc2_param; struct reservation_config config; - int res_type = SPORADIC_POLLING; + int res_type = PERIODIC_POLLING; int n_str, num_int = 0; int verbose = 0; @@ -284,7 +319,7 @@ int main(int argc, char** argv) /* default for reservation */ config.id = 0; config.priority = LITMUS_NO_PRIORITY; /* use EDF by default */ - config.cpu = 0; + config.cpu = -1; mc2_param.crit = CRIT_LEVEL_C; @@ -346,14 +381,10 @@ int main(int argc, char** argv) break; case 'm': mc2_param.crit = atoi(optarg); - if (mc2_param.crit == CRIT_LEVEL_A) { - res_type = TABLE_DRIVEN; - } - else if (mc2_param.crit == CRIT_LEVEL_B) { - res_type = PERIODIC_POLLING; - } - else + if (mc2_param.crit < CRIT_LEVEL_A || mc2_param.crit == NUM_CRIT_LEVELS) { usage("Invalid criticality level."); + } + res_type = PERIODIC_POLLING; break; case 'h': hyperperiod_ms = atof(optarg); @@ -362,14 +393,7 @@ int main(int argc, char** argv) budget_ms = atof(optarg); break; case 'i': - n_str = strlen(optarg); - while(n_str--) { - if (optarg[n_str] == ',') - num_int++; - } - if (!num_int) - usage("Bad argument."); - config.table_driven_params.intervals = parse_td_intervals(num_int, optarg, &config.table_driven_params.num_intervals); + config.priority = atoi(optarg); break; case ':': usage("Argument missing."); @@ -382,10 +406,13 @@ int main(int argc, char** argv) } if (test_loop) { - debug_delay_loop(); + debug_delay_loop(1); return 0; } + if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY) + usage("Bad criticailty level or priority"); + srand(getpid()); if (file) { @@ -440,20 +467,15 @@ int main(int argc, char** argv) config.id = gettid(); if (hyperperiod%period != 0 ) { - bail_out("hyperperiod must be multiple of period"); + ;//bail_out("hyperperiod must be multiple of period"); } - if (mc2_param.crit == CRIT_LEVEL_A) { - config.table_driven_params.major_cycle_length = period; - } - else if (mc2_param.crit == CRIT_LEVEL_B) { - 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."); - } + 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 a reservation */ @@ -474,23 +496,33 @@ int main(int argc, char** argv) param.cpu = gettid(); } ret = set_rt_task_param(gettid(), ¶m); +//printf("SET_RT_TASK\n"); if (ret < 0) bail_out("could not setup rt task params"); - mc2_param.pid = gettid(); - mc2_param.hyperperiod = hyperperiod; + mc2_param.res_id = gettid(); ret = set_mc2_task_param(gettid(), &mc2_param); +//printf("SET_MC2_TASK\n"); if (ret < 0) bail_out("could not setup mc2 task params"); + + pages = (int*)malloc(sizeof(int)*NUM_ITEMS); + access_order = (unsigned long*)malloc(sizeof(unsigned long)*NUM_ITEMS); + sattolo(access_order, NUM_ITEMS); + init_litmus(); +printf("CALL\n"); + set_page_color(config.cpu); +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 (protocol >= 0) { - /* open reference to semaphore */ lock_od = litmus_open_lock(protocol, resource_id, lock_namespace, &cluster); if (lock_od < 0) { perror("litmus_open_lock"); @@ -500,6 +532,7 @@ int main(int argc, char** argv) if (wait) { +//printf("BEFORE WAIT\n"); ret = wait_for_ts_release(); if (ret != 0) bail_out("wait_for_ts_release()"); @@ -507,9 +540,7 @@ int main(int argc, char** argv) } if (file) { - /* use times read from the CSV file */ for (cur_job = 0; cur_job < num_jobs; ++cur_job) { - /* convert job's length to seconds */ job(exec_times[cur_job] * 0.001 * scale, start + duration, lock_od, cs_length * 0.001); @@ -521,11 +552,10 @@ int main(int argc, char** argv) printf("rtspin/%d:%u @ %.4fms\n", gettid(), job_no, (wctime() - start) * 1000); } - /* convert to seconds and scale */ } while (job(wcet_ms * 0.001 * scale, start + duration, lock_od, cs_length * 0.001)); } - +printf("BEFORE BACK_TASK\n"); ret = task_mode(BACKGROUND_TASK); if (ret != 0) bail_out("could not become regular task (huh?)"); @@ -534,8 +564,11 @@ int main(int argc, char** argv) free(exec_times); reservation_destroy(gettid(), config.cpu); - if (mc2_param.crit == CRIT_LEVEL_A) { - free(config.table_driven_params.intervals); - } + +printf("CALL\n"); + set_page_color(config.cpu); +printf("CALL\n"); + free(pages); + free(access_order); return 0; } diff --git a/bin/mttest.c b/bin/mttest.c new file mode 100644 index 0000000..e2813e6 --- /dev/null +++ b/bin/mttest.c @@ -0,0 +1,256 @@ +/* based_mt_task.c -- A basic multi-threaded real-time task skeleton. + * + * This (by itself useless) task demos how to setup a multi-threaded LITMUS^RT + * real-time task. Familiarity with the single threaded example (base_task.c) + * is assumed. + * + * Currently, liblitmus still lacks automated support for real-time + * tasks, but internaly it is thread-safe, and thus can be used together + * with pthreads. + */ + +#include +#include +#include +#include +#include +#include +#include +/* Include gettid() */ +#include + +/* Include threading support. */ +#include + +/* Include the LITMUS^RT API.*/ +#include "litmus.h" +#include "color_shm.h" + +#define PERIOD 100 +#define RELATIVE_DEADLINE 100 +#define EXEC_COST 10 + +/* Let's create 10 threads in the example, + * for a total utilization of 1. + */ +#define NUM_THREADS 2 + +/* The information passed to each thread. Could be anything. */ +struct thread_context { + int id; + int cpu; + int job_no; + char* shm; +}; + +/* The real-time thread program. Doesn't have to be the same for + * all threads. Here, we only have one that will invoke job(). + */ +void* rt_thread(void *tcontext); + +/* Declare the periodically invoked job. + * Returns 1 -> task should exit. + * 0 -> task should continue. + */ +int job(struct thread_context *tcx); + + +/* Catch errors. + */ +#define CALL( exp ) do { \ + int ret; \ + ret = exp; \ + if (ret != 0) \ + fprintf(stderr, "%s failed: %m\n", #exp);\ + else \ + fprintf(stderr, "%s ok.\n", #exp); \ + } while (0) + + +/* Basic setup is the same as in the single-threaded example. However, + * we do some thread initiliazation first before invoking the job. + */ +int main(int argc, char** argv) +{ + int i, ret, fd; + struct thread_context ctx[NUM_THREADS]; + pthread_t task[NUM_THREADS]; + char *shm; + struct ioctl_cmd shm_info; + /* The task is in background mode upon startup. */ + + + /***** + * 1) Command line paramter parsing would be done here. + */ + + + + /***** + * 2) Work environment (e.g., global data structures, file data, etc.) would + * be setup here. + */ + fd = open("/dev/litmus/color_shm", O_RDWR); + if (fd < 0) { + printf("Device open error.\n"); + return -1; + } + + shm_info.color = 0x0000cccc; + shm_info.bank = 0x000000ac; + + ret = ioctl(fd, SET_COLOR_SHM_CMD, &shm_info); + + shm = mmap(NULL, 6000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (shm == MAP_FAILED) { + printf("mmap failed.\n"); + return -1; + } + + mlockall(MCL_CURRENT | MCL_FUTURE); + /***** + * 3) Initialize LITMUS^RT. + * Task parameters will be specified per thread. + */ + init_litmus(); + + + /***** + * 4) Launch threads. + */ + for (i = 0; i < NUM_THREADS; i++) { + ctx[i].id = i; + ctx[i].cpu = 0; + ctx[i].job_no = 0; + ctx[i].shm = shm; + pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i)); + } + + + /***** + * 5) Wait for RT threads to terminate. + */ + for (i = 0; i < NUM_THREADS; i++) + pthread_join(task[i], NULL); + + + /***** + * 6) Clean up, maybe print results and stats, and exit. + */ + return 0; +} + + + +/* A real-time thread is very similar to the main function of a single-threaded + * real-time app. Notice, that init_rt_thread() is called to initialized per-thread + * data structures of the LITMUS^RT user space libary. + */ +void* rt_thread(void *tcontext) +{ + int do_exit; + struct thread_context *ctx = (struct thread_context *) tcontext; + struct rt_task param; + int ret; + + /* Set up task parameters */ + init_rt_task_param(¶m); + param.exec_cost = ms2ns(EXEC_COST); + param.period = ms2ns(PERIOD); + param.relative_deadline = ms2ns(RELATIVE_DEADLINE*(ctx->id+1)); + + /* What to do in the case of budget overruns? */ + param.budget_policy = NO_ENFORCEMENT; + + /* The task class parameter is ignored by most plugins. */ + param.cls = RT_CLASS_SOFT; + + /* The priority parameter is only used by fixed-priority plugins. */ + param.priority = LITMUS_LOWEST_PRIORITY; + + /* Make presence visible. */ + printf("RT Thread %d active.\n", ctx->id); + + /***** + * 1) Initialize real-time settings. + */ + CALL( init_rt_thread() ); + + /* To specify a partition, do + * + * param.cpu = CPU; + * be_migrate_to(CPU); + * + * where CPU ranges from 0 to "Number of CPUs" - 1 before calling + * set_rt_task_param(). + */ + param.cpu = ctx->cpu; + ret = be_migrate_to_cpu(ctx->cpu); + if (ret < 0) { + printf("RT Thread %d fails to migrate to CPU%d\n", ctx->id, ctx->cpu); + return NULL; + } + CALL( set_rt_task_param(gettid(), ¶m) ); + + /***** + * 2) Transition to real-time mode. + */ + CALL( task_mode(LITMUS_RT_TASK) ); + + /* The task is now executing as a real-time task if the call didn't fail. + */ + + + + /***** + * 3) Invoke real-time jobs. + */ + do { + /* Wait until the next job is released. */ + sleep_next_period(); + /* Invoke job. */ + do_exit = job(ctx); + } while (!do_exit); + + + + /***** + * 4) Transition to background mode. + */ + CALL( task_mode(BACKGROUND_TASK) ); + + + return NULL; +} + + + +int job(struct thread_context *tcx) +{ + int i; + char* buf = tcx->shm; + /* Do real-time calculation. */ + printf("Task %d Job %d executinig\n", tcx->id, tcx->job_no); + + if (tcx->id == 0) { + printf("WRITE\n"); + for (i=0; i<6000; i++) { + buf[i] = rand()%255; + printf("%x ",buf[i]); + } + printf("\n"); + } else if (tcx->id == 1) { + printf("READ\n"); + for (i=0; i<6000; i++) { + char t = buf[i]; + printf("%x ", t); + } + printf("\n"); + } + //test_call(0); + tcx->job_no++; + if (tcx->job_no == 1) + return 1; + /* Don't exit. */ + return 0; +} diff --git a/bin/rtspin.c b/bin/rtspin.c index ea7f192..fd57c45 100644 --- a/bin/rtspin.c +++ b/bin/rtspin.c @@ -6,7 +6,7 @@ #include #include #include - +#include #include "litmus.h" #include "common.h" @@ -191,7 +191,7 @@ int main(int argc, char** argv) lt_t wcet; lt_t period; double wcet_ms, period_ms; - unsigned int priority = LITMUS_LOWEST_PRIORITY; + unsigned int priority = LITMUS_NO_PRIORITY; int migrate = 0; int cluster = 0; int reservation = -1; diff --git a/include/color_shm.h b/include/color_shm.h new file mode 100644 index 0000000..a95ffde --- /dev/null +++ b/include/color_shm.h @@ -0,0 +1,13 @@ +#include +#include + +#define SHM_MAJOR 240 + +struct ioctl_cmd { + unsigned int color; + unsigned int bank; +}; + +#define SET_COLOR_SHM_CMD \ + _IOW(SHM_MAJOR, 0x1, struct ioctl_cmd) + diff --git a/include/litmus.h b/include/litmus.h index b90a83d..e96a4a6 100644 --- a/include/litmus.h +++ b/include/litmus.h @@ -46,7 +46,7 @@ extern "C" { * @private * Number of semaphore protocol object types */ -#define SCHED_LITMUS 6 +#define SCHED_LITMUS 7 /** * Initialise a real-time task param struct @@ -424,6 +424,10 @@ int reservation_destroy(unsigned int reservation_id, int cpu); int set_mc2_task_param(pid_t pid, struct mc2_task* param); +int set_page_color(int cpu); + +int test_call(unsigned int param); + #ifdef __cplusplus } #endif diff --git a/src/syscalls.c b/src/syscalls.c index b07d135..ab064ad 100644 --- a/src/syscalls.c +++ b/src/syscalls.c @@ -100,4 +100,14 @@ int reservation_destroy(unsigned int reservation_id, int cpu) int set_mc2_task_param(pid_t pid, struct mc2_task *param) { return syscall(__NR_set_mc2_task_param, pid, param); -} \ No newline at end of file +} + +int set_page_color(int cpu) +{ + return syscall(__NR_set_page_color, cpu); +} + +int test_call(unsigned int param) +{ + return syscall(__NR_test_call, param); +} -- cgit v1.2.2