1/** 2 * \file 3 * \brief Phase-change scalability benchmark 4 */ 5 6/* 7 * Copyright (c) 2009, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdio.h> 16#include <barrelfish/barrelfish.h> 17#include <barrelfish/waitset.h> 18#include <barrelfish/resource_ctrl.h> 19#include <barrelfish/sys_debug.h> 20#include <bench/bench.h> 21 22struct workcnt { 23 uint64_t cnt; 24} __attribute__ ((aligned (64))); 25 26static const char *my_manifest = 27 "B 1\n" // Normal phase 28 "B 1\n"; // Other normal phase 29 30static int init_done = 1; 31static rsrcid_t my_rsrc_id; 32static struct thread_sem init_sem = THREAD_SEM_INITIALIZER; 33static struct thread_mutex init_lock = THREAD_MUTEX_INITIALIZER; 34static struct thread_cond init_cond = THREAD_COND_INITIALIZER; 35static struct workcnt workcnt[MAX_CPUS]; 36 37static int remote_init(void *arg) 38{ 39 errval_t err = rsrc_join(my_rsrc_id); 40 assert(err_is_ok(err)); 41 42 thread_mutex_lock(&init_lock); 43 thread_sem_post(&init_sem); 44 thread_cond_wait(&init_cond, &init_lock); 45 thread_mutex_unlock(&init_lock); 46 47 for(;;) { 48 workcnt[disp_get_core_id()].cnt++; 49 } 50 51 return 0; 52} 53 54static void domain_spanned(void *arg, errval_t reterr) 55{ 56 assert(err_is_ok(reterr)); 57 init_done++; 58} 59 60int main(int argc, char *argv[]) 61{ 62 int my_core_id = disp_get_core_id(); 63 errval_t err; 64 uint64_t tscperms; 65 66 if(argc < 4) { 67 printf("Usage: %s threads phase-delay timeout\n", argv[0]); 68 } 69 int nthreads = atoi(argv[1]); 70 int delay = atoi(argv[2]); 71 int timeout = atoi(argv[3]); 72 73 err = sys_debug_get_tsc_per_ms(&tscperms); 74 assert(err_is_ok(err)); 75 76 bench_init(); 77 78 // Submit manifest (derived from program) 79 err = rsrc_manifest(my_manifest, &my_rsrc_id); 80 81 /* Span domain to all cores */ 82 for (int i = my_core_id + 1; i < nthreads + my_core_id; i++) { 83 err = domain_new_dispatcher(i, domain_spanned, NULL); 84 if (err_is_fail(err)) { 85 DEBUG_ERR(err, "failed to span domain"); 86 } 87 assert(err_is_ok(err)); 88 } 89 90 while(init_done < nthreads) { 91 thread_yield(); 92 } 93 94 for (int i = my_core_id + 1; i < nthreads + my_core_id; i++) { 95 err = domain_thread_create_on(i, remote_init, NULL, NULL); 96 assert(err_is_ok(err)); 97 thread_sem_wait(&init_sem); 98 } 99 100 thread_mutex_lock(&init_lock); 101 thread_cond_broadcast(&init_cond); 102 thread_mutex_unlock(&init_lock); 103 104 // Run benchmark 105 bool flip = false; 106 cycles_t begin = bench_tsc(), end = 0; 107 for(;;) { 108 if(delay != 0) { 109 flip = !flip; 110 err = rsrc_phase(my_rsrc_id, flip ? 1 : 0); 111 assert(err_is_ok(err)); 112 end = bench_tsc(); 113 } 114 115 // Let it cool down 116 do { 117 workcnt[disp_get_core_id()].cnt++; 118 119 // Stop when timeout is reached 120 if(bench_tsc() >= begin + (timeout * tscperms)) { 121 goto out; 122 } 123 } while(bench_tsc() < end + (delay * tscperms)); 124 } 125 126 out: 127 for(int i = 0; i < nthreads; i++) { 128 printf("workcnt %d: %lu\n", i, workcnt[i].cnt); 129 } 130 printf("number of threads: %d, delay: %d\n", nthreads, delay); 131 printf("client done.\n"); 132 return 0; 133} 134