From e1e24f60f63ca339f91051e70d371e565547df96 Mon Sep 17 00:00:00 2001 From: Namhoon Kim Date: Tue, 3 May 2016 19:01:14 +0000 Subject: Add PGM^RT support --- Makefile | 12 ++- bin/mttest.c | 33 ++++++-- include/cache_common.h | 213 +++++++++++++++++++++++++++++++++++++++++++++++++ include/color_shm.h | 12 ++- include/litmus.h | 12 +++ src/color_shm.c | 42 ++++++++++ src/syscalls.c | 11 +++ 7 files changed, 327 insertions(+), 8 deletions(-) create mode 100644 include/cache_common.h create mode 100644 src/color_shm.c diff --git a/Makefile b/Makefile index 5ceaedf..b135529 100644 --- a/Makefile +++ b/Makefile @@ -73,7 +73,8 @@ 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 test1 mttest + base_mt_task uncache runtests resctrl mc2spin test1 mttest \ + mc2thrash mc2shm mc2bench .PHONY: all lib clean dump-config TAGS tags cscope help doc @@ -254,6 +255,15 @@ lib-test1 = -lrt -static obj-mttest = mttest.o ldf-mttest = -pthread + +obj-mc2thrash = mc2thrash.o common.o +lib-mc2thrash = -lrt -static + +obj-mc2shm = mc2shm.o common.o +lib-mc2shm = -lrt -static + +obj-mc2bench = mc2bench.o common.o +lib-mc2bench = -lrt -static # ############################################################################## # Build everything that depends on liblitmus. diff --git a/bin/mttest.c b/bin/mttest.c index 7d573cc..d502778 100644 --- a/bin/mttest.c +++ b/bin/mttest.c @@ -101,7 +101,11 @@ int main(int argc, char** argv) shm_info.bank = 0x000000ac; ret = ioctl(fd, SET_COLOR_SHM_CMD, &shm_info); - + if (ret < 0) { + printf("ioctl failed.\n"); + return -1; + } + shm = mmap(NULL, 6000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (shm == MAP_FAILED) { printf("mmap failed.\n"); @@ -154,6 +158,8 @@ void* rt_thread(void *tcontext) struct thread_context *ctx = (struct thread_context *) tcontext; struct rt_task param; int ret; + struct mc2_task mc2_param; + struct reservation_config res_config; /* Set up task parameters */ init_rt_task_param(¶m); @@ -173,11 +179,27 @@ void* rt_thread(void *tcontext) /* Make presence visible. */ printf("RT Thread %d active.\n", ctx->id); + /* reservation config */ + res_config.id = gettid(); + res_config.polling_params.budget = ms2ns(EXEC_COST+1); + res_config.polling_params.period = param.period; + res_config.polling_params.offset = 0; + res_config.polling_params.relative_deadline = 0; + res_config.priority = LITMUS_MAX_PRIORITY; + res_config.cpu = ctx->cpu; + mc2_param.crit = CRIT_LEVEL_A; + mc2_param.res_id = gettid(); /***** * 1) Initialize real-time settings. */ CALL( init_rt_thread() ); + ret = reservation_create(PERIODIC_POLLING, &res_config); + if (ret < 0) { + printf("reservation failed.\n"); + return NULL; + } + /* To specify a partition, do * * param.cpu = CPU; @@ -194,6 +216,7 @@ void* rt_thread(void *tcontext) } CALL( set_rt_task_param(gettid(), ¶m) ); + CALL( set_mc2_task_param(gettid(), &mc2_param) ); /***** * 2) Transition to real-time mode. */ @@ -220,7 +243,7 @@ void* rt_thread(void *tcontext) * 4) Transition to background mode. */ CALL( task_mode(BACKGROUND_TASK) ); - + reservation_destroy(gettid(), res_config.cpu); return NULL; } @@ -236,14 +259,14 @@ int job(struct thread_context *tcx) if (tcx->id == 0) { printf("WRITE\n"); - for (i=0; i<6000; i++) { + for (i=0; i<600; 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++) { + for (i=0; i<600; i++) { char t = buf[i]; printf("%x ", t); } @@ -251,7 +274,7 @@ int job(struct thread_context *tcx) } //test_call(0); tcx->job_no++; - if (tcx->job_no == 1) + if (tcx->job_no == 10) return 1; /* Don't exit. */ return 0; diff --git a/include/cache_common.h b/include/cache_common.h new file mode 100644 index 0000000..2957dd3 --- /dev/null +++ b/include/cache_common.h @@ -0,0 +1,213 @@ +#ifndef __CACHE_COMMON_H__ +#define __CACHE_COMMON_H__ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "litmus.h" +#include "asm/cycles.h" + +#if defined(__i386__) || defined(__x86_64__) +#include "asm/irq.h" +#endif + + +#define UNCACHE_DEV "/dev/litmus/uncache" + +static void die(char *error) +{ + fprintf(stderr, "Error: %s (errno: %m)\n", + error); + exit(1); +} + +static int migrate_to(int cpu) +{ + int ret; + + static __thread cpu_set_t* cpu_set = NULL; + static __thread size_t cpu_set_sz; + static __thread int num_cpus; + if(!cpu_set) + { + num_cpus = sysconf(_SC_NPROCESSORS_ONLN); + cpu_set = CPU_ALLOC(num_cpus); + cpu_set_sz = CPU_ALLOC_SIZE(num_cpus); + } + + CPU_ZERO_S(cpu_set_sz, cpu_set); + CPU_SET_S(cpu, cpu_set_sz, cpu_set); + ret = sched_setaffinity(0 /* self */, cpu_set_sz, cpu_set); + return ret; +} + +static int check_migrations(int num_cpus) +{ + int cpu, err; + + for (cpu = 0; cpu < num_cpus; cpu++) { + err = migrate_to(cpu); + if (err != 0) { + fprintf(stderr, "Migration to CPU %d failed: %m.\n", + cpu + 1); + return 1; + } + } + return 0; +} + +static int become_posix_realtime_task(int prio) +{ + struct sched_param param; + memset(¶m, 0, sizeof(param)); + param.sched_priority = prio; + return sched_setscheduler(0 /* self */, SCHED_FIFO, ¶m); +} + +static int renice(int nice_val) +{ + return setpriority(PRIO_PROCESS, 0 /* self */, nice_val); +} + +static int lock_memory(void) +{ + return mlockall(MCL_CURRENT | MCL_FUTURE); +} + +/* define CACHELINE_SIZE if not provided by compiler args */ +#ifndef CACHELINE_SIZE +#if defined(__i386__) || defined(__x86_64__) +/* recent intel cpus */ +#define CACHELINE_SIZE 64 +#elif defined(__arm__) +/* at least with Cortex-A9 cpus ("8 words") */ +#define CACHELINE_SIZE 32 +#else +#error "Could not determine cacheline size!" +#endif +#endif + +//#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int)) +//typedef struct cacheline +//{ +// int line[INTS_IN_CACHELINE]; +//} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t; + +static cacheline_t* alloc_arena(size_t size, int use_huge_pages, int use_uncache_pages) +{ + int flags = MAP_PRIVATE | MAP_POPULATE; + cacheline_t* arena = NULL; + int fd; + + if(use_huge_pages) + flags |= MAP_HUGETLB; + + if(use_uncache_pages) { + fd = open(UNCACHE_DEV, O_RDWR); + if (fd == -1) + die("Failed to open uncache device. Are you running the LITMUS^RT kernel?"); + } + else { + fd = -1; + flags |= MAP_ANONYMOUS; + } + + arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0); + + if(use_uncache_pages) + close(fd); + + assert(arena); + + return arena; +} + +static void dealloc_arena(cacheline_t* arena, size_t size) +{ + int ret = munmap((void*)arena, size); + if(ret != 0) + die("munmap() error"); +} + +static int randrange(int min, int max) +{ + /* generate a random number on the range [min, max) w/o skew */ + int limit = max - min; + int devisor = RAND_MAX/limit; + int retval; + + do { + retval = rand() / devisor; + } while(retval == limit); + retval += min; + + return retval; +} + +static void init_arena(cacheline_t* arena, size_t size) +{ + int i; + size_t num_arena_elem = size / sizeof(cacheline_t); + + /* Generate a cycle among the cache lines using Sattolo's algorithm. + Every int in the cache line points to the same cache line. + Note: Sequential walk doesn't care about these values. */ + for (i = 0; i < num_arena_elem; i++) { + int j; + for(j = 0; j < INTS_IN_CACHELINE; ++j) + arena[i].line[j] = i; + } + while(1 < i--) { + int j = randrange(0, i); + cacheline_t temp = arena[j]; + arena[j] = arena[i]; + arena[i] = temp; + } +} + +static void sleep_us(int microseconds) +{ + struct timespec delay; + + delay.tv_sec = 0; + delay.tv_nsec = microseconds * 1000; + if (nanosleep(&delay, NULL) != 0) + die("sleep failed"); +} + +static int completed(int nSamples, int* history, int nCategories) +{ + int i; + for(i = 0; i < nCategories; ++i) + if(history[i] < nSamples) + return 0; + return 1; +} + +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; +} + + +#endif diff --git a/include/color_shm.h b/include/color_shm.h index f6ad8a5..ffa90dd 100644 --- a/include/color_shm.h +++ b/include/color_shm.h @@ -1,3 +1,4 @@ +#include #include #include @@ -8,6 +9,13 @@ struct color_ioctl_cmd { unsigned int bank; }; -#define SET_COLOR_SHM_CMD \ - _IOW(SHM_MAJOR, 0x1, struct color_ioctl_cmd) +struct color_ioctl_offset { + unsigned long offset; + int lock; +}; + +#define SET_COLOR_SHM_CMD _IOW(SHM_MAJOR, 0x1, struct color_ioctl_cmd) +#define SET_COLOR_SHM_OFFSET _IOW(SHM_MAJOR, 0x2, struct color_ioctl_offset) + +void* color_mmap(size_t size, struct color_ioctl_cmd cmd, struct color_ioctl_offset offset); diff --git a/include/litmus.h b/include/litmus.h index aaa8d1c..4a4ea39 100644 --- a/include/litmus.h +++ b/include/litmus.h @@ -48,6 +48,14 @@ extern "C" { */ #define SCHED_LITMUS 7 +#define CACHELINE_SIZE 32 +#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int)) +#define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t)) +typedef struct cacheline +{ + int line[INTS_IN_CACHELINE]; +} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t; + /** * Initialise a real-time task param struct * @param param Pointer to the struct to initialise @@ -440,6 +448,10 @@ int set_page_color(int cpu); int test_call(unsigned int param); +int run_bench(int type, int size, cacheline_t *src, cacheline_t *dst, lt_t __user *ts); + +int lock_buffer(void* vaddr, size_t size, unsigned int lock_way, unsigned int unlock_way); + #ifdef __cplusplus } #endif diff --git a/src/color_shm.c b/src/color_shm.c new file mode 100644 index 0000000..15332aa --- /dev/null +++ b/src/color_shm.c @@ -0,0 +1,42 @@ +#include +#include +#include + +#include "color_shm.h" + +void* color_mmap(size_t size, struct color_ioctl_cmd cmd, struct color_ioctl_offset offset) +{ + int ret, fd; + void *mem; + + fd = open("/dev/litmus/color_shm", O_RDWR); + if (fd < 0) { + printf("Device open error.\n"); + return NULL; + } + + ret = ioctl(fd, SET_COLOR_SHM_CMD, &cmd); + if (ret < 0) { + printf("ioctl failed.\n"); + return NULL; + } + + ret = ioctl(fd, SET_COLOR_SHM_OFFSET, &offset); + if (ret < 0) { + printf("ioctl failed.\n"); + return NULL; + } + + size += offset.offset; + mem = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (mem == MAP_FAILED) { + printf("mmap failed.\n"); + return MAP_FAILED; + } + close(fd); + + mem += offset.offset; + + return mem; +} + diff --git a/src/syscalls.c b/src/syscalls.c index ab064ad..a4cec67 100644 --- a/src/syscalls.c +++ b/src/syscalls.c @@ -111,3 +111,14 @@ int test_call(unsigned int param) { return syscall(__NR_test_call, param); } + +int run_bench(int type, int wss, cacheline_t *src, cacheline_t *dst, lt_t *ts) +{ + return syscall(__NR_run_test, type, wss, src, dst, ts); +} + +int lock_buffer(void* vaddr, size_t size, unsigned int lock_way, unsigned int unlock_way) +{ + return syscall(__NR_lock_buffer, vaddr, size, lock_way, unlock_way); +} + -- cgit v1.2.2