1#include <stdlib.h> 2#include <stdbool.h> 3#include <stdio.h> 4#include <string.h> 5#include <barrelfish/barrelfish.h> 6#include <barrelfish/types.h> 7#include <barrelfish/cap_predicates.h> 8#include <bench/bench.h> 9 10#include "mdb_bench.h" 11 12const char *progname = NULL; 13 14static void test(char *base, size_t size, size_t runs, reset_fn reset, measure_fn measure, const char *name) 15{ 16 assert(size % sizeof(struct cte) == 0); 17 struct cte *ctes = (struct cte*)base; 18 size_t num_caps = size/sizeof(struct cte); 19 20 int run, skipped; 21 for (run = skipped = 0; 22 run < runs && (skipped < runs/10 || skipped < run*2); 23 run++) 24 { 25 // reset MDB 26 reset(base, size); 27 28 // perform measurement 29 cycles_t val = measure(ctes, num_caps); 30 31 if (!val) { 32 // measurement skipped 33 printf("%s: skipping\n", name); 34 skipped++; 35 run--; 36 continue; 37 } 38 39 // output 40 printf("%s:%s: %"PRIu64"/%zu\n", progname, name, val - bench_tscoverhead(), num_caps); 41 } 42 43 if (run < runs) { 44 printf("%s: skipped too many, aborting\n", name); 45 } 46} 47 48static void 49reset_and_dump(char *base, size_t size, size_t runs, reset_fn reset, const char *name) 50{ 51 assert(size % sizeof(struct cte) == 0); 52 struct cte *ctes = (struct cte*)base; 53 size_t num_caps = size/sizeof(struct cte); 54 55 for (size_t run = 0; run < runs; run++) { 56 // reset MDB 57 reset(base, size); 58 59 for (size_t i = 0; i < num_caps; i++) { 60 INS(&ctes[i]); 61 } 62 63 // dump entries 64 for (size_t i = 0; i < num_caps; i++) { 65 struct cte *cte = &ctes[i]; 66 struct capability *curr = &cte->cap; 67 assert(curr->type == ObjType_RAM); 68 printf("%s/%zu:dump:%zu: 0x%08"PRIxGENPADDR"/0x%"PRIxGENSIZE" %c%c%c\n", 69 name, num_caps, run, curr->u.ram.base, curr->u.ram.bytes, 70 (HASCOP(cte) ? 'c' : '.'), (HASANC(cte) ? 'a' : '.'), 71 (HASDESC(cte) ? 'd' : '.')); 72 } 73 } 74} 75 76static void usage(const char *program) 77{ 78 printf("usage: %s [runs=NUM]" 79 " [size=NUM] [count=NUM]" 80 " [logsize=NUM] [logcount=NUM]" 81 " [reset=NAME] [measure=NAME]\n\n", program); 82 printf("\truns defaults to 100\n"); 83 printf("\tlogsize defaults to 20\n"); 84 printf("\tcount = size/sizeof(struct cte)\n\n"); 85 printf("resetters:\n"); 86 for (int i = 0; reset_opts[i].name; i++) { 87 printf("\t%s\n", reset_opts[i].name); 88 } 89 printf("\n"); 90 printf("measures:\n"); 91 for (int i = 0; measure_opts[i].name; i++) { 92 printf("\t%s\n", measure_opts[i].name); 93 } 94 printf("\tdump\n"); 95 printf("\n"); 96} 97 98int main(int argc, char* argv[]) 99{ 100 progname = argv[0]; 101 102 size_t size_wanted = 1<<20; 103 size_t runs = 100; 104 struct reset_opt *reset = NULL; 105 struct measure_opt *measure = NULL; 106 bool dump = false; 107 108 assert(argc>0); 109 if (argc == 1) { 110 usage(argv[0]); 111 return 0; 112 } 113 114 bool args_ok = true; 115 116 for (int arg = 1; arg < argc; arg++) { 117 if (strcmp(argv[arg], "help") == 0 118 || strcmp(argv[arg], "--help") == 0 119 || strcmp(argv[arg], "-h") == 0) 120 { 121 usage(argv[0]); 122 return 0; 123 } 124 if (strncmp(argv[arg], "size=", 5) == 0) { 125 size_wanted = atol(argv[arg]+5); 126 } 127 if (strncmp(argv[arg], "logsize=", 8) == 0) { 128 size_t logsize = atol(argv[arg]+8); 129 if (logsize > 31) { 130 printf("ERROR: logsize too big\n"); 131 args_ok = false; 132 } 133 else { 134 size_wanted = 1 << logsize; 135 } 136 } 137 else if (strncmp(argv[arg], "count=", 6) == 0) { 138 size_wanted = atol(argv[arg]+6)*sizeof(struct cte); 139 } 140 else if (strncmp(argv[arg], "logcount=", 9) == 0) { 141 size_t logcount = atol(argv[arg]+9); 142 if (logcount > (31-OBJBITS_CTE)) { 143 printf("ERROR: logcount too big\n"); 144 args_ok = false; 145 } 146 else { 147 size_wanted = (1 << logcount)*sizeof(struct cte); 148 } 149 } 150 else if (strncmp(argv[arg], "runs=", 5) == 0) { 151 runs = atol(argv[arg]+5); 152 } 153 else if (strncmp(argv[arg], "reset=", 6) == 0) { 154 char *name = argv[arg]+6; 155 int i; 156 for (i = 0; reset_opts[i].name; i++) { 157 if (strcmp(reset_opts[i].name, name) == 0) { 158 reset = &reset_opts[i]; 159 break; 160 } 161 } 162 if (!reset_opts[i].name) { 163 args_ok = false; 164 printf("ERROR: unkown reset \"%s\"\n", name); 165 } 166 } 167 else if (strncmp(argv[arg], "measure=", 8) == 0) { 168 char *name = argv[arg]+8; 169 if (strcmp(name, "dump") == 0) { 170 measure = NULL; 171 dump = true; 172 } 173 else { 174 int i; 175 for (i = 0; measure_opts[i].name; i++) { 176 if (strcmp(measure_opts[i].name, name) == 0) { 177 measure = &measure_opts[i]; 178 break; 179 } 180 } 181 182 if (measure_opts[i].name) { 183 dump = false; 184 } 185 else { 186 args_ok = false; 187 printf("ERROR: unkown measure \"%s\"\n", name); 188 } 189 } 190 } 191 else if (strncmp(argv[arg], "seed=", 5) == 0) { 192 char *seedarg = argv[arg]+5; 193 unsigned long seed = strtoul(seedarg, NULL, 10); 194 srand(seed); 195 } 196 else { 197 args_ok = false; 198 printf("ERROR: unkown argument %s\n", argv[arg]); 199 } 200 } 201 if (!args_ok) { 202 usage(argv[0]); 203 return 1; 204 } 205 206 assert(size_wanted > 0); 207 assert(runs > 0); 208 assert(reset); 209 assert(measure || dump); 210 211 errval_t err; 212 struct capref frame; 213 size_t size; 214 err = frame_alloc(&frame, size_wanted, &size); 215 assert_err(err, "alloc"); 216 assert(size >= size_wanted); 217 printf("got %zu bytes\n", size); 218 219 struct memobj *m; 220 struct vregion *v; 221 void *addr; 222 223 err = vspace_map_one_frame(&addr, size, frame, &m, &v); 224 assert_err(err, "map"); 225 226 if (dump) { 227 reset_and_dump(addr, size_wanted, runs, reset->fn, reset->name); 228 } 229 else { 230 bench_init(); 231 232 char *bench_name = malloc(strlen(reset->name)+strlen(measure->name)+2); 233 strcpy(bench_name, reset->name); 234 strcat(bench_name, ":"); 235 strcat(bench_name, measure->name); 236 test(addr, size_wanted, runs, reset->fn, measure->fn, bench_name); 237 238 free(bench_name); 239 } 240 241 printf("client done\n"); 242 243 vregion_destroy(v); 244 cap_destroy(frame); 245 246 return 0; 247} 248