diff options
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | bin/color.c | 2 | ||||
-rw-r--r-- | bin/colorbench.c | 37 | ||||
-rw-r--r-- | bin/colortest.c | 1 | ||||
-rw-r--r-- | bin/perfcounters.c | 27 | ||||
-rw-r--r-- | bin/singlepage.c | 158 | ||||
-rw-r--r-- | include/perfcounters.h | 10 |
7 files changed, 224 insertions, 18 deletions
@@ -72,7 +72,7 @@ AR := ${CROSS_COMPILE}${AR} | |||
72 | 72 | ||
73 | all = lib ${rt-apps} | 73 | all = lib ${rt-apps} |
74 | rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \ | 74 | rt-apps = cycles base_task rt_launch rtspin release_ts measure_syscall \ |
75 | base_mt_task runtests colortest colorbench testcounters bespin | 75 | base_mt_task runtests colortest colorbench testcounters singlepage |
76 | 76 | ||
77 | .PHONY: all lib clean dump-config TAGS tags cscope help | 77 | .PHONY: all lib clean dump-config TAGS tags cscope help |
78 | 78 | ||
@@ -236,6 +236,9 @@ lib-colortest = -static | |||
236 | obj-colorbench = colorbench.o color.o perfcounters.o common.o | 236 | obj-colorbench = colorbench.o color.o perfcounters.o common.o |
237 | lib-colorbench = -lpthread -lrt -lgsl -lgslcblas | 237 | lib-colorbench = -lpthread -lrt -lgsl -lgslcblas |
238 | 238 | ||
239 | obj-singlepage = singlepage.o color.o perfcounters.o common.o | ||
240 | lib-singlepage = | ||
241 | |||
239 | obj-testcounters = testcounters.o | 242 | obj-testcounters = testcounters.o |
240 | lib-testcounters = | 243 | lib-testcounters = |
241 | 244 | ||
@@ -244,7 +247,7 @@ lib-testcounters = | |||
244 | 247 | ||
245 | .SECONDEXPANSION: | 248 | .SECONDEXPANSION: |
246 | ${rt-apps}: $${obj-$$@} liblitmus.a | 249 | ${rt-apps}: $${obj-$$@} liblitmus.a |
247 | $(CC) -o $@ $(LDFLAGS) ${ldf-$@} $(filter-out liblitmus.a,$+) $(LOADLIBS) $(LDLIBS) ${liblitmus-flags} ${lib-$@} | 250 | $(CC) -o $@ $(LDFLAGS) ${ldf-$@} $(filter-out liblitmus.a,$+) $(LOADLIBS) $(LDLIBS) ${lib-$@} ${liblitmus-flags} |
248 | 251 | ||
249 | # ############################################################################## | 252 | # ############################################################################## |
250 | # Dependency resolution. | 253 | # Dependency resolution. |
diff --git a/bin/color.c b/bin/color.c index 2ec97a4..c1753a4 100644 --- a/bin/color.c +++ b/bin/color.c | |||
@@ -21,7 +21,7 @@ static int map_file(const char* filename, void **addr, size_t size) | |||
21 | if (fd >= 0) { | 21 | if (fd >= 0) { |
22 | *addr = mmap(NULL, size, | 22 | *addr = mmap(NULL, size, |
23 | PROT_READ | PROT_WRITE, | 23 | PROT_READ | PROT_WRITE, |
24 | MAP_PRIVATE, | 24 | MAP_SHARED, |
25 | fd, 0); | 25 | fd, 0); |
26 | if (*addr == MAP_FAILED) | 26 | if (*addr == MAP_FAILED) |
27 | error = -1; | 27 | error = -1; |
diff --git a/bin/colorbench.c b/bin/colorbench.c index c91b731..ac0c01a 100644 --- a/bin/colorbench.c +++ b/bin/colorbench.c | |||
@@ -18,17 +18,25 @@ | |||
18 | #define DEBUG 1 | 18 | #define DEBUG 1 |
19 | #define NR_LOOPS 10 | 19 | #define NR_LOOPS 10 |
20 | 20 | ||
21 | #if 0 | ||
21 | /* Pound */ | 22 | /* Pound */ |
22 | #define NR_CPUS 4 | 23 | #define NR_CPUS 4 |
23 | #define CACHE_SIZE_MB 8 | 24 | #define CACHE_SIZE_MB 8 |
24 | #define ASSOC 16 | 25 | #define ASSOC 16 |
25 | #define LINE_SIZE 64 | 26 | #define LINE_SIZE 64 |
27 | #endif | ||
28 | |||
29 | /* Flare */ | ||
30 | #define NR_CPUS 1 | ||
31 | #define CACHE_SIZE_MB 3 | ||
32 | #define ASSOC 12 | ||
33 | #define LINE_SIZE 64 | ||
26 | 34 | ||
27 | #define CACHE_SIZE (CACHE_SIZE_MB * 1024 * 1024) | 35 | #define CACHE_SIZE (CACHE_SIZE_MB * 1024 * 1024) |
28 | #define TOTAL_COLORS (CACHE_SIZE / ASSOC / PAGE_SIZE) | 36 | #define TOTAL_COLORS (CACHE_SIZE / ASSOC / PAGE_SIZE) |
29 | 37 | ||
30 | /* number of colors we actually use */ | 38 | /* number of colors we actually use (cannot be zero) */ |
31 | #define USE_COLORS (TOTAL_COLORS >> color_shift) | 39 | #define USE_COLORS ({int v = TOTAL_COLORS >> color_shift; (v) ? v : 1; }) |
32 | 40 | ||
33 | /* how many adjacent pages of the same color we need to allocate */ | 41 | /* how many adjacent pages of the same color we need to allocate */ |
34 | #define CONTIG_COLORS (ARENA_PAGES / USE_COLORS) | 42 | #define CONTIG_COLORS (ARENA_PAGES / USE_COLORS) |
@@ -76,7 +84,7 @@ static pthread_barrier_t barrier; | |||
76 | static int nr_threads; | 84 | static int nr_threads; |
77 | static int arena_size; | 85 | static int arena_size; |
78 | static int color_shift; | 86 | static int color_shift; |
79 | //static int *page_line_order; | 87 | static int *page_line_order; |
80 | static int *arena_line_order; | 88 | static int *arena_line_order; |
81 | static struct perf_counter perf_counters[NR_CPUS * NR_PERF_COUNTERS]; | 89 | static struct perf_counter perf_counters[NR_CPUS * NR_PERF_COUNTERS]; |
82 | 90 | ||
@@ -138,7 +146,6 @@ void sattolo(int *items, const int len) | |||
138 | * Starting at position 0 in the page_line_order means the cycle ends with 0. | 146 | * Starting at position 0 in the page_line_order means the cycle ends with 0. |
139 | * We use 0 in the arena to signify that we are done reading. | 147 | * We use 0 in the arena to signify that we are done reading. |
140 | */ | 148 | */ |
141 | #if 0 | ||
142 | static void init_arena_page_line_order(int *arena) | 149 | static void init_arena_page_line_order(int *arena) |
143 | { | 150 | { |
144 | int cur_page; | 151 | int cur_page; |
@@ -168,7 +175,8 @@ static void init_arena_page_line_order(int *arena) | |||
168 | } | 175 | } |
169 | } | 176 | } |
170 | } | 177 | } |
171 | #endif | 178 | |
179 | #if 0 | ||
172 | static void init_arena_line_order(int *arena) | 180 | static void init_arena_line_order(int *arena) |
173 | { | 181 | { |
174 | int cur_line; | 182 | int cur_line; |
@@ -184,6 +192,7 @@ static void init_arena_line_order(int *arena) | |||
184 | arena[idx] = next_idx; | 192 | arena[idx] = next_idx; |
185 | } | 193 | } |
186 | } | 194 | } |
195 | #endif | ||
187 | 196 | ||
188 | static void setup_colors(struct pthread_state *state) | 197 | static void setup_colors(struct pthread_state *state) |
189 | { | 198 | { |
@@ -262,8 +271,8 @@ int thread_init(struct pthread_state *state) | |||
262 | goto out; | 271 | goto out; |
263 | } | 272 | } |
264 | 273 | ||
265 | //init_arena_page_line_order(state->arena); | 274 | init_arena_page_line_order(state->arena); |
266 | init_arena_line_order(state->arena); | 275 | //init_arena_line_order(state->arena); |
267 | 276 | ||
268 | err = mlockall(MCL_CURRENT|MCL_FUTURE); | 277 | err = mlockall(MCL_CURRENT|MCL_FUTURE); |
269 | if (err) | 278 | if (err) |
@@ -405,7 +414,7 @@ int main(int argc, char **argv) | |||
405 | } | 414 | } |
406 | 415 | ||
407 | pthread_state = malloc(nr_threads * sizeof(*pthread_state)); | 416 | pthread_state = malloc(nr_threads * sizeof(*pthread_state)); |
408 | //page_line_order = malloc(PAGE_LINES * sizeof(*page_line_order)); | 417 | page_line_order = malloc(PAGE_LINES * sizeof(*page_line_order)); |
409 | arena_line_order = malloc(ARENA_LINES * sizeof(*arena_line_order)); | 418 | arena_line_order = malloc(ARENA_LINES * sizeof(*arena_line_order)); |
410 | //if (!pthread_state || !page_line_order) { | 419 | //if (!pthread_state || !page_line_order) { |
411 | if (!pthread_state || !arena_line_order) { | 420 | if (!pthread_state || !arena_line_order) { |
@@ -420,9 +429,10 @@ int main(int argc, char **argv) | |||
420 | CHECK(pthread_attr_setdetachstate, &attr, PTHREAD_CREATE_JOINABLE); | 429 | CHECK(pthread_attr_setdetachstate, &attr, PTHREAD_CREATE_JOINABLE); |
421 | CHECK(pthread_barrier_init, &barrier, NULL, nr_threads); | 430 | CHECK(pthread_barrier_init, &barrier, NULL, nr_threads); |
422 | 431 | ||
423 | //sattolo(page_line_order, PAGE_LINES); | 432 | sattolo(page_line_order, PAGE_LINES); |
424 | sattolo(arena_line_order, ARENA_LINES); | 433 | //sattolo(arena_line_order, ARENA_LINES); |
425 | //sequential(page_line_order, PAGE_LINES); | 434 | //sequential(page_line_order, PAGE_LINES); |
435 | //sequential(arena_line_order, PAGE_LINES); | ||
426 | 436 | ||
427 | for (i = 0; i < nr_threads; i++) { | 437 | for (i = 0; i < nr_threads; i++) { |
428 | pthread_state[i].tid = i; | 438 | pthread_state[i].tid = i; |
@@ -447,12 +457,15 @@ int main(int argc, char **argv) | |||
447 | CHECK(pthread_barrier_destroy, &barrier); | 457 | CHECK(pthread_barrier_destroy, &barrier); |
448 | CHECK(pthread_attr_destroy, &attr); | 458 | CHECK(pthread_attr_destroy, &attr); |
449 | 459 | ||
460 | printf("page size: %d\n", PAGE_SIZE); | ||
461 | printf("cache size: %d\n", CACHE_SIZE); | ||
462 | printf("total colors: %d\n", TOTAL_COLORS); | ||
463 | printf("use colors: %d\n", USE_COLORS); | ||
464 | printf("contiguous colors: %d\n", CONTIG_COLORS); | ||
450 | printf("arena size: %d\n", arena_size); | 465 | printf("arena size: %d\n", arena_size); |
451 | printf("color shift: %d\n", color_shift); | 466 | printf("color shift: %d\n", color_shift); |
452 | printf("arena pages: %d\n", ARENA_PAGES); | 467 | printf("arena pages: %d\n", ARENA_PAGES); |
453 | printf("arena lines: %d\n", ARENA_LINES); | 468 | printf("arena lines: %d\n", ARENA_LINES); |
454 | printf("use colors: %d\n", USE_COLORS); | ||
455 | printf("contiguous colors: %d\n", CONTIG_COLORS); | ||
456 | //print_perf_counters(); | 469 | //print_perf_counters(); |
457 | 470 | ||
458 | out: | 471 | out: |
diff --git a/bin/colortest.c b/bin/colortest.c index 02a9169..bc66522 100644 --- a/bin/colortest.c +++ b/bin/colortest.c | |||
@@ -1,7 +1,6 @@ | |||
1 | #include <stdlib.h> | 1 | #include <stdlib.h> |
2 | #include <stdio.h> | 2 | #include <stdio.h> |
3 | #include <stdint.h> | 3 | #include <stdint.h> |
4 | |||
5 | #include <litmus/rt_param.h> | 4 | #include <litmus/rt_param.h> |
6 | 5 | ||
7 | #include "color.h" | 6 | #include "color.h" |
diff --git a/bin/perfcounters.c b/bin/perfcounters.c index 6302164..975ee5b 100644 --- a/bin/perfcounters.c +++ b/bin/perfcounters.c | |||
@@ -39,7 +39,7 @@ struct perf_counter_setup { | |||
39 | }; | 39 | }; |
40 | 40 | ||
41 | #if 0 | 41 | #if 0 |
42 | /* these events are always zero */ | 42 | /* on Pound, these events are always zero */ |
43 | static struct perf_fd perf_fds[] = { | 43 | static struct perf_fd perf_fds[] = { |
44 | { | 44 | { |
45 | .fd = -1, | 45 | .fd = -1, |
@@ -61,6 +61,8 @@ static struct perf_fd perf_fds[] = { | |||
61 | }; | 61 | }; |
62 | #endif | 62 | #endif |
63 | 63 | ||
64 | #if 0 | ||
65 | /* these are for Pound */ | ||
64 | static struct perf_counter_setup perf_setup[NR_PERF_COUNTERS] = { | 66 | static struct perf_counter_setup perf_setup[NR_PERF_COUNTERS] = { |
65 | #if 0 | 67 | #if 0 |
66 | { | 68 | { |
@@ -108,7 +110,30 @@ static struct perf_counter_setup perf_setup[NR_PERF_COUNTERS] = { | |||
108 | #endif | 110 | #endif |
109 | }, | 111 | }, |
110 | }; | 112 | }; |
113 | #endif | ||
111 | 114 | ||
115 | static struct perf_counter_setup perf_setup[NR_PERF_COUNTERS] = { | ||
116 | { | ||
117 | .name = "Linux LL Cache Read Miss", | ||
118 | .type = PERF_TYPE_HW_CACHE, | ||
119 | .config = ATTR_CONFIG_CACHE(LL, OP_READ, RESULT_MISS), | ||
120 | #if 0 | ||
121 | /* read misses */ | ||
122 | .config = ATTR_CONFIG_CACHE(LL, OP_READ, RESULT_MISS), | ||
123 | /* write misses */ | ||
124 | .config = ATTR_CONFIG_CACHE(LL, OP_WRITE, RESULT_MISS), | ||
125 | /* prefetch misses */ | ||
126 | .config = ATTR_CONFIG_CACHE(LL, OP_PREFETCH, RESULT_MISS), | ||
127 | #endif | ||
128 | }, | ||
129 | #if (2 == NR_PERF_COUNTERS) | ||
130 | { | ||
131 | .name = "Cycles", | ||
132 | .type = PERF_TYPE_HARDWARE, | ||
133 | .config = PERF_COUNT_HW_CPU_CYCLES, | ||
134 | }, | ||
135 | #endif | ||
136 | }; | ||
112 | 137 | ||
113 | /* from kernel tools/perf/perf.h */ | 138 | /* from kernel tools/perf/perf.h */ |
114 | int sys_perf_event_open(struct perf_event_attr *attr, pid_t pid, | 139 | int sys_perf_event_open(struct perf_event_attr *attr, pid_t pid, |
diff --git a/bin/singlepage.c b/bin/singlepage.c new file mode 100644 index 0000000..376f55d --- /dev/null +++ b/bin/singlepage.c | |||
@@ -0,0 +1,158 @@ | |||
1 | #include <stdint.h> | ||
2 | #include <stdio.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <sys/ioctl.h> | ||
5 | |||
6 | #include <litmus/rt_param.h> | ||
7 | |||
8 | #include "perfcounters.h" | ||
9 | #include "color.h" | ||
10 | #include "litmus.h" | ||
11 | |||
12 | #define CPU 0 | ||
13 | #define NR_PAGES 10 | ||
14 | #define NR_LOOPS 10 | ||
15 | |||
16 | struct page { | ||
17 | struct page *ptr; | ||
18 | char _unused[PAGE_SIZE - sizeof(struct page*)]; | ||
19 | }; | ||
20 | |||
21 | /* | ||
22 | * Get a random number in [0, max). Not really a good way to do this. | ||
23 | */ | ||
24 | static int randrange(const int max) | ||
25 | { | ||
26 | return (rand() / (RAND_MAX / max + 1)); | ||
27 | } | ||
28 | |||
29 | /* | ||
30 | * Sattolo's algorithm makes a random cycle that includes all the elements | ||
31 | * in the items array. | ||
32 | */ | ||
33 | static void sattolo(int *items, const int len) | ||
34 | { | ||
35 | int i; | ||
36 | /* first set up 0, 1, ..., n - 1 */ | ||
37 | for (i = 0; i < len; i++) | ||
38 | items[i] = i; | ||
39 | /* note: i is now n */ | ||
40 | while (1 < i--) { | ||
41 | /* 0 <= j < i */ | ||
42 | int t, j = randrange(i); | ||
43 | t = items[i]; | ||
44 | items[i] = items[j]; | ||
45 | items[j] = t; | ||
46 | } | ||
47 | } | ||
48 | static struct page * do_read(struct page* page) | ||
49 | { | ||
50 | struct page *old; | ||
51 | do { | ||
52 | old = page; | ||
53 | page = page->ptr; | ||
54 | } while (page); | ||
55 | return old; | ||
56 | } | ||
57 | |||
58 | static inline void get_counters(const struct perf_counter *pc, uint64_t *vals) | ||
59 | { | ||
60 | read_perf_counter(&pc[0], &vals[0]); | ||
61 | #if (2 == NR_PERF_COUNTERS) | ||
62 | read_perf_counter(&pc[1], &vals[1]); | ||
63 | #endif | ||
64 | } | ||
65 | |||
66 | static void print_counters(uint64_t *vals, double div) | ||
67 | { | ||
68 | int i; | ||
69 | for (i = 0; i < NR_PERF_COUNTERS; i++) { | ||
70 | printf("counter %d: %12lu div: %8.3f\n", i, vals[i], vals[i] / div); | ||
71 | } | ||
72 | printf("\n"); | ||
73 | } | ||
74 | |||
75 | #define quit_on_err(err, msg) do { \ | ||
76 | if (err) { \ | ||
77 | fprintf(stderr, "error: " msg); \ | ||
78 | goto out; \ | ||
79 | } \ | ||
80 | } while (0) | ||
81 | |||
82 | int main(int argc, char **argv) | ||
83 | { | ||
84 | static struct perf_counter perf_counters[NR_PERF_COUNTERS]; | ||
85 | struct color_ctrl_page *color_ctrl; | ||
86 | struct page *pages[NR_PAGES]; | ||
87 | struct page *page_ptr; | ||
88 | int read_order[NR_PAGES]; | ||
89 | uint64_t counter_vals[NR_PERF_COUNTERS]; | ||
90 | int i, err = 0; | ||
91 | |||
92 | err = be_migrate_to(CPU); | ||
93 | quit_on_err(err, "migrate to cpu\n"); | ||
94 | |||
95 | err = setup_cpu_perf(CPU, -1, perf_counters); | ||
96 | quit_on_err(err, "setup perf\n"); | ||
97 | |||
98 | ioctl(perf_counters[0].fd, PERF_EVENT_IOC_DISABLE); | ||
99 | ioctl(perf_counters[0].fd, PERF_EVENT_IOC_RESET); | ||
100 | |||
101 | |||
102 | err = map_color_ctrl((void**)&color_ctrl); | ||
103 | quit_on_err(err, "map color ctrl\n"); | ||
104 | |||
105 | color_ctrl->colors[0] = 0; | ||
106 | |||
107 | for (i = 0; i < NR_PAGES; i++) { | ||
108 | pages[i] = color_malloc(sizeof(*pages[i])); | ||
109 | if (!pages[i]) { | ||
110 | fprintf(stderr, "could not color malloc\n"); | ||
111 | err = -1; | ||
112 | goto out; | ||
113 | } | ||
114 | } | ||
115 | |||
116 | sattolo(read_order, NR_PAGES); | ||
117 | |||
118 | ioctl(perf_counters[0].fd, PERF_EVENT_IOC_ENABLE); | ||
119 | |||
120 | for (i = 0; i < NR_PAGES; i++) { | ||
121 | if (0 != read_order[i]) { | ||
122 | /* not the last element */ | ||
123 | pages[i]->ptr = pages[read_order[i]]; | ||
124 | } else { | ||
125 | /* last element should be NULL (terminate the cycle) */ | ||
126 | pages[i]->ptr = NULL; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | get_counters(perf_counters, counter_vals); | ||
131 | print_counters(counter_vals, NR_PAGES); | ||
132 | ioctl(perf_counters[0].fd, PERF_EVENT_IOC_RESET); | ||
133 | |||
134 | page_ptr = do_read(pages[0]); | ||
135 | get_counters(perf_counters, counter_vals); | ||
136 | print_counters(counter_vals, NR_PAGES); | ||
137 | ioctl(perf_counters[0].fd, PERF_EVENT_IOC_RESET); | ||
138 | |||
139 | page_ptr = do_read(pages[0]); | ||
140 | get_counters(perf_counters, counter_vals); | ||
141 | print_counters(counter_vals, NR_PAGES); | ||
142 | ioctl(perf_counters[0].fd, PERF_EVENT_IOC_RESET); | ||
143 | |||
144 | page_ptr = do_read(pages[0]); | ||
145 | get_counters(perf_counters, counter_vals); | ||
146 | print_counters(counter_vals, NR_PAGES); | ||
147 | ioctl(perf_counters[0].fd, PERF_EVENT_IOC_RESET); | ||
148 | |||
149 | for (i = 0; i < NR_LOOPS; i++) { | ||
150 | page_ptr = do_read(pages[0]); | ||
151 | } | ||
152 | get_counters(perf_counters, counter_vals); | ||
153 | print_counters(counter_vals, NR_PAGES * NR_LOOPS); | ||
154 | ioctl(perf_counters[0].fd, PERF_EVENT_IOC_DISABLE); | ||
155 | |||
156 | out: | ||
157 | return err; | ||
158 | } | ||
diff --git a/include/perfcounters.h b/include/perfcounters.h index 03f94fb..0329921 100644 --- a/include/perfcounters.h +++ b/include/perfcounters.h | |||
@@ -5,7 +5,15 @@ | |||
5 | 5 | ||
6 | #include "../../litmus-rt/include/linux/perf_event.h" | 6 | #include "../../litmus-rt/include/linux/perf_event.h" |
7 | 7 | ||
8 | #define NR_PERF_COUNTERS 4 | 8 | /* on Pound */ |
9 | //#define NR_PERF_COUNTERS 4 | ||
10 | |||
11 | /* | ||
12 | * Flare: 1 gets you the L2 read misses and 2 gets you that plus the | ||
13 | * CPU clock counter. However, accessing the CPU clock will add misses | ||
14 | * when you go to read the performance counters, so I don't use it. | ||
15 | */ | ||
16 | #define NR_PERF_COUNTERS 1 | ||
9 | 17 | ||
10 | /* | 18 | /* |
11 | * Retain this information with a performance counter file descriptor. | 19 | * Retain this information with a performance counter file descriptor. |