aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2013-03-08 01:25:35 -0500
committerBjoern Brandenburg <bbb@mpi-sws.org>2013-03-12 09:47:01 -0400
commit072b486393ab702eea9ea0a7fef569dbf8be0a32 (patch)
treedda3128725f9324908c4f3daae992208030faaff
parent7051511d6b059097f2eb5f650294e0ead7d8f488 (diff)
uncachedev: uncache test tool.
This adds the uncache test tool (bin/uncache.c). The tool can be used to test Litmus's char device driver for allocating uncacheable CPU memory. The tool runs various checks and gathers basic cache vs. main memory statistics. In the future, uncache could be extended to quantify the benefits of the L1, L2, and L3 caches, instead of treating them as a black box. Note: Uncache works best when compiled with '-O2'. While '-O2' has not been added to the Makefile, other code was updated (code in tests/ and rtspin), to compile with -O2. DEPENDS UPON LITMUS-RT PATCH 888d097deb6d1fdc0c89a4f9667fd81cf416cfc7.
-rw-r--r--Makefile5
-rw-r--r--bin/rtspin.c6
-rw-r--r--bin/uncache.c381
-rw-r--r--tests/fdso.c4
-rw-r--r--tests/locks.c8
-rw-r--r--tests/pcp.c8
6 files changed, 398 insertions, 14 deletions
diff --git a/Makefile b/Makefile
index 8195752..5432edd 100644
--- a/Makefile
+++ b/Makefile
@@ -71,7 +71,7 @@ AR := ${CROSS_COMPILE}${AR}
71 71
72all = lib ${rt-apps} 72all = lib ${rt-apps}
73rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \ 73rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \
74 base_mt_task runtests 74 base_mt_task uncache runtests
75 75
76.PHONY: all lib clean dump-config TAGS tags cscope help 76.PHONY: all lib clean dump-config TAGS tags cscope help
77 77
@@ -215,6 +215,9 @@ obj-rt_launch = rt_launch.o common.o
215obj-rtspin = rtspin.o common.o 215obj-rtspin = rtspin.o common.o
216lib-rtspin = -lrt 216lib-rtspin = -lrt
217 217
218obj-uncache = uncache.o
219lib-uncache = -lrt
220
218obj-release_ts = release_ts.o 221obj-release_ts = release_ts.o
219 222
220obj-measure_syscall = null_call.o 223obj-measure_syscall = null_call.o
diff --git a/bin/rtspin.c b/bin/rtspin.c
index 5054d0b..657a94c 100644
--- a/bin/rtspin.c
+++ b/bin/rtspin.c
@@ -80,7 +80,7 @@ static void get_exec_times(const char *file, const int column,
80 80
81 for (cur_col = 1; cur_col < column; ++cur_col) { 81 for (cur_col = 1; cur_col < column; ++cur_col) {
82 /* discard input until we get to the column we want */ 82 /* discard input until we get to the column we want */
83 fscanf(fstream, "%*s,"); 83 int unused __attribute__ ((unused)) = fscanf(fstream, "%*s,");
84 } 84 }
85 85
86 /* get the desired exec. time */ 86 /* get the desired exec. time */
@@ -200,11 +200,11 @@ int main(int argc, char** argv)
200 int column = 1; 200 int column = 1;
201 const char *file = NULL; 201 const char *file = NULL;
202 int want_enforcement = 0; 202 int want_enforcement = 0;
203 double duration = 0, start; 203 double duration = 0, start = 0;
204 double *exec_times = NULL; 204 double *exec_times = NULL;
205 double scale = 1.0; 205 double scale = 1.0;
206 task_class_t class = RT_CLASS_HARD; 206 task_class_t class = RT_CLASS_HARD;
207 int cur_job, num_jobs; 207 int cur_job = 0, num_jobs = 0;
208 208
209 /* locking */ 209 /* locking */
210 int lock_od = -1; 210 int lock_od = -1;
diff --git a/bin/uncache.c b/bin/uncache.c
new file mode 100644
index 0000000..b6f6913
--- /dev/null
+++ b/bin/uncache.c
@@ -0,0 +1,381 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <time.h>
5#include <sched.h>
6#include <assert.h>
7#include <string.h>
8#include <stdint.h>
9#include <sys/fcntl.h>
10#include <sys/mman.h>
11
12/* Test tool for validating Litmus's uncache device. */
13/* Tool also capable basic cache vs. sysmem statistics. */
14/* Compile with '-O2' for significaintly greater margins */
15/* in performance between cache and sysmem: */
16/* (Intel Xeon X5650) */
17/* -g -> uncache is 30x slower */
18/* -O2 -> uncache is >100x slower */
19
20int PAGE_SIZE;
21#define NR_PAGES 16
22
23#define UNCACHE_DEV "/dev/litmus/uncache"
24
25/* volatile forces a read from memory (or cache) on every reference. Note
26 that volatile does not keep data out of the cache! */
27typedef volatile char* pbuf_t;
28
29/* hit the first byte in each page.
30 addr must be page aligned. */
31inline int linear_write(pbuf_t addr, int size, char val)
32{
33 pbuf_t end = addr + size;
34 pbuf_t step;
35 int nr_pages = (unsigned long)(end - addr)/PAGE_SIZE;
36 int times = nr_pages * PAGE_SIZE;
37 int i;
38
39 for (i = 0; i < times; ++i)
40 for(step = addr; step < end; step += PAGE_SIZE)
41 *step = val;
42 return 0;
43}
44inline int linear_read(pbuf_t addr, int size, char val)
45{
46 pbuf_t end = addr + size;
47 pbuf_t step;
48 int nr_pages = (unsigned long)(end - addr)/PAGE_SIZE;
49 int times = nr_pages * PAGE_SIZE;
50 int i;
51
52 for (i = 0; i < times; ++i)
53 for(step = addr; step < end; step += PAGE_SIZE) {
54 if (*step != val)
55 return -1;
56 }
57 return 0;
58}
59
60/* write to *data nr times. */
61inline int hammer_write(pbuf_t data, char val, int nr)
62{
63 int i;
64 for (i = 0; i < nr; ++i)
65 *data = val;
66 return 0;
67}
68
69/* read from *data nr times. */
70inline int hammer_read(pbuf_t data, char val, int nr)
71{
72 int i;
73 for (i = 0; i < nr; ++i) {
74 if (*data != val)
75 return -1;
76 }
77 return 0;
78}
79
80inline int test(pbuf_t data, int size, int trials)
81{
82 int HAMMER_TIME = 10000; /* can't cache this! */
83 char VAL = 0x55;
84 int t;
85 for(t = 0; t < trials; ++t) {
86
87#if 0
88 if (linear_write(data, size, VAL) != 0) {
89 printf("failed linear_write()\n");
90 return -1;
91 }
92 if (linear_read(data, size, VAL) != 0) {
93 printf("failed linear_read()\n");
94 return -1;
95 }
96#endif
97
98 /* hammer at the first byte in the array */
99 if (hammer_write(data, VAL, HAMMER_TIME) != 0) {
100 printf("failed hammer_write()\n");
101 return -1;
102 }
103 if (hammer_read(data, VAL, HAMMER_TIME) != 0) {
104 printf("failed hammer_read()\n");
105 return -1;
106 }
107 }
108 return 0;
109}
110
111inline void timespec_normalize(struct timespec* ts, time_t sec, int64_t nsec)
112{
113 while(nsec > 1000000000LL) {
114 asm("" : "+rm"(nsec));
115 nsec -= 1000000000LL;
116 ++sec;
117 }
118 while(nsec < 0) {
119 asm("" : "+rm"(nsec));
120 nsec += 1000000000LL;
121 --sec;
122 }
123
124 ts->tv_sec = sec;
125 ts->tv_nsec = nsec;
126}
127
128inline struct timespec timespec_sub(struct timespec lhs, struct timespec rhs)
129{
130 struct timespec delta;
131 timespec_normalize(&delta, lhs.tv_sec - rhs.tv_sec, lhs.tv_nsec - rhs.tv_nsec);
132 return delta;
133}
134
135inline struct timespec timespec_add(struct timespec lhs, struct timespec rhs)
136{
137 struct timespec delta;
138 timespec_normalize(&delta, lhs.tv_sec + rhs.tv_sec, lhs.tv_nsec + rhs.tv_nsec);
139 return delta;
140}
141
142inline int64_t timespec_to_us(struct timespec ts)
143{
144 int64_t t;
145 t = ts.tv_sec * 1000000LL;
146 t += ts.tv_nsec / 1000LL;
147 return t;
148}
149
150/* hammers away at the first byte in each mmaped page and
151 times how long it took. */
152int do_data(int do_uncache, int64_t* time)
153{
154 int size;
155 int prot = PROT_READ | PROT_WRITE;
156 int flags = MAP_PRIVATE;
157
158 pbuf_t data;
159
160 struct sched_param fifo_params;
161
162 struct timespec start, end;
163 int64_t elapsed;