1/** 2 * \file 3 * \brief Test spanning of domains across cores 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, 2010, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdio.h> 16#include <string.h> 17#include <barrelfish/barrelfish.h> 18#include <barrelfish/dispatch.h> 19#include <trace/trace.h> 20#include <trace_definitions/trace_defs.h> 21 22 23#define LOCKDEC(x) spinlock_t x; 24#define LOCK(x) acquire_spinlock(&x) 25#define UNLOCK(x) release_spinlock(&x) 26 27#define BARDEC(x) \ 28 struct { \ 29 volatile uint32_t counter; \ 30 volatile int cycle; \ 31 } x; 32 33#define BARINIT(x,y) \ 34 x.counter = 0; \ 35 x.cycle = 0; 36 37#define NEWBARRIER(x,y) { \ 38 int cycle = x.cycle; \ 39 if (__sync_fetch_and_add(&x.counter, 1) == (y-1)) { \ 40 x.counter = 0; \ 41 x.cycle = !x.cycle; \ 42 } else { \ 43 while (cycle == x.cycle); \ 44 } \ 45 } 46 47#define BARRIER(x,y) { \ 48 int cycle = x.cycle; \ 49 if (__sync_fetch_and_add(&x.counter, 1) == (y-1)) { \ 50 x.counter = 0; \ 51 x.cycle = !cycle; \ 52 } else { \ 53 while (cycle == x.cycle); \ 54 } \ 55 } 56 57static uint64_t times[32]; 58 59int null(int); 60int malloctest(int); 61int printftest(int); 62int locktest1(int); 63int locktest4(int); 64int inctest1(int); 65int inctest4(int); 66int bartest1(int); 67int bartest4(int); 68 69int null(int arg) 70{ 71 72 return 0; 73} 74 75extern size_t terminal_write(const char *data, size_t length); 76 77static int sysprinttest(int arg) 78{ 79 char out = 'A'+arg; 80 for(int i=0; i<1<<10; i++) { 81 sys_print(&out, 1); 82 } 83 return 0; 84} 85static int termwritetest(int arg) 86{ 87 char out = 'A'+arg; 88 for(int i=0; i<1<<10; i++) { 89 terminal_write(&out, 1); 90 } 91 return 0; 92} 93 94int printftest(int arg) 95{ 96 char msg[2]; 97 msg[0] = 'A'+arg; 98 msg[1] = 0; 99 for(int i=0; i<1<<10; i++) { 100 printf("%s", msg); 101 } 102 return 0; 103} 104 105int malloctest(int arg) 106{ 107 for(int i=0; i<1<<10; i++) { 108 if (arg==1) sys_print(".", 1); 109 void *tmp = malloc(i); 110 free(tmp); 111 } 112 return 0; 113} 114 115LOCKDEC(spinlock); 116static uint64_t gcount = 0; 117 118int locktest1(int arg) 119{ 120 for(int i=0; i<1<<20; i++) { 121 LOCK(spinlock); 122 gcount++; 123 UNLOCK(spinlock); 124 } 125 return 0; 126} 127int locktest4(int arg) 128{ 129 for(int i=0; i<1<<20; i++) { 130 LOCK(spinlock); 131 gcount++; 132 UNLOCK(spinlock); 133 LOCK(spinlock); 134 gcount++; 135 UNLOCK(spinlock); 136 LOCK(spinlock); 137 gcount++; 138 UNLOCK(spinlock); 139 LOCK(spinlock); 140 gcount++; 141 UNLOCK(spinlock); 142 } 143 return 0; 144} 145 146static uint32_t atomiccounter = 0; 147 148int inctest1(int arg) 149{ 150 for(int i=0; i<1<<20; i++) { 151 __sync_fetch_and_add(&atomiccounter, 1); 152 } 153 return 0; 154} 155 156int inctest4(int arg) 157{ 158 uint64_t lcount = 0; 159 char msg[128]; 160 for(int i=0; i<1<<20; i++) { 161 lcount++; 162 __sync_fetch_and_add(&atomiccounter, 1); 163 lcount++; 164 __sync_fetch_and_add(&atomiccounter, 1); 165 lcount++; 166 __sync_fetch_and_add(&atomiccounter, 1); 167 lcount++; 168 __sync_fetch_and_add(&atomiccounter, 1); 169 } 170 sprintf(msg, "%"PRIuCOREID": Count %"PRIx64" %p\n", disp_get_core_id(), lcount, &lcount); 171 sys_print(msg, strlen(msg)); 172 return 0; 173} 174 175BARDEC(barrier); 176uint32_t NPROC = 0; 177 178int bartest1(int arg) 179{ 180 uint64_t count = 0; 181 char msg[128]; 182 183 for(int i=0; i<1<<20; i++) { 184 BARRIER(barrier, NPROC); 185 count++; 186 } 187 // Take address of count to prevent optimisation 188 sprintf(msg, "%"PRIuCOREID": Count %"PRIx64" %p\n", disp_get_core_id(), count, &count); 189 sys_print(msg, strlen(msg)); 190 return 0; 191} 192 193int bartest4(int arg) 194{ 195 uint64_t count = 0; 196 char msg[128]; 197 for(int i=0; i<1<<20; i++) { 198 BARRIER(barrier, NPROC); 199 count++; 200 BARRIER(barrier, NPROC); 201 count++; 202 BARRIER(barrier, NPROC); 203 count++; 204 BARRIER(barrier, NPROC); 205 count++; 206 } 207 // Take address of count to prevent optimisation 208 sprintf(msg, "%"PRIuCOREID": Count %"PRIx64" %p\n", disp_get_core_id(), count, &count); 209 sys_print(msg, strlen(msg)); 210 return 0; 211} 212 213static struct thread_mutex print_mutex = THREAD_MUTEX_INITIALIZER; 214 215static int mutextest(int arg) 216{ 217 for(int i = 0; i < 100000; i++) { 218 thread_mutex_lock(&print_mutex); 219 printf("%"PRIuCOREID": test_thread %d\n", disp_get_core_id(), i); 220 thread_mutex_unlock(&print_mutex); 221 } 222 223 return 0; 224} 225 226static int remote(void *dummy) 227{ 228 uint64_t time = rdtsc(); 229 int core = disp_get_core_id(); 230 times[core] = time; 231 printf("remote running on %d after %"PRIu64"\n", core, time-times[0]); 232 233 if (core == 1) sys_print("Null\n", 5); 234 BARRIER(barrier, NPROC); 235 //sys_print("*", 1); 236 null(core); 237 238 if (core == 1) sys_print("sys_print\n", 10); 239 BARRIER(barrier, NPROC); 240 sysprinttest(core); 241 BARRIER(barrier, NPROC); 242 243 if (core == 1) sys_print("terminal_write\n", 15); 244 BARRIER(barrier, NPROC); 245 termwritetest(core); 246 BARRIER(barrier, NPROC); 247 248 if (core == 1) sys_print("printf\n", 7); 249 BARRIER(barrier, NPROC); 250 printftest(core); 251 BARRIER(barrier, NPROC); 252 253 if (core == 1) sys_print("malloc\n", 7); 254 BARRIER(barrier, NPROC); 255 malloctest(core); 256 BARRIER(barrier, NPROC); 257 258 if (core == 1) printf("\nlocktest1\n"); 259 gcount = 0; 260 261 BARRIER(barrier, NPROC); 262 locktest1(core); 263 BARRIER(barrier, NPROC); 264 265 if (core == 1) { 266 printf("gcount %"PRIx64"\n", gcount); 267 gcount = 0; 268 printf("locktest4\n"); 269 } 270 271 BARRIER(barrier, NPROC); 272 locktest4(core); 273 BARRIER(barrier, NPROC); 274 275 if (core == 1) printf("gcount %"PRIx64"\n", gcount); 276 277 if (core == 1) printf("inctest1\n"); 278 atomiccounter = 0; 279 280 BARRIER(barrier, NPROC); 281 inctest1(core); 282 BARRIER(barrier, NPROC); 283 284 if (core == 1) { 285 printf("count %"PRIx32"\n", atomiccounter); 286 atomiccounter = 0; 287 printf("inctest4\n"); 288 } 289 290 BARRIER(barrier, NPROC); 291 inctest4(core); 292 BARRIER(barrier, NPROC); 293 294 if (core == 1) { 295 printf("count %"PRIx32"\n", atomiccounter); 296 atomiccounter = 0; 297 printf("bartest1\n"); 298 } 299 BARRIER(barrier, NPROC); 300 bartest1(core); 301 BARRIER(barrier, NPROC); 302 303 if (core == 1) printf("bartest4\n"); 304 305 BARRIER(barrier, NPROC); 306 bartest4(core); 307 BARRIER(barrier, NPROC); 308 309 if (core == 1) printf("mutextest\n"); 310 311 BARRIER(barrier, NPROC); 312 mutextest(core); 313 BARRIER(barrier, NPROC); 314 315 if (core == 1) printf("Done\n"); 316 317 return 0; 318} 319 320int ndispatchers = 1; 321 322static void domain_spanned_callback(void *arg, errval_t err) 323{ 324 //sys_print("D", 1); 325 ndispatchers++; 326} 327 328int main(int argc, char *argv[]) 329{ 330 errval_t err; 331 if (argc != 2) { 332 printf("Usage %s: <Num additional threads>\n", argv[0]); 333 exit(-1); 334 } 335 336 337 printf("main running on %d\n", disp_get_core_id()); 338 339 int cores = strtol(argv[1], NULL, 10) + 1; 340 341 NPROC = cores -1; 342 BARINIT(barrier, NPROC); 343 344 uint64_t before = rdtsc(); 345 times[0] = before; 346 347 trace_event(TRACE_SUBSYS_BENCH, TRACE_EVENT_BENCH_PCBENCH, 1); 348 for (int i = 1; i < cores; i++) { 349 printf("spantest: spanning to core %" PRIuCOREID "\n", i); 350 err = domain_new_dispatcher(i + disp_get_core_id(), 351 domain_spanned_callback, 352 (void*)(uintptr_t)i); 353 if (err_is_fail(err)) { 354 USER_PANIC_ERR(err, "domain_new_dispatcher failed"); 355 } 356 } 357 358 while (ndispatchers < cores) { 359 thread_yield(); 360 } 361 uint64_t finish = rdtsc(); 362 363 trace_event(TRACE_SUBSYS_BENCH, TRACE_EVENT_BENCH_PCBENCH, 0); 364 365 //sys_print("\nDone\n", 6); 366 printf("spantest: Done in %"PRIu64" cycles\n", finish-before); 367 368 //trace_dump(); 369 370 for(int i = 1; i < cores; i++) { 371 printf("spantest: create thread oncore %" PRIuCOREID "\n", i); 372 err = domain_thread_create_on(i, remote, NULL, NULL); 373 assert(err_is_ok(err)); 374 } 375 376 messages_handler_loop(); 377 return 0; 378} 379