1/** 2 * \file 3 * \brief Bfscope (trace server) support for the monitor. 4 */ 5 6/* 7 * Copyright (c) 2012 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 <barrelfish/barrelfish.h> 16#include <barrelfish/nameservice_client.h> 17#include <barrelfish/event_queue.h> 18#include <trace/trace.h> 19#include <sys/time.h> 20#include "monitor.h" 21 22struct bfscope_flush_state 23{ 24 struct intermon_binding *ib; 25 iref_t iref; 26}; 27 28struct bfscope_ack_state 29{ 30 struct intermon_binding* to_initiator_binding; 31}; 32 33struct notify_bfscope_state 34{ 35 struct monitor_binding *monitor_binding; 36 struct event_queue_node qnode; 37}; 38 39// --------- Global variables 40 41// Monitor binding to the process that initiated the trace_start 42static struct monitor_binding *requester_monitor_binding = NULL; 43 44// Intermonitor binding between monitor on the core that initiated the flush request 45// and monitor on the core that runs bfscope 46static struct intermon_binding *requester_intermon_binding = NULL; 47 48// ---------- 49 50//----------- 51// Receiving a flush ack message from bfscope 52//----------- 53 54static void bfscope_intermon_flush_ack_continue(void *arg); 55static void bfscope_intermon_flush_forward_handler(struct intermon_binding *imb, iref_t iref); 56static void bfscope_intermon_flush_ack(struct intermon_binding *ib); 57 58/* 59 * We received a message from bfscope, telling us that the flushing has been 60 * completed. 61 * 62 * So let's forward this information to the initiator. 63 */ 64static void bfscope_monitor_flush_ack_handler(struct monitor_binding *mb) 65{ 66 if(requester_intermon_binding == NULL) { 67 // The initiator and bfscope run on the same core, do no intermon communication 68 69 bfscope_intermon_flush_ack(NULL); 70 return; 71 } 72 73 struct bfscope_ack_state *state = malloc(sizeof (struct bfscope_ack_state)); 74 state->to_initiator_binding = requester_intermon_binding; 75 76 requester_intermon_binding = NULL; 77 78 bfscope_intermon_flush_ack_continue(state); 79} 80 81// ------- 82 83static void bfscope_monitor_flush_send_continue(void* arg) 84{ 85 86 struct bfscope_flush_state *state = (struct bfscope_flush_state*) arg; 87 88 assert(state->ib != NULL); 89 90 // Send the intermonitor message 91 errval_t err; 92 err = state->ib->tx_vtbl.bfscope_flush_send_forward(state->ib, MKCONT(free, state), state->iref); 93 94 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) { 95 // Sending failed, must be repeated for this core 96 err = state->ib->register_send(state->ib, state->ib->waitset, MKCONT(&bfscope_monitor_flush_send_continue, state)); 97 assert(err_is_ok(err)); 98 } else if(err_is_fail(err)) { 99 //TODO: Error handling 100 USER_PANIC_ERR(err, "Could not broadcast trace_monitor_broadcast_start_continue"); 101 } else { 102 // Everything was ok, do nothing. 103 } 104 105} 106 107/* 108 * This function is called on the monitor that initiated the "trace_flush" command. 109 * 110 * Let's forward the message to the core on which bfscope is running. 111 */ 112static void bfscope_monitor_flush_send_handler(struct monitor_binding *mb, iref_t iref) 113{ 114 //printf("bfscope_monitor_flush_send_handler\n"); 115 116 requester_monitor_binding = mb; 117 118 struct bfscope_flush_state *state = malloc(sizeof(struct bfscope_flush_state)); 119 state->iref = iref; 120 121 // Get the coreid on which bfscope is running 122 coreid_t coreid; 123 errval_t err = iref_get_core_id(iref, &coreid); 124 if (err_is_fail(err)) { 125 USER_PANIC_ERR(err, "iref_get_core_id for bfscope failed"); 126 } 127 128 //printf("bfscope runs on core: %d\n", coreid); 129 130 if(coreid == my_core_id) { 131 //printf("bfscope runs on the same core as the initiator of the flush request\n"); 132 133 // we don't need the state in this case 134 free(state); 135 // Send message to bfscope directly 136 bfscope_intermon_flush_forward_handler(NULL, iref); 137 return; 138 } 139 140 err = intermon_binding_get(coreid, &state->ib); 141 142 if(err_is_fail(err)) { 143 USER_PANIC_ERR(err, "intermon_binding_get failed"); 144 } 145 146 bfscope_monitor_flush_send_continue(state); 147} 148 149 150/* 151 * This function is called on the monitor on which the initiator of the flush 152 * message is running, once the flush has been performed and the ack has been 153 * received. 154 */ 155static void bfscope_monitor_flush_finished_successfully(void *arg) 156{ 157 // Reset the global state 158 159 requester_monitor_binding = NULL; 160} 161 162static void bfscope_intermon_flush_ack_continue(void* arg) 163{ 164 struct bfscope_ack_state *state = (struct bfscope_ack_state*) arg; 165 struct intermon_binding *intermon_binding = state->to_initiator_binding; 166 167 errval_t err; 168 169 err = intermon_binding->tx_vtbl.bfscope_flush_ack_forward(intermon_binding, MKCONT(free, state)); 170 171 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) { 172 err = intermon_binding->register_send(intermon_binding, intermon_binding->waitset, MKCONT(&bfscope_intermon_flush_ack_continue, state)); 173 assert(err_is_ok(err)); 174 } else if(err_is_fail(err)) { 175 //TODO: Error handling 176 USER_PANIC_ERR(err, "Could not forward ack in bfscope_intermon_flush_ack_continue"); 177 } else { 178 // Everything was ok, do nothing. 179 } 180} 181 182static void bfscope_send_flush_msg_to_bfscope(void* arg) 183{ 184 errval_t err; 185 186 struct notify_bfscope_state *state = (struct notify_bfscope_state*) arg; 187 struct monitor_binding *monitor_binding = state->monitor_binding; 188 189 err = monitor_binding->tx_vtbl.bfscope_flush_send(monitor_binding, MKCONT(free, state), 0); 190 191 if (err_is_ok(err)) { 192 event_mutex_unlock(&monitor_binding->mutex); 193 } else if (err_no(err) == FLOUNDER_ERR_TX_BUSY) { 194 err = monitor_binding->register_send(monitor_binding, monitor_binding->waitset, MKCONT(&bfscope_send_flush_msg_to_bfscope, state)); 195 assert(err_is_ok(err)); 196 } else { 197 event_mutex_unlock(&monitor_binding->mutex); 198 //TODO: Error handling 199 USER_PANIC_ERR(err, "Could not send flush message to bfscope"); 200 } 201} 202 203/* 204 * The flush message has received on the monitor where bfscope is running. 205 * 206 * Let's Notify bfscope about the flush request. 207 */ 208static void bfscope_intermon_flush_forward_handler(struct intermon_binding *imb, iref_t iref) 209{ 210 //printf("bfscope_intermon_flush_forward_handler on core %d.\n", my_core_id); 211 212 // Store the intermonitor binding so that we can later reply 213 requester_intermon_binding = imb; 214 215 // Notify bfscope 216 217 struct notify_bfscope_state *state = malloc(sizeof(struct notify_bfscope_state)); 218 //memset(state, 0, sizeof(struct trace_broadcast_start_state)); 219 220 // Get the monitor binding to bfscope 221 errval_t err = iref_get_binding(iref, &state->monitor_binding); 222 if(err_is_fail(err)) { 223 USER_PANIC_ERR(err, "iref_get_binding for bfscope failed"); 224 } 225 // Send the message to bfscope 226 event_mutex_enqueue_lock(&state->monitor_binding->mutex, &state->qnode, MKCLOSURE(&bfscope_send_flush_msg_to_bfscope, state)); 227 228} 229 230static void bfscope_monitor_flush_forward_ack_to_requester(void *arg) 231{ 232 233 assert(requester_monitor_binding != NULL); 234 235 errval_t err; 236 237 err = requester_monitor_binding->tx_vtbl.bfscope_flush_ack(requester_monitor_binding, MKCONT(bfscope_monitor_flush_finished_successfully, NULL)); 238 239 if(err_no(err) == FLOUNDER_ERR_TX_BUSY) { 240 err = requester_monitor_binding->register_send(requester_monitor_binding, 241 requester_monitor_binding->waitset, MKCONT(&bfscope_monitor_flush_forward_ack_to_requester, NULL)); 242 assert(err_is_ok(err)); 243 } else if(err_is_fail(err)) { 244 //TODO: Error handling 245 USER_PANIC_ERR(err, "Could not reply to flush bfscope_monitor_flush_forward_ack_to_requester"); 246 } else { 247 // Everything was ok, do nothing. 248 } 249} 250 251// This function is automatically called when the initiating monitor receives an ack from another monitor 252static void bfscope_intermon_flush_ack(struct intermon_binding *ib) 253{ 254 //printf("bfscope_intermon_flush_ack\n"); 255 256 bfscope_monitor_flush_forward_ack_to_requester(NULL); 257} 258 259//------------------------------------------------------------------------------ 260// Message Table Initialization 261//------------------------------------------------------------------------------ 262 263 264// set up receive vtable in the intermonitor interface 265errval_t bfscope_intermon_init(struct intermon_binding *ib) 266{ 267 ib->rx_vtbl.bfscope_flush_send_forward = &bfscope_intermon_flush_forward_handler; 268 ib->rx_vtbl.bfscope_flush_ack_forward = &bfscope_intermon_flush_ack; 269 270 return SYS_ERR_OK; 271} 272 273// set up receive vtable in the monitor interface 274errval_t bfscope_monitor_init(struct monitor_binding *mb) 275{ 276 mb->rx_vtbl.bfscope_flush_send = &bfscope_monitor_flush_send_handler; 277 mb->rx_vtbl.bfscope_flush_ack = &bfscope_monitor_flush_ack_handler; 278 279 return SYS_ERR_OK; 280} 281