diff options
author | Namhoon Kim <namhoonk@cs.unc.edu> | 2016-05-03 15:01:14 -0400 |
---|---|---|
committer | Namhoon Kim <namhoonk@cs.unc.edu> | 2016-05-03 15:01:14 -0400 |
commit | e1e24f60f63ca339f91051e70d371e565547df96 (patch) | |
tree | 0c42c53a7196a0bfd53ab0a0dd32fa13a38883d6 | |
parent | cc61f79e3a7f5b28c8731d0e041dd57cdcd812ca (diff) |
Add PGM^RT support
-rw-r--r-- | Makefile | 12 | ||||
-rw-r--r-- | bin/mttest.c | 33 | ||||
-rw-r--r-- | include/cache_common.h | 213 | ||||
-rw-r--r-- | include/color_shm.h | 12 | ||||
-rw-r--r-- | include/litmus.h | 12 | ||||
-rw-r--r-- | src/color_shm.c | 42 | ||||
-rw-r--r-- | src/syscalls.c | 11 |
7 files changed, 327 insertions, 8 deletions
@@ -73,7 +73,8 @@ AR := ${CROSS_COMPILE}${AR} | |||
73 | 73 | ||
74 | all = lib ${rt-apps} | 74 | all = lib ${rt-apps} |
75 | rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \ | 75 | rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \ |
76 | base_mt_task uncache runtests resctrl mc2spin test1 mttest | 76 | base_mt_task uncache runtests resctrl mc2spin test1 mttest \ |
77 | mc2thrash mc2shm mc2bench | ||
77 | 78 | ||
78 | .PHONY: all lib clean dump-config TAGS tags cscope help doc | 79 | .PHONY: all lib clean dump-config TAGS tags cscope help doc |
79 | 80 | ||
@@ -254,6 +255,15 @@ lib-test1 = -lrt -static | |||
254 | 255 | ||
255 | obj-mttest = mttest.o | 256 | obj-mttest = mttest.o |
256 | ldf-mttest = -pthread | 257 | ldf-mttest = -pthread |
258 | |||
259 | obj-mc2thrash = mc2thrash.o common.o | ||
260 | lib-mc2thrash = -lrt -static | ||
261 | |||
262 | obj-mc2shm = mc2shm.o common.o | ||
263 | lib-mc2shm = -lrt -static | ||
264 | |||
265 | obj-mc2bench = mc2bench.o common.o | ||
266 | lib-mc2bench = -lrt -static | ||
257 | # ############################################################################## | 267 | # ############################################################################## |
258 | # Build everything that depends on liblitmus. | 268 | # Build everything that depends on liblitmus. |
259 | 269 | ||
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) | |||
101 | shm_info.bank = 0x000000ac; | 101 | shm_info.bank = 0x000000ac; |
102 | 102 | ||
103 | ret = ioctl(fd, SET_COLOR_SHM_CMD, &shm_info); | 103 | ret = ioctl(fd, SET_COLOR_SHM_CMD, &shm_info); |
104 | 104 | if (ret < 0) { | |
105 | printf("ioctl failed.\n"); | ||
106 | return -1; | ||
107 | } | ||
108 | |||
105 | shm = mmap(NULL, 6000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); | 109 | shm = mmap(NULL, 6000, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); |
106 | if (shm == MAP_FAILED) { | 110 | if (shm == MAP_FAILED) { |
107 | printf("mmap failed.\n"); | 111 | printf("mmap failed.\n"); |
@@ -154,6 +158,8 @@ void* rt_thread(void *tcontext) | |||
154 | struct thread_context *ctx = (struct thread_context *) tcontext; | 158 | struct thread_context *ctx = (struct thread_context *) tcontext; |
155 | struct rt_task param; | 159 | struct rt_task param; |
156 | int ret; | 160 | int ret; |
161 | struct mc2_task mc2_param; | ||
162 | struct reservation_config res_config; | ||
157 | 163 | ||
158 | /* Set up task parameters */ | 164 | /* Set up task parameters */ |
159 | init_rt_task_param(¶m); | 165 | init_rt_task_param(¶m); |
@@ -173,11 +179,27 @@ void* rt_thread(void *tcontext) | |||
173 | /* Make presence visible. */ | 179 | /* Make presence visible. */ |
174 | printf("RT Thread %d active.\n", ctx->id); | 180 | printf("RT Thread %d active.\n", ctx->id); |
175 | 181 | ||
182 | /* reservation config */ | ||
183 | res_config.id = gettid(); | ||
184 | res_config.polling_params.budget = ms2ns(EXEC_COST+1); | ||
185 | res_config.polling_params.period = param.period; | ||
186 | res_config.polling_params.offset = 0; | ||
187 | res_config.polling_params.relative_deadline = 0; | ||
188 | res_config.priority = LITMUS_MAX_PRIORITY; | ||
189 | res_config.cpu = ctx->cpu; | ||
190 | mc2_param.crit = CRIT_LEVEL_A; | ||
191 | mc2_param.res_id = gettid(); | ||
176 | /***** | 192 | /***** |
177 | * 1) Initialize real-time settings. | 193 | * 1) Initialize real-time settings. |
178 | */ | 194 | */ |
179 | CALL( init_rt_thread() ); | 195 | CALL( init_rt_thread() ); |
180 | 196 | ||
197 | ret = reservation_create(PERIODIC_POLLING, &res_config); | ||
198 | if (ret < 0) { | ||
199 | printf("reservation failed.\n"); | ||
200 | return NULL; | ||
201 | } | ||
202 | |||
181 | /* To specify a partition, do | 203 | /* To specify a partition, do |
182 | * | 204 | * |
183 | * param.cpu = CPU; | 205 | * param.cpu = CPU; |
@@ -194,6 +216,7 @@ void* rt_thread(void *tcontext) | |||
194 | } | 216 | } |
195 | CALL( set_rt_task_param(gettid(), ¶m) ); | 217 | CALL( set_rt_task_param(gettid(), ¶m) ); |
196 | 218 | ||
219 | CALL( set_mc2_task_param(gettid(), &mc2_param) ); | ||
197 | /***** | 220 | /***** |
198 | * 2) Transition to real-time mode. | 221 | * 2) Transition to real-time mode. |
199 | */ | 222 | */ |
@@ -220,7 +243,7 @@ void* rt_thread(void *tcontext) | |||
220 | * 4) Transition to background mode. | 243 | * 4) Transition to background mode. |
221 | */ | 244 | */ |
222 | CALL( task_mode(BACKGROUND_TASK) ); | 245 | CALL( task_mode(BACKGROUND_TASK) ); |
223 | 246 | reservation_destroy(gettid(), res_config.cpu); | |
224 | 247 | ||
225 | return NULL; | 248 | return NULL; |
226 | } | 249 | } |
@@ -236,14 +259,14 @@ int job(struct thread_context *tcx) | |||
236 | 259 | ||
237 | if (tcx->id == 0) { | 260 | if (tcx->id == 0) { |
238 | printf("WRITE\n"); | 261 | printf("WRITE\n"); |
239 | for (i=0; i<6000; i++) { | 262 | for (i=0; i<600; i++) { |
240 | buf[i] = rand()%255; | 263 | buf[i] = rand()%255; |
241 | printf("%x ",buf[i]); | 264 | printf("%x ",buf[i]); |
242 | } | 265 | } |
243 | printf("\n"); | 266 | printf("\n"); |
244 | } else if (tcx->id == 1) { | 267 | } else if (tcx->id == 1) { |
245 | printf("READ\n"); | 268 | printf("READ\n"); |
246 | for (i=0; i<6000; i++) { | 269 | for (i=0; i<600; i++) { |
247 | char t = buf[i]; | 270 | char t = buf[i]; |
248 | printf("%x ", t); | 271 | printf("%x ", t); |
249 | } | 272 | } |
@@ -251,7 +274,7 @@ int job(struct thread_context *tcx) | |||
251 | } | 274 | } |
252 | //test_call(0); | 275 | //test_call(0); |
253 | tcx->job_no++; | 276 | tcx->job_no++; |
254 | if (tcx->job_no == 1) | 277 | if (tcx->job_no == 10) |
255 | return 1; | 278 | return 1; |
256 | /* Don't exit. */ | 279 | /* Don't exit. */ |
257 | return 0; | 280 | 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 @@ | |||
1 | #ifndef __CACHE_COMMON_H__ | ||
2 | #define __CACHE_COMMON_H__ | ||
3 | |||
4 | #include <stdio.h> | ||
5 | #include <stdlib.h> | ||
6 | #include <time.h> | ||
7 | #include <string.h> | ||
8 | #include <assert.h> | ||
9 | |||
10 | #include <signal.h> | ||
11 | #include <sys/mman.h> | ||
12 | #include <sys/types.h> | ||
13 | #include <sys/stat.h> | ||
14 | #include <fcntl.h> | ||
15 | #include <unistd.h> | ||
16 | |||
17 | #include <sys/io.h> | ||
18 | #include <sys/utsname.h> | ||
19 | |||
20 | #include <sched.h> | ||
21 | #include <sys/time.h> | ||
22 | #include <sys/resource.h> | ||
23 | |||
24 | #include "litmus.h" | ||
25 | #include "asm/cycles.h" | ||
26 | |||
27 | #if defined(__i386__) || defined(__x86_64__) | ||
28 | #include "asm/irq.h" | ||
29 | #endif | ||
30 | |||
31 | |||
32 | #define UNCACHE_DEV "/dev/litmus/uncache" | ||
33 | |||
34 | static void die(char *error) | ||
35 | { | ||
36 | fprintf(stderr, "Error: %s (errno: %m)\n", | ||
37 | error); | ||
38 | exit(1); | ||
39 | } | ||
40 | |||
41 | static int migrate_to(int cpu) | ||
42 | { | ||
43 | int ret; | ||
44 | |||
45 | static __thread cpu_set_t* cpu_set = NULL; | ||
46 | static __thread size_t cpu_set_sz; | ||
47 | static __thread int num_cpus; | ||
48 | if(!cpu_set) | ||
49 | { | ||
50 | num_cpus = sysconf(_SC_NPROCESSORS_ONLN); | ||
51 | cpu_set = CPU_ALLOC(num_cpus); | ||
52 | cpu_set_sz = CPU_ALLOC_SIZE(num_cpus); | ||
53 | } | ||
54 | |||
55 | CPU_ZERO_S(cpu_set_sz, cpu_set); | ||
56 | CPU_SET_S(cpu, cpu_set_sz, cpu_set); | ||
57 | ret = sched_setaffinity(0 /* self */, cpu_set_sz, cpu_set); | ||
58 | return ret; | ||
59 | } | ||
60 | |||
61 | static int check_migrations(int num_cpus) | ||
62 | { | ||
63 | int cpu, err; | ||
64 | |||
65 | for (cpu = 0; cpu < num_cpus; cpu++) { | ||
66 | err = migrate_to(cpu); | ||
67 | if (err != 0) { | ||
68 | fprintf(stderr, "Migration to CPU %d failed: %m.\n", | ||
69 | cpu + 1); | ||
70 | return 1; | ||
71 | } | ||
72 | } | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static int become_posix_realtime_task(int prio) | ||
77 | { | ||
78 | struct sched_param param; | ||
79 | memset(¶m, 0, sizeof(param)); | ||
80 | param.sched_priority = prio; | ||
81 | return sched_setscheduler(0 /* self */, SCHED_FIFO, ¶m); | ||
82 | } | ||
83 | |||
84 | static int renice(int nice_val) | ||
85 | { | ||
86 | return setpriority(PRIO_PROCESS, 0 /* self */, nice_val); | ||
87 | } | ||
88 | |||
89 | static int lock_memory(void) | ||
90 | { | ||
91 | return mlockall(MCL_CURRENT | MCL_FUTURE); | ||
92 | } | ||
93 | |||
94 | /* define CACHELINE_SIZE if not provided by compiler args */ | ||
95 | #ifndef CACHELINE_SIZE | ||
96 | #if defined(__i386__) || defined(__x86_64__) | ||
97 | /* recent intel cpus */ | ||
98 | #define CACHELINE_SIZE 64 | ||
99 | #elif defined(__arm__) | ||
100 | /* at least with Cortex-A9 cpus ("8 words") */ | ||
101 | #define CACHELINE_SIZE 32 | ||
102 | #else | ||
103 | #error "Could not determine cacheline size!" | ||
104 | #endif | ||
105 | #endif | ||
106 | |||
107 | //#define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int)) | ||
108 | //typedef struct cacheline | ||
109 | //{ | ||
110 | // int line[INTS_IN_CACHELINE]; | ||
111 | //} __attribute__((aligned(CACHELINE_SIZE))) cacheline_t; | ||
112 | |||
113 | static cacheline_t* alloc_arena(size_t size, int use_huge_pages, int use_uncache_pages) | ||
114 | { | ||
115 | int flags = MAP_PRIVATE | MAP_POPULATE; | ||
116 | cacheline_t* arena = NULL; | ||
117 | int fd; | ||
118 | |||
119 | if(use_huge_pages) | ||
120 | flags |= MAP_HUGETLB; | ||
121 | |||
122 | if(use_uncache_pages) { | ||
123 | fd = open(UNCACHE_DEV, O_RDWR); | ||
124 | if (fd == -1) | ||
125 | die("Failed to open uncache device. Are you running the LITMUS^RT kernel?"); | ||
126 | } | ||
127 | else { | ||
128 | fd = -1; | ||
129 | flags |= MAP_ANONYMOUS; | ||
130 | } | ||
131 | |||
132 | arena = mmap(0, size, PROT_READ | PROT_WRITE, flags, fd, 0); | ||
133 | |||
134 | if(use_uncache_pages) | ||
135 | close(fd); | ||
136 | |||
137 | assert(arena); | ||
138 | |||
139 | return arena; | ||
140 | } | ||
141 | |||
142 | static void dealloc_arena(cacheline_t* arena, size_t size) | ||
143 | { | ||
144 | int ret = munmap((void*)arena, size); | ||
145 | if(ret != 0) | ||
146 | die("munmap() error"); | ||
147 | } | ||
148 | |||
149 | static int randrange(int min, int max) | ||
150 | { | ||
151 | /* generate a random number on the range [min, max) w/o skew */ | ||
152 | int limit = max - min; | ||
153 | int devisor = RAND_MAX/limit; | ||
154 | int retval; | ||
155 | |||
156 | do { | ||
157 | retval = rand() / devisor; | ||
158 | } while(retval == limit); | ||
159 | retval += min; | ||
160 | |||
161 | return retval; | ||
162 | } | ||
163 | |||
164 | static void init_arena(cacheline_t* arena, size_t size) | ||
165 | { | ||
166 | int i; | ||
167 | size_t num_arena_elem = size / sizeof(cacheline_t); | ||
168 | |||
169 | /* Generate a cycle among the cache lines using Sattolo's algorithm. | ||
170 | Every int in the cache line points to the same cache line. | ||
171 | Note: Sequential walk doesn't care about these values. */ | ||
172 | for (i = 0; i < num_arena_elem; i++) { | ||
173 | int j; | ||
174 | for(j = 0; j < INTS_IN_CACHELINE; ++j) | ||
175 | arena[i].line[j] = i; | ||
176 | } | ||
177 | while(1 < i--) { | ||
178 | int j = randrange(0, i); | ||
179 | cacheline_t temp = arena[j]; | ||
180 | arena[j] = arena[i]; | ||
181 | arena[i] = temp; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | static void sleep_us(int microseconds) | ||
186 | { | ||
187 | struct timespec delay; | ||
188 | |||
189 | delay.tv_sec = 0; | ||
190 | delay.tv_nsec = microseconds * 1000; | ||
191 | if (nanosleep(&delay, NULL) != 0) | ||
192 | die("sleep failed"); | ||
193 | } | ||
194 | |||
195 | static int completed(int nSamples, int* history, int nCategories) | ||
196 | { | ||
197 | int i; | ||
198 | for(i = 0; i < nCategories; ++i) | ||
199 | if(history[i] < nSamples) | ||
200 | return 0; | ||
201 | return 1; | ||
202 | } | ||
203 | |||
204 | inline unsigned long get_cyclecount (void) | ||
205 | { | ||
206 | unsigned long value; | ||
207 | // Read CCNT Register | ||
208 | asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value)); | ||
209 | return value; | ||
210 | } | ||
211 | |||
212 | |||
213 | #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 @@ | |||
1 | #include <sys/types.h> | ||
1 | #include <sys/ioctl.h> | 2 | #include <sys/ioctl.h> |
2 | #include <fcntl.h> | 3 | #include <fcntl.h> |
3 | 4 | ||
@@ -8,6 +9,13 @@ struct color_ioctl_cmd { | |||
8 | unsigned int bank; | 9 | unsigned int bank; |
9 | }; | 10 | }; |
10 | 11 | ||
11 | #define SET_COLOR_SHM_CMD \ | 12 | struct color_ioctl_offset { |
12 | _IOW(SHM_MAJOR, 0x1, struct color_ioctl_cmd) | 13 | unsigned long offset; |
14 | int lock; | ||
15 | }; | ||
16 | |||
17 | #define SET_COLOR_SHM_CMD _IOW(SHM_MAJOR, 0x1, struct color_ioctl_cmd) | ||
18 | #define SET_COLOR_SHM_OFFSET _IOW(SHM_MAJOR, 0x2, struct color_ioctl_offset) | ||
19 | |||
20 | void* color_mmap(size_t size, struct color_ioctl_cmd cmd, struct color_ioctl_offset offset); | ||
13 | 21 | ||
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" { | |||
48 | */ | 48 | */ |
49 | #define SCHED_LITMUS 7 | 49 | #define SCHED_LITMUS 7 |
50 | 50 | ||
51 | #define CACHELINE_SIZE 32 | ||
52 | #define INTS_IN_CACHELINE (CACHELINE_SIZE/sizeof(int)) | ||
53 | #define CACHELINES_IN_1KB (1024 / sizeof(cacheline_t)) | ||
54 | typedef struct cacheline | ||
55 | { | ||
56 | int line[INTS_IN_CACHELINE]; | ||
57 | } __attribute__((aligned(CACHELINE_SIZE))) cacheline_t; | ||
58 | |||
51 | /** | 59 | /** |
52 | * Initialise a real-time task param struct | 60 | * Initialise a real-time task param struct |
53 | * @param param Pointer to the struct to initialise | 61 | * @param param Pointer to the struct to initialise |
@@ -440,6 +448,10 @@ int set_page_color(int cpu); | |||
440 | 448 | ||
441 | int test_call(unsigned int param); | 449 | int test_call(unsigned int param); |
442 | 450 | ||
451 | int run_bench(int type, int size, cacheline_t *src, cacheline_t *dst, lt_t __user *ts); | ||
452 | |||
453 | int lock_buffer(void* vaddr, size_t size, unsigned int lock_way, unsigned int unlock_way); | ||
454 | |||
443 | #ifdef __cplusplus | 455 | #ifdef __cplusplus |
444 | } | 456 | } |
445 | #endif | 457 | #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 @@ | |||
1 | #include <sys/mman.h> | ||
2 | #include <stdio.h> | ||
3 | #include <unistd.h> | ||
4 | |||
5 | #include "color_shm.h" | ||
6 | |||
7 | void* color_mmap(size_t size, struct color_ioctl_cmd cmd, struct color_ioctl_offset offset) | ||
8 | { | ||
9 | int ret, fd; | ||
10 | void *mem; | ||
11 | |||
12 | fd = open("/dev/litmus/color_shm", O_RDWR); | ||
13 | if (fd < 0) { | ||
14 | printf("Device open error.\n"); | ||
15 | return NULL; | ||
16 | } | ||
17 | |||
18 | ret = ioctl(fd, SET_COLOR_SHM_CMD, &cmd); | ||
19 | if (ret < 0) { | ||
20 | printf("ioctl failed.\n"); | ||
21 | return NULL; | ||
22 | } | ||
23 | |||
24 | ret = ioctl(fd, SET_COLOR_SHM_OFFSET, &offset); | ||
25 | if (ret < 0) { | ||
26 | printf("ioctl failed.\n"); | ||
27 | return NULL; | ||
28 | } | ||
29 | |||
30 | size += offset.offset; | ||
31 | mem = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); | ||
32 | if (mem == MAP_FAILED) { | ||
33 | printf("mmap failed.\n"); | ||
34 | return MAP_FAILED; | ||
35 | } | ||
36 | close(fd); | ||
37 | |||
38 | mem += offset.offset; | ||
39 | |||
40 | return mem; | ||
41 | } | ||
42 | |||
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) | |||
111 | { | 111 | { |
112 | return syscall(__NR_test_call, param); | 112 | return syscall(__NR_test_call, param); |
113 | } | 113 | } |
114 | |||
115 | int run_bench(int type, int wss, cacheline_t *src, cacheline_t *dst, lt_t *ts) | ||
116 | { | ||
117 | return syscall(__NR_run_test, type, wss, src, dst, ts); | ||
118 | } | ||
119 | |||
120 | int lock_buffer(void* vaddr, size_t size, unsigned int lock_way, unsigned int unlock_way) | ||
121 | { | ||
122 | return syscall(__NR_lock_buffer, vaddr, size, lock_way, unlock_way); | ||
123 | } | ||
124 | |||