1/** 2 * \file 3 * \brief Benchmark revoke of cap with no remote relations (no framework) 4 */ 5 6/* 7 * Copyright (c) 2017, 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, Universitaetstr 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <barrelfish/barrelfish.h> 16#include <if/bench_distops_defs.h> 17 18#include <bitmacros.h> 19 20#include <bench/bench.h> 21#include <trace/trace.h> 22 23#include "benchapi.h" 24 25#define REVOKE_COPIES 10 26 27//{{{1 Management node: state management 28 29struct global_state { 30 struct capref ram; 31 int nodecount; 32 int copies_done; 33 int currcopies; 34}; 35 36errval_t mgmt_init_benchmark(void **st, int nodecount) 37{ 38 *st = malloc(sizeof(struct global_state)); 39 if (!*st) { 40 return LIB_ERR_MALLOC_FAIL; 41 } 42 struct global_state *gs = *st; 43 gs->nodecount = nodecount; 44 gs->copies_done = 0; 45 return ram_alloc(&gs->ram, BASE_PAGE_BITS); 46} 47 48struct node_state { 49 struct capref cap; 50 struct capref ram; 51 uint32_t numcopies; 52 struct capref *copies; 53 uint64_t *delcycles; 54 uint32_t benchcount; 55}; 56 57static coreid_t my_core_id = -1; 58 59static void node_create_copies(struct node_state *ns) 60{ 61 errval_t err; 62 ns->copies = calloc(ns->numcopies, sizeof(struct capref)); 63 for (int i = 0; i < ns->numcopies; i++) { 64 err = slot_alloc(&ns->copies[i]); 65 PANIC_IF_ERR(err, "slot_alloc for copy %d\n", i); 66 err = cap_copy(ns->copies[i], ns->ram); 67 PANIC_IF_ERR(err, "cap_copy for copy %d\n", i); 68 } 69} 70 71static size_t get_mdb_size(void) 72{ 73 errval_t err; 74 size_t cap_base_count = 0; 75 err = sys_debug_get_mdb_size(&cap_base_count); 76 assert(err_is_ok(err)); 77 return cap_base_count; 78} 79 80int main(int argc, char *argv[]) 81{ 82 if (argc > 1) { 83 printf("# Benchmarking REVOKE NO REMOTE: nodes=%d\n", atoi(argv[1])); 84 85 printf("# Starting out with %d copies, will double up to %d...\n", 86 NUM_COPIES_START, NUM_COPIES_END); 87 } 88 89 struct global_state *gs; 90 errval_t err; 91 92 // Initialize global state 93 err = mgmt_init_benchmark((void**)&gs, 1); 94 assert(err_is_ok(err)); 95 96 // Initialize tracing 97 err = mgmt_init_tracing(); 98 assert(err_is_ok(err)); 99 100 // Initialize node state 101 struct node_state ns_; 102 struct node_state *ns = &ns_; 103 ns->ram = gs->ram; 104 ns->benchcount = ITERS; 105 ns->delcycles = calloc(ns->benchcount, sizeof(uint64_t)); 106 assert(ns->delcycles); 107 108 my_core_id = disp_get_core_id(); 109 110 bench_init(); 111 112 // allocate slots for copies 113 struct capref copies[REVOKE_COPIES]; 114 for (int c = 0; c < REVOKE_COPIES; c++) { 115 err = slot_alloc(&copies[c]); 116 assert(err_is_ok(err)); 117 } 118 119 TRACE(CAPOPS, START, 0); 120 121 for (gs->currcopies = NUM_COPIES_START; 122 gs->currcopies <= NUM_COPIES_END; 123 gs->currcopies *= 2) 124 { 125 ns->numcopies = gs->currcopies; 126 printf("# node %d: creating %d cap copies\n", my_core_id, ns->numcopies); 127 node_create_copies(ns); 128 printf("# node %d: %zu capabilities on node\n", my_core_id, get_mdb_size()); 129 struct capref cap; 130 err = ram_alloc(&cap, BASE_PAGE_BITS); 131 assert(err_is_ok(err)); 132 // printf("# node %d: starting benchmark iterations\n", my_core_id); 133 for (int i = 0; i < ns->benchcount; i++) { 134 uint64_t start, end; 135 // Make some copies to be deleted during revoke 136 // printf("# node %d: creating copies\n", my_core_id); 137 for (int c = 0; c < REVOKE_COPIES; c++) { 138 err = cap_copy(copies[c], cap); 139 PANIC_IF_ERR(err, "creating copy for revoke"); 140 assert(err_is_ok(err)); 141 } 142 // printf("# node %d: doing revoke\n", my_core_id); 143 start = bench_tsc(); 144 TRACE(CAPOPS, USER_REVOKE_CALL, (ns->numcopies << 16) | i); 145 err = cap_revoke(cap); 146 TRACE(CAPOPS, USER_REVOKE_RESP, (ns->numcopies << 16) | i); 147 end = bench_tsc(); 148 ns->delcycles[i] = end - start; 149 assert(err_is_ok(err)); 150 PANIC_IF_ERR(err, "# core %d: revoke failed", my_core_id); 151 if (i % (ns->benchcount / 10) == 0) { 152 // printf("# node %d: %d percent done\n", my_core_id, i / (ns->benchcount/100)); 153 } 154 } 155 err = cap_destroy(cap); 156 assert(err_is_ok(err)); 157 PANIC_IF_ERR(err, "# core %d: final cap_destroy", my_core_id); 158 159 printf("# node %d: tsc_per_us = %ld; numcopies = %d\n", 160 my_core_id, bench_tsc_per_us(), ns->numcopies); 161 printf("# delete latency in cycles\n"); 162 for (int i = 0; i < ns->benchcount; i++) { 163 printf("%ld\n", ns->delcycles[i]); 164 } 165 // Cleanup before next round 166 for (int i = 0; i < ns->numcopies; i++) { 167 err = cap_destroy(ns->copies[i]); 168 assert(err_is_ok(err)); 169 } 170 free(ns->copies); 171 printf("# Round done!\n"); 172 } 173 174 TRACE(CAPOPS, STOP, 0); 175 mgmt_trace_flush(NOP_CONT); 176 177 // We're not printing this line here, as it's printed from the standalone 178 // runner, that allows us to run single-core benchmarks sequentially on 179 // multiple cores 180 // printf("# Benchmark done!\n"); 181 return 0; 182} 183