1/** 2 * \file 3 * \brief Distributed (percore) memory server: code specific to THC version 4 */ 5 6/* 7 * Copyright (c) 2007-2011, 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 <stdlib.h> 16#include <stdio.h> 17#include <string.h> 18#include <getopt.h> 19 20#include <inttypes.h> 21#include <barrelfish/barrelfish.h> 22#include <barrelfish/dispatch.h> 23#include <trace/trace.h> 24#include <trace_definitions/trace_defs.h> 25#include <barrelfish/monitor_client.h> 26#include <dist/barrier.h> 27 28#include <thc/thc.h> 29#include <thc/thcsync.h> 30 31#include <if/mem_defs.h> 32#include <if/mem_defs.h> 33#include <if/mem_thc.h> 34#include <if/monitor_defs.h> 35 36// #include "barrier.h" 37 38#include "mem_serv.h" 39#include "steal.h" 40 41// The various request handler functions 42 43static void percore_free_handler(struct mem_thc_service_binding_t *sv, 44 struct capref ramcap, genpaddr_t base, 45 uint8_t bits) 46{ 47 errval_t ret; 48 ret = percore_free_handler_common(ramcap, base, bits); 49 sv->send.free_monitor(sv, ret); 50} 51 52static void mem_available_handler(struct mem_thc_service_binding_t *sv) 53{ 54 memsize_t mem_available; 55 mem_available = mem_available_handler_common(); 56 sv->send.available(sv, mem_available); 57} 58 59 60static void percore_steal_handler(struct mem_thc_service_binding_t *sv, 61 uint8_t bits, 62 genpaddr_t minbase, genpaddr_t maxlimit) 63{ 64 errval_t ret; 65 struct capref cap; 66 ret = percore_steal_handler_common(bits, minbase, maxlimit, &cap); 67 sv->send.steal(sv, ret, cap); 68 69 trace_event(TRACE_SUBSYS_MEMSERV, TRACE_EVENT_MEMSERV_PERCORE_ALLOC_COMPLETE, 0); 70 71} 72 73static void percore_allocate_handler(struct mem_thc_service_binding_t *sv, 74 uint8_t bits, 75 genpaddr_t minbase, genpaddr_t maxlimit) 76{ 77 errval_t ret; 78 struct capref cap; 79 ret = percore_allocate_handler_common(bits, minbase, maxlimit, &cap); 80 sv->send.allocate(sv, ret, cap); 81 if(!capref_is_null(cap)) { 82 ret = cap_delete(cap); 83 if(err_is_fail(ret)) { 84 DEBUG_ERR(err, "cap_delete after send. This memory will leak."); 85 } 86 } 87 88 trace_event(TRACE_SUBSYS_MEMSERV, TRACE_EVENT_MEMSERV_PERCORE_ALLOC_COMPLETE, 0); 89} 90 91// Various startup procedures 92 93static void run_server(struct mem_thc_service_binding_t *sv) 94{ 95 mem_service_msg_t msg; 96 bool loop = true; 97 98 // this is the bitmap of messages we are interested in receiving 99 struct mem_service_selector selector = { 100 .allocate = 1, 101 .available = 1, 102 .free = 1, 103 .steal = 1, 104 }; 105 106 while (loop) { 107 // receive any message 108 sv->recv_any(sv, &msg, selector); 109 110 // dispatch it 111 switch(msg.msg) { 112 case mem_allocate: 113 percore_allocate_handler(sv, msg.args.allocate.in.bits, 114 msg.args.allocate.in.minbase, 115 msg.args.allocate.in.maxlimit); 116 break; 117 case mem_steal: 118 percore_steal_handler(sv, msg.args.allocate.in.bits, 119 msg.args.allocate.in.minbase, 120 msg.args.allocate.in.maxlimit); 121 break; 122 case mem_available: 123 mem_available_handler(sv); 124 break; 125 case mem_free_monitor: 126 percore_free_handler(sv, msg.args.free.in.mem_cap); 127 break; 128 default: 129 debug_printf("unexpected message: %d\n", msg.msg); 130 loop = false; 131 break; 132 } 133 } 134} 135 136errval_t percore_mem_serv(coreid_t core, coreid_t *cores, 137 int len_cores, memsize_t ram) 138{ 139 errval_t err; 140 141 struct waitset *ws = get_default_waitset(); 142 143 // Init the memory allocator 144 err = initialize_percore_mem_serv(core, cores, len_cores, ram); 145 if (err_is_fail(err)) { 146 DEBUG_ERR(err, "initializing percore mem_serv"); 147 return err; 148 } 149 150 struct mem_thc_export_info e_info; 151 struct mem_thc_service_binding_t *sv; 152 struct mem_binding *b; 153 iref_t iref; 154 155 char service_name[NAME_LEN]; 156 snprintf(service_name, NAME_LEN, "%s.%d", MEMSERV_DIST, core); 157 158 // err = mem_thc_export(&e_info, service_name, ws, 159 err = mem_thc_export(&e_info, NULL, ws, 160 IDC_EXPORT_FLAGS_DEFAULT, 161 &iref); 162 if (err_is_fail(err)) { 163 DEBUG_ERR(err, "exporting percore mem interface"); 164 return err; 165 } 166 167 struct monitor_binding *mb = get_monitor_binding(); 168 err = mb->tx_vtbl. set_mem_iref_request(mb, NOP_CONT, iref); 169 if (err_is_fail(err)) { 170 DEBUG_ERR(err, "setting monitor's percore mem_serv iref"); 171 return err; 172 } 173 174 // explicitly tell spawnd to use us 175 err = set_local_spawnd_memserv(core); 176 if (err_is_fail(err)) { 177 DEBUG_ERR(err, "setting spawnd.%d's local memserv", core); 178 return err; 179 } 180 181 // register only after spawnd's local memserv has been set 182 err = nameservice_register(service_name, iref); 183 if (err_is_fail(err)) { 184 DEBUG_ERR(err, "nameservice_register failed"); 185 return err; 186 } 187 // let the master know we are ready 188 err = nsb_register_n(core, MEMSERV_DIST); 189 if (err_is_fail(err)) { 190 USER_PANIC_ERR(err, "nsb_register_n failed"); 191 } 192 193 194 do { 195 while (true) { 196 197 mem_thc_accept(&e_info, &b); 198 if (err_is_fail(err)) { 199 DEBUG_ERR(err, "thc accept failed"); 200 continue; 201 } 202 203 sv = malloc(sizeof(struct mem_thc_service_binding_t)); 204 if (sv == NULL) { 205 DEBUG_ERR(LIB_ERR_MALLOC_FAIL, "allocating thc service binding"); 206 continue; 207 } 208 209 err = mem_thc_init_service(sv, b, b); 210 if (err_is_fail(err)) { 211 DEBUG_ERR(err, "thc init failed"); 212 continue; 213 } 214 215 async run_server(sv); 216 217 } 218 } finish; 219 220 // should never reach here 221 return SYS_ERR_OK; 222} 223