void retrieve_result__rx(struct intermon_binding *b, errval_t status, uint8_t relations, genvaddr_t st) { errval_t err; struct retrieve_rpc_st *rst = (struct retrieve_rpc_st*)(lvaddr_t)st; if (err_is_fail(status)) { err = status; goto report_error; } err = monitor_domcap_remote_relations(rst->cap.croot, rst->cap.cptr, rst->cap.bits, relations, 0xFF, NULL); PANIC_IF_ERR(err, "setting rrels for retrieved cap"); struct event_closure updated_cont = MKCONT(retrieve_ownership_update__fin, rst); err = capsend_update_owner(rst->cap, updated_cont); PANIC_IF_ERR(err, "updating retrieve ownership"); report_error: retrieve_ownership__rx(err, rst); }
static void revoke_no_remote(struct revoke_master_st *st) { assert(num_monitors_online() == 1); if (!delete_steps_get_waitset()) { delete_steps_init(get_default_waitset()); } errval_t err; DEBUG_CAPOPS("%s\n", __FUNCTION__); // pause deletion steps DEBUG_CAPOPS("%s: delete_steps_pause()\n", __FUNCTION__); delete_steps_pause(); // mark target of revoke DEBUG_CAPOPS("%s: mon_revoke_mark_tgt()\n", __FUNCTION__); err = monitor_revoke_mark_target(st->cap.croot, st->cap.cptr, st->cap.bits); PANIC_IF_ERR(err, "marking revoke"); // resume delete steps DEBUG_CAPOPS("%s: delete_steps_resume()\n", __FUNCTION__); delete_steps_resume(); // wait on delete queue, marking that remote cores are done st->remote_fin = true; DEBUG_CAPOPS("%s: delete_queue_wait()\n", __FUNCTION__); struct event_closure steps_fin_cont = MKCLOSURE(revoke_master_steps__fin, st); delete_queue_wait(&st->del_qn, steps_fin_cont); }
void revoke_mark__rx(struct intermon_binding *b, intermon_caprep_t caprep, genvaddr_t st) { DEBUG_CAPOPS("%s\n", __FUNCTION__); errval_t err; struct intermon_state *inter_st = (struct intermon_state*)b->st; struct revoke_slave_st *rvk_st; err = calloce(1, sizeof(*rvk_st), &rvk_st); PANIC_IF_ERR(err, "allocating revoke slave state"); rvk_st->from = inter_st->core_id; rvk_st->st = st; caprep_to_capability(&caprep, &rvk_st->rawcap); if (!slaves_head) { assert(!slaves_tail); slaves_head = slaves_tail = rvk_st; } else { assert(slaves_tail); assert(!slaves_tail->next); slaves_tail->next = rvk_st; slaves_tail = rvk_st; } // pause any ongoing "delete stepping" as mark phases on other nodes need // to delete all foreign copies before we can delete locally owned caps delete_steps_pause(); // XXX: this invocation could create a scheduling hole that could be // problematic in RT systems and should probably be done in a loop. err = monitor_revoke_mark_relations(&rvk_st->rawcap); if (err_no(err) == SYS_ERR_CAP_NOT_FOUND) { // found no copies or descendants of capability on this core, // do nothing. -SG DEBUG_CAPOPS("no copies on core %d\n", disp_get_core_id()); } else if (err_is_fail(err)) { USER_PANIC_ERR(err, "marking revoke"); } rvk_st->im_qn.cont = revoke_ready__send; err = capsend_target(rvk_st->from, (struct msg_queue_elem*)rvk_st); PANIC_IF_ERR(err, "enqueing revoke_ready"); }
static void revoke_ready__send(struct intermon_binding *b, struct intermon_msg_queue_elem *e) { errval_t err; struct revoke_slave_st *rvk_st = (struct revoke_slave_st*)e; err = intermon_capops_revoke_ready__tx(b, NOP_CONT, rvk_st->st); PANIC_IF_ERR(err, "sending revoke_ready"); }
static void retrieve_result__enq(errval_t status, struct retrieve_response_st *st) { errval_t err; st->status = status; st->iqn.cont = retrieve_result__send; err = capsend_target(st->from, (struct msg_queue_elem*)st); PANIC_IF_ERR(err, "enqueing retrieve result"); }
static void revoke_slave_steps__fin(void *st) { errval_t err; struct revoke_slave_st *rvk_st = (struct revoke_slave_st*)st; rvk_st->im_qn.cont = revoke_done__send; err = capsend_target(rvk_st->from, (struct msg_queue_elem*)rvk_st); PANIC_IF_ERR(err, "enqueueing revoke_done"); }
static void revoke_done__send(struct intermon_binding *b, struct intermon_msg_queue_elem *e) { errval_t err; struct revoke_slave_st *rvk_st = (struct revoke_slave_st*)e; err = intermon_capops_revoke_done__tx(b, NOP_CONT, rvk_st->st); PANIC_IF_ERR(err, "sending revoke_done"); remove_slave_from_list(rvk_st); free(rvk_st); }
static void retrieve_result__send(struct intermon_binding *b, struct intermon_msg_queue_elem *e) { errval_t err; struct retrieve_response_st *st = (struct retrieve_response_st*)e; err = intermon_capops_retrieve_result__tx(b, NOP_CONT, st->status, st->relations, st->st); PANIC_IF_ERR(err, "sending retrieve result"); free(st); }
static void revoke_local(struct revoke_master_st *st) { DEBUG_CAPOPS("%s: called from %p\n", __FUNCTION__, __builtin_return_address(0)); errval_t err; delete_steps_pause(); err = monitor_revoke_mark_target(st->cap.croot, st->cap.cptr, st->cap.bits); PANIC_IF_ERR(err, "marking revoke"); DEBUG_CAPOPS("%s ## revocation: mark phase\n", __FUNCTION__); // XXX: could check whether remote copies exist here(?), -SG, 2014-11-05 err = capsend_relations(&st->rawcap, revoke_mark__send, &st->revoke_mc_st, &st->dests); PANIC_IF_ERR(err, "initiating revoke mark multicast"); }
static void revoke_retrieve__rx(errval_t result, void *st_) { struct revoke_master_st *st = (struct revoke_master_st*)st_; if (err_is_fail(result)) { revoke_result__rx(result, st, false); } else { #ifndef NDEBUG distcap_state_t state; errval_t err = dom_cnode_get_state(st->cap, &state); PANIC_IF_ERR(err, "dom_cnode_get_state"); assert(!distcap_state_is_foreign(state)); #endif revoke_local(st); } }
void revoke_ready__rx(struct intermon_binding *b, genvaddr_t st) { DEBUG_CAPOPS("%s\n", __FUNCTION__); errval_t err; struct revoke_master_st *rvk_st = (struct revoke_master_st*)(lvaddr_t)st; if (!capsend_handle_mc_reply(&rvk_st->revoke_mc_st)) { DEBUG_CAPOPS("%s: waiting for remote cores\n", __FUNCTION__); // multicast not complete return; } DEBUG_CAPOPS("%s ## revocation: commit phase\n", __FUNCTION__); err = capsend_relations(&rvk_st->rawcap, revoke_commit__send, &rvk_st->revoke_mc_st, &rvk_st->dests); PANIC_IF_ERR(err, "enqueing revoke_commit multicast"); delete_steps_resume(); struct event_closure steps_fin_cont = MKCLOSURE(revoke_master_steps__fin, rvk_st); delete_queue_wait(&rvk_st->del_qn, steps_fin_cont); }
void retrieve_request__rx(struct intermon_binding *b, intermon_caprep_t caprep, genvaddr_t st) { errval_t err, err2; struct intermon_state *inter_st = (struct intermon_state*)b->st; struct retrieve_response_st *rst; err = calloce(1, sizeof(*rst), &rst); PANIC_IF_ERR(err, "allocating retrieve respones state"); rst->st = st; rst->from = inter_st->core_id; struct capability rawcap; caprep_to_capability(&caprep, &rawcap); struct capref cap; err = slot_alloc(&cap); GOTO_IF_ERR(err, respond_err); err = monitor_copy_if_exists(&rawcap, cap); GOTO_IF_ERR(err, free_slot); distcap_state_t state; err = dom_cnode_get_state(get_cap_domref(cap), &state); GOTO_IF_ERR(err, delete_cap); if (distcap_state_is_busy(state)) { err = MON_ERR_REMOTE_CAP_RETRY; goto delete_cap; } if (distcap_state_is_foreign(state)) { err = MON_ERR_CAP_FOREIGN; goto delete_cap; } uint8_t relations, remote_relations; err = monitor_cap_has_relations(cap, 0xFF, &relations); GOTO_IF_ERR(err, delete_cap); err = monitor_remote_relations(cap, 0, 0, &remote_relations); GOTO_IF_ERR(err, delete_cap); rst->relations = relations | remote_relations | RRELS_COPY_BIT; err = monitor_set_cap_owner(cap_root, get_cap_addr(cap), get_cap_valid_bits(cap), rst->from); delete_cap: err2 = cap_delete(cap); DEBUG_IF_ERR(err2, "while deleting temp cap for retrieve"); free_slot: err2 = slot_free(cap); DEBUG_IF_ERR(err2, "freeing temp cap slot for retrieve"); respond_err: retrieve_result__enq(err, rst); }