1/* 2 * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <stdlib.h> 11#include <stdio.h> 12//#include <time.h> 13#include <barrelfish/barrelfish.h> 14#include <barrelfish/sys_debug.h> 15#include <barrelfish/deferred.h> 16#include <devif/queue_interface.h> 17#include <devif/backends/loopback_devif.h> 18#include <devif/backends/null.h> 19#include <bench/bench.h> 20#include <vfs/vfs.h> 21 22//#define DEBUG(x...) printf("devif_test: " x) 23#define DEBUG(x...) do {} while (0) 24 25#define BUF_SIZE 2048 26#define NUM_BUFS 128 27#define MEMORY_SIZE BUF_SIZE*NUM_BUFS 28 29#define NUM_REGIONS 128 30#define NUM_ROUNDS 100000 31#define NUM_STACKS 10 32 33static struct capref memory; 34static regionid_t regid; 35static struct frame_identity id; 36static lpaddr_t phys; 37 38static void* va; 39 40struct direct_state { 41 struct list_ele* first; 42 struct list_ele* last; 43}; 44 45struct list_ele{ 46 regionid_t rid; 47 bufferid_t bid; 48 lpaddr_t addr; 49 size_t len; 50 uint64_t flags; 51 52 struct list_ele* next; 53}; 54 55static struct loopback_queue* queue; 56static struct null_q* null_q[NUM_STACKS+1]; 57static struct devq* que; 58 59static cycles_t tot_deq = 0; 60static cycles_t tot_enq = 0; 61static cycles_t tot_reg = 0; 62static cycles_t tot_dereg = 0; 63static cycles_t start_enq = 0, end_enq = 0; 64static cycles_t start_deq = 0, end_deq = 0; 65static cycles_t start_reg = 0, end_reg = 0; 66static cycles_t start_dereg = 0, end_dereg = 0; 67 68static bench_ctl_t *ctl_tmp_en; 69static bench_ctl_t *ctl_tmp_de; 70static bench_ctl_t *ctl_tmp_reg; 71static bench_ctl_t *ctl_tmp_dereg; 72 73static cycles_t tscperus; 74static char* machine_name; 75 76static void dump_results_nfs(char* prefix, bool destroy) 77//static void dump_results_console(char* prefix, bool destroy) 78{ 79 char buffer[512]; 80 81 // first 10 % is warmup 82 if (ctl_tmp_en == NULL) { 83 return; 84 } 85 86 for (int i = NUM_ROUNDS/10 ; i < NUM_ROUNDS; i++) { 87#ifdef BENCH_DEVQ 88 sprintf(buffer, ";%s_devq;enqueue;%lu;dequeue;%lu;register;%lu;deregister;%lu \n", 89#else 90 sprintf(buffer, ";%s;enqueue;%lu;dequeue;%lu;register;%lu;deregister;%lu \n", 91#endif 92 prefix, 93 ctl_tmp_en->data[i], ctl_tmp_de->data[i], ctl_tmp_reg->data[i], 94 ctl_tmp_dereg->data[i]); 95 printf("%s", buffer); 96 } 97 98 if (destroy) { 99 bench_ctl_destroy(ctl_tmp_dereg); 100 bench_ctl_destroy(ctl_tmp_reg); 101 bench_ctl_destroy(ctl_tmp_de); 102 bench_ctl_destroy(ctl_tmp_en); 103 } 104} 105 106static void test_register(void) 107{ 108 errval_t err; 109 struct capref regions[NUM_REGIONS]; 110 regionid_t rids[NUM_REGIONS]; 111 112 tot_reg = 0; 113 tot_dereg = 0; 114 115 ctl_tmp_reg = calloc(1, sizeof(*ctl_tmp_reg)); 116 ctl_tmp_reg->mode = BENCH_MODE_FIXEDRUNS; 117 ctl_tmp_reg->result_dimensions = 1; 118 ctl_tmp_reg->min_runs = NUM_ROUNDS; 119 ctl_tmp_reg->data = calloc(ctl_tmp_reg->min_runs * ctl_tmp_reg->result_dimensions, 120 sizeof(*ctl_tmp_de->data)); 121 122 ctl_tmp_dereg = calloc(1, sizeof(*ctl_tmp_dereg)); 123 ctl_tmp_dereg->mode = BENCH_MODE_FIXEDRUNS; 124 ctl_tmp_dereg->result_dimensions = 1; 125 ctl_tmp_dereg->min_runs = NUM_ROUNDS; 126 ctl_tmp_dereg->data = calloc(ctl_tmp_dereg->min_runs * ctl_tmp_dereg->result_dimensions, 127 sizeof(*ctl_tmp_dereg->data)); 128 129 for (int i = 0; i < NUM_REGIONS; i++) { 130 err = frame_alloc(®ions[i], BASE_PAGE_SIZE, NULL); 131 if (err_is_fail(err)){ 132 USER_PANIC("Allocating cap failed \n"); 133 } 134 } 135 136 srand(rdtscp()); 137 int idx = 0; 138 struct capref ret; 139 cycles_t res1; 140 cycles_t res2; 141 for (int i = 0; i < NUM_ROUNDS; i++) { 142 idx = i % NUM_REGIONS; 143 start_reg = rdtscp(); 144 err = devq_register(que, regions[idx], &rids[idx]); 145 end_reg = rdtscp(); 146 if (err_is_fail(err)){ 147 USER_PANIC("Registering memory to devq failed: %s \n", 148 err_getstring(err)); 149 } else { 150 tot_reg += end_reg - start_reg; 151 res1 = end_reg - start_reg; 152 bench_ctl_add_run(ctl_tmp_reg, &res1); 153 } 154 155 start_dereg = rdtscp(); 156 err = devq_deregister(que, rids[idx], &ret); 157 end_dereg = rdtscp(); 158 if (err_is_fail(err)){ 159 USER_PANIC("Registering memory to devq failed: %s\n", 160 err_getstring(err)); 161 } else { 162 tot_dereg += end_dereg - start_dereg; 163 res2 = end_dereg - start_dereg; 164 bench_ctl_add_run(ctl_tmp_dereg, &res2); 165 } 166 } 167 168 for (int i = 0; i < NUM_REGIONS; i++) { 169 err = cap_destroy(regions[i]); 170 if (err_is_fail(err)){ 171 USER_PANIC("Destroy region failed: %s\n", 172 err_getstring(err)); 173 } 174 } 175 176 //bench_ctl_dump_analysis(ctl_tmp_dereg, 0, "deregister", tscperus); 177 //bench_ctl_dump_analysis(ctl_tmp_reg, 0, "register", tscperus); 178 179} 180 181static void test_randomized_test(void) 182{ 183 errval_t err; 184 regionid_t rid; 185 genoffset_t offset; 186 genoffset_t length; 187 genoffset_t valid_data; 188 genoffset_t valid_length; 189 uint64_t flags; 190 191 tot_enq = 0; 192 tot_deq = 0; 193 194 ctl_tmp_en = calloc(1, sizeof(*ctl_tmp_en)); 195 ctl_tmp_en->mode = BENCH_MODE_FIXEDRUNS; 196 ctl_tmp_en->result_dimensions = 1; 197 ctl_tmp_en->min_runs = NUM_ROUNDS; 198 ctl_tmp_en->data = calloc(ctl_tmp_en->min_runs * ctl_tmp_en->result_dimensions, 199 sizeof(*ctl_tmp_de->data)); 200 201 ctl_tmp_de = calloc(1, sizeof(*ctl_tmp_en)); 202 ctl_tmp_de->mode = BENCH_MODE_FIXEDRUNS; 203 ctl_tmp_de->result_dimensions = 1; 204 ctl_tmp_de->min_runs = NUM_ROUNDS; 205 ctl_tmp_de->data = calloc(ctl_tmp_de->min_runs * ctl_tmp_de->result_dimensions, 206 sizeof(*ctl_tmp_de->data)); 207 208 srand(rdtscp()); 209 int idx = 0; 210 cycles_t res; 211 // enqueue from the beginning of the region 212 for (int i = 0; i < NUM_ROUNDS; i++) { 213 214 idx = i % NUM_BUFS; 215 start_enq = rdtscp(); 216 217 err = devq_enqueue(que, regid, idx*BUF_SIZE, BUF_SIZE, 218 0, BUF_SIZE, 0); 219 220 end_enq = rdtscp(); 221 if (err_is_fail(err)){ 222 USER_PANIC("Enqueue failed: %s \n", err_getstring(err)); 223 } else { 224 tot_enq += end_enq - start_enq; 225 res = end_enq - start_enq; 226 bench_ctl_add_run(ctl_tmp_de, &res); 227 } 228 229 start_deq = rdtscp(); 230 err = devq_dequeue(que, &rid, &offset, &length, &valid_data, 231 &valid_length, &flags); 232 end_deq = rdtscp(); 233 if (err_is_ok(err)){ 234 tot_deq += end_deq - start_deq; 235 res = end_deq - start_deq; 236 bench_ctl_add_run(ctl_tmp_en, &res); 237 } else { 238 USER_PANIC("Dequeue failed: %s \n", err_getstring(err)); 239 } 240 } 241 242 //bench_ctl_dump_analysis(ctl_tmp_de, 0, "enqueue", tscperus); 243 //bench_ctl_dump_analysis(ctl_tmp_en, 0, "dequeue", tscperus); 244} 245 246int main(int argc, char *argv[]) 247{ 248 249 if (argc > 1) { 250 machine_name = argv[1]; 251 } else { 252 machine_name = "default"; 253 } 254 255 errval_t err; 256 257 // mount_vfs 258 vfs_init(); 259 260 char fname[256]; 261 err = vfs_mount("/nfs", "nfs://10.110.4.4/mnt/local/nfs/haeckir"); 262 if(err_is_fail(err)) { 263 USER_PANIC("vfs_mount: %s \n", err_getstring(err)); 264 } 265 266 sprintf(fname, "/nfs/%s", machine_name); 267 err = vfs_mkdir(fname); 268 if (err_is_fail(err)) { 269 printf("Folder %s already exists \n", fname); 270 } else { 271 printf("Creating folder %s \n", fname); 272 } 273 274 // Allocate memory 275 err = frame_alloc(&memory, MEMORY_SIZE, NULL); 276 if (err_is_fail(err)){ 277 USER_PANIC("Allocating cap failed \n"); 278 } 279 280 // RX frame 281 err = frame_identify(memory, &id); 282 if (err_is_fail(err)) { 283 USER_PANIC("Frame identify failed \n"); 284 } 285 286 err = vspace_map_one_frame_attr(&va, id.bytes, memory, 287 VREGION_FLAGS_READ, NULL, NULL); 288 if (err_is_fail(err)) { 289 USER_PANIC("Frame mapping failed \n"); 290 } 291 292 phys = id.base; 293 294 debug_printf("Descriptor queue test started \n"); 295 err = loopback_queue_create(&queue); 296 if (err_is_fail(err)){ 297 USER_PANIC("Allocating devq failed \n"); 298 } 299 300 // stack null queue on top 301 err = null_create(&null_q[0], (struct devq*) queue); 302 if (err_is_fail(err)) { 303 USER_PANIC("Allocating null q failed \n"); 304 } 305 306 que = (struct devq*) queue; 307 308 err = devq_register(que, memory, ®id); 309 if (err_is_fail(err)){ 310 USER_PANIC("Registering memory to devq failed \n"); 311 } 312 313 err = sys_debug_get_tsc_per_ms(&tscperus); 314 assert(err_is_ok(err)); 315 tscperus /= 1000; 316 317 printf("Starting randomized queue\n"); 318 que = (struct devq*) queue; 319 320 test_register(); 321 322 test_randomized_test(); 323 324 dump_results_nfs("Loopback", true); 325 326#if 0 327 ctl_tmp_en = devq_get_benchmark_data(que, 0); 328 ctl_tmp_de = devq_get_benchmark_data(que, 1); 329 ctl_tmp_reg = devq_get_benchmark_data(que, 2); 330 ctl_tmp_dereg = devq_get_benchmark_data(que, 3); 331 dump_results_nfs("Loopback_bcalls", false); 332#endif 333 char name[512]; 334 sprintf(name, "Null %d", 1); 335 for (int i = 0; i < 10; i++) { 336 printf("############################################################ \n"); 337 338 err = devq_deregister(que, regid, &memory); 339 if (err_is_fail(err)){ 340 USER_PANIC("Deregistering memory from devq failed: %s \n", 341 err_getstring(err)); 342 } 343 344 printf("Starting randomized test debug\n"); 345 que = (struct devq*) null_q[i]; 346 347 test_register(); 348 349 err = devq_register(que, memory, ®id); 350 if (err_is_fail(err)){ 351 USER_PANIC("Registering memory to devq failed \n"); 352 } 353 354 test_randomized_test(); 355 356 dump_results_nfs(name, true); 357 358 sprintf(name, "Null %d", i+2); 359 360 // stack null queue on top 361 err = null_create(&null_q[i+1], (struct devq*) null_q[i]); 362 if (err_is_fail(err)) { 363 USER_PANIC("Allocating null q failed \n"); 364 } 365 366 } 367 printf("SUCCESS! \n");; 368 369} 370 371