static errval_t bind_to_octopus(void) { errval_t err; struct bind_state st = { .done = false }; err = octopus_bind(name_serv_iref, bind_continuation, &st, get_default_waitset(), IDC_BIND_FLAG_RPC_CAP_TRANSFER); while (!st.done) { err = event_dispatch(get_default_waitset()); if (err_is_fail(err)) { DEBUG_ERR(err, "ev_disp in bind_to_octopus"); } } return st.err; } size_t num_monitors_online(void) { errval_t err; struct octopus_rpc_client *r = get_octopus_rpc_client(); if (r == NULL) { err = bind_to_octopus(); if (err_is_fail(err)) { DEBUG_ERR(err, "bind_to_octopus"); debug_printf("no connection to octopus, num_monitors=1\n"); return 1; } r = get_octopus_rpc_client(); } assert(r != NULL); char* buffer = NULL; errval_t error_code; octopus_trigger_id_t tid; char** names = NULL; size_t count = 0; static char* spawnds = "r'spawn.[0-9]+' { iref: _ }"; err = r->vtbl.get_names(r, spawnds, NOP_TRIGGER, &buffer, &tid, &error_code); if (err_is_fail(err) || err_is_fail(error_code)) { err = err_push(err, SPAWN_ERR_FIND_SPAWNDS); goto out; } err = oct_parse_names(buffer, &names, &count); if (err_is_fail(err)) { goto out; } out: free(buffer); oct_free_names(names, count); if (err_is_fail(err)) { DEBUG_ERR(err, "num_spawnds_online"); debug_printf("error in octopus, setting num_monitors=1\n"); return 1; } return count; }
/** * \brief Register with name service * * \param iface Name of interface to register * \param iref IREF to register */ errval_t nameservice_register(const char *iface, iref_t iref) { errval_t err = SYS_ERR_OK; struct octopus_rpc_client *r = get_octopus_rpc_client(); if (r == NULL) { return LIB_ERR_NAMESERVICE_NOT_BOUND; } // Format record static const char* format = "%s { iref: %d }"; size_t len = snprintf(NULL, 0, format, iface, iref); char* record = malloc(len+1); if (record == NULL) { return LIB_ERR_MALLOC_FAIL; } snprintf(record, len+1, format, iface, iref); char* ret = NULL; octopus_trigger_id_t tid; errval_t error_code; err = r->vtbl.set(r, record, 0, NOP_TRIGGER, 0, &ret, &tid, &error_code); if (err_is_fail(err)) { goto out; } err = error_code; out: free(record); return err; }
/** * \brief Retrieve interface references for incoming and outgoing characters * as well as for configuration messages from octopus. */ static errval_t get_irefs(struct capref session_id, iref_t *in_iref, iref_t *out_iref, iref_t *conf_iref) { errval_t err; struct octopus_rpc_client *r = get_octopus_rpc_client(); assert(r != NULL); char *record; errval_t error_code; octopus_trigger_id_t tid; err = r->vtbl.get_with_idcap(r, session_id, NOP_TRIGGER, &record, &tid, &error_code); if (err_is_fail(err)) { err_push(err, TERM_ERR_LOOKUP_SESSION_RECORD); goto out; } err = error_code; if (err_is_fail(err)) { err_push(err, TERM_ERR_LOOKUP_SESSION_RECORD); goto out; } TERM_DEBUG("Record retrieved from octopus: %s\n", record); int64_t session_oct; int64_t in_oct; int64_t out_oct; int64_t conf_oct; // oct_read can only parse 64-bit values, we need to parse the irefs as 64bit // then cast to 32bit err = oct_read(record, "_ { session_iref: %d, in_iref: %d, out_iref: %d, " "conf_iref: %d }", &session_oct, &in_oct, &out_oct, &conf_oct); //iref_t session_iref = (iref_t)session_oct; *in_iref = (iref_t)in_oct; *out_iref = (iref_t)out_oct; *conf_iref = (iref_t)conf_oct; if (err_is_fail(err)) { err_push(err, TERM_ERR_PARSE_SESSION_RECORD); goto out; } if ((*in_iref == NULL_IREF) || (*out_iref == NULL_IREF) || (*conf_iref == NULL_IREF)) { err = TERM_ERR_PARSE_SESSION_RECORD; goto out; } TERM_DEBUG("Retrieved interface references from octopus. in_iref: %" PRIuIREF ", out_iref: %" PRIuIREF ", conf_iref: %" PRIuIREF "\n", *in_iref, *out_iref, *conf_iref); out: free(record); return err; }
/** * \brief Retrieve interface references for incoming and outgoing characters * as well as for configuration messages from octopus. */ static errval_t get_irefs(struct capref session_id, iref_t *in_iref, iref_t *out_iref, iref_t *conf_iref) { errval_t err; struct octopus_rpc_client *r = get_octopus_rpc_client(); assert(r != NULL); char *record; errval_t error_code; octopus_trigger_id_t tid; err = r->vtbl.get_with_idcap(r, session_id, NOP_TRIGGER, &record, &tid, &error_code); if (err_is_fail(err)) { err_push(err, TERM_ERR_LOOKUP_SESSION_RECORD); goto out; } err = error_code; if (err_is_fail(err)) { err_push(err, TERM_ERR_LOOKUP_SESSION_RECORD); goto out; } TERM_DEBUG("Record retrieved from octopus: %s\n", record); iref_t session_iref; err = oct_read(record, "_ { session_iref: %d, in_iref: %d, out_iref: %d, " "conf_iref: %d }", &session_iref, in_iref, out_iref, conf_iref); if (err_is_fail(err)) { err_push(err, TERM_ERR_PARSE_SESSION_RECORD); goto out; } if ((*in_iref == NULL_IREF) || (*out_iref == NULL_IREF) || (*conf_iref == NULL_IREF)) { err = TERM_ERR_PARSE_SESSION_RECORD; goto out; } TERM_DEBUG("Retrieved interface references from octopus. in_iref: %" PRIuIREF ", out_iref: %" PRIuIREF ", conf_iref: %" PRIuIREF "\n", *in_iref, *out_iref, *conf_iref); out: free(record); return err; }
/** * \brief registers a found symbol with octopus for later retrieval * * \param binary the name of the binary * \param idx index of the symbol to insert * \param symname name of the symbol to insert * \param address address of the sybol to insert * * \returns SYS_ERR_OK on success * errval on error */ errval_t spawn_symval_register(const char *binary, uint32_t idx, const char *symname, genvaddr_t address) { errval_t err = SYS_ERR_OK; struct octopus_rpc_client *r = get_octopus_rpc_client(); if (r == NULL) { return LIB_ERR_NAMESERVICE_NOT_BOUND; } if (symname[0] == '_') { symname++; } // Format record static const char* format = "%s.omp.%u { sym: %s, addr: %d }"; size_t len = snprintf(NULL, 0, format, binary, idx, symname, address); char* record = malloc(len + 1); if (record == NULL) { return LIB_ERR_MALLOC_FAIL; } snprintf(record, len + 1, format, binary, idx, symname, address); // transform to lower case for (int i = 0; i < len; ++i) { if (record[i] >= 'A' && record[i] <= 'Z') { record[i] -= ('A' - 'a'); } } char* ret = NULL; octopus_trigger_id_t tid; errval_t error_code; err = r->vtbl.set(r, record, 0, NOP_TRIGGER, 0, &ret, &tid, &error_code); if (err_is_fail(err)) { goto out; } err = error_code; out: free(record); return err; }
/** * \brief Non-blocking name service lookup * * \param iface Name of the domain * \param retdomid returns the Xeon Phi Domain ID */ errval_t domain_lookup(const char *iface, xphi_dom_id_t *retdomid) { errval_t err; struct octopus_rpc_client *r = get_octopus_rpc_client(); if (r == NULL) { return LIB_ERR_NAMESERVICE_NOT_BOUND; } char* record = NULL; octopus_trigger_id_t tid; errval_t error_code; err = r->vtbl.get(r, iface, NOP_TRIGGER, &record, &tid, &error_code); if (err_is_fail(err)) { goto out; } err = error_code; if (err_is_fail(err)) { if (err_no(err) == OCT_ERR_NO_RECORD) { err = err_push(err, XEON_PHI_ERR_CLIENT_DOMAIN_VOID); } goto out; } xphi_dom_id_t domid = 0; err = oct_read(record, "_ { domid: %d }", &domid); if (err_is_fail(err) || domid == 0) { err = err_push(err, XEON_PHI_ERR_CLIENT_DOMAIN_VOID); goto out; } if (retdomid != NULL) { *retdomid = domid; } out: free(record); return err; }
/** * \brief Non-blocking name service lookup * * \param iface Name of interface for which to query name server * \param retiref Returns pointer to IREF on success */ errval_t nameservice_lookup(const char *iface, iref_t *retiref) { errval_t err; struct octopus_rpc_client *r = get_octopus_rpc_client(); if (r == NULL) { return LIB_ERR_NAMESERVICE_NOT_BOUND; } char* record = NULL; octopus_trigger_id_t tid; errval_t error_code; err = r->vtbl.get(r, iface, NOP_TRIGGER, &record, &tid, &error_code); if (err_is_fail(err)) { goto out; } err = error_code; if (err_is_fail(err)) { if (err_no(err) == OCT_ERR_NO_RECORD) { err = err_push(err, LIB_ERR_NAMESERVICE_UNKNOWN_NAME); } goto out; } uint64_t iref_number = 0; err = oct_read(record, "_ { iref: %d }", &iref_number); if (err_is_fail(err) || iref_number == 0) { err = err_push(err, LIB_ERR_NAMESERVICE_INVALID_NAME); goto out; } if (retiref != NULL) { *retiref = iref_number; } out: free(record); return err; }
/** * \brief executes a lookup query on octopus to obtain the symbol * * \param binary name of the binary to query * \param idx index of the symbol to query * \param ret_name returns the name of the symbol * \param ret_addr returns the address of the symbol * * \return */ errval_t spawn_symval_lookup(const char *binary, uint32_t idx, char **ret_name, genvaddr_t *ret_addr) { errval_t err; size_t len; len = snprintf(NULL, 0, "%s.omp.%"PRIu32, binary, idx); char *omp_entry = malloc(len+1); if (omp_entry == NULL) { return LIB_ERR_MALLOC_FAIL; } snprintf(omp_entry, len+1, "%s.omp.%"PRIu32, binary, idx); struct octopus_rpc_client *r = get_octopus_rpc_client(); if (r == NULL) { return LIB_ERR_NAMESERVICE_NOT_BOUND; } // transform to lower case for (int i = 0; i < len; ++i) { if (omp_entry[i] >= 'A' && omp_entry[i] <= 'Z') { omp_entry[i] -= ('A' - 'a'); } } char* record = NULL; octopus_trigger_id_t tid; errval_t error_code; err = r->vtbl.get(r, omp_entry, NOP_TRIGGER, &record, &tid, &error_code); if (err_is_fail(err)) { goto out; } err = error_code; if (err_is_fail(err)) { if (err_no(err) == OCT_ERR_NO_RECORD) { err = err_push(err, LIB_ERR_NAMESERVICE_UNKNOWN_NAME); } goto out; } uint64_t addr = 0; char *symname = NULL; err = oct_read(record, "_ { sym: %s, addr: %d }", &symname, &addr); if (err_is_fail(err) || symname == NULL) { err = err_push(err, LIB_ERR_NAMESERVICE_INVALID_NAME); goto out; } if (ret_addr != NULL) { *ret_addr = addr; } if (ret_name != NULL) { *ret_name = strdup(symname); } out: free(record); free(omp_entry); return err; }