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 capops_revoke(struct domcapref cap, revoke_result_handler_t result_handler, void *st) { errval_t err; DEBUG_CAPOPS("%s ## start revocation protocol\n", __FUNCTION__); distcap_state_t state; err = dom_cnode_get_state(cap, &state); GOTO_IF_ERR(err, report_error); if (distcap_state_is_busy(state)) { err = MON_ERR_REMOTE_CAP_RETRY; goto report_error; } struct revoke_master_st *rst; err = calloce(1, sizeof(*rst), &rst); GOTO_IF_ERR(err, report_error); rst->cap = cap; err = monitor_domains_cap_identify(cap.croot, cap.cptr, cap.bits, &rst->rawcap); GOTO_IF_ERR(err, free_st); rst->result_handler = result_handler; rst->st = st; if (distcap_state_is_foreign(state)) { // need to retrieve ownership DEBUG_CAPOPS("%s getting cap ownership\n", __FUNCTION__); capops_retrieve(rst->cap, revoke_retrieve__rx, rst); } else { if (num_monitors_online() == 1) { DEBUG_CAPOPS("%s: only one monitor: do simpler revoke\n", __FUNCTION__); // no remote monitors exist; do simplified revocation process revoke_no_remote(rst); // return here return; } // have ownership, initiate revoke revoke_local(rst); } return; free_st: free(rst); report_error: result_handler(err, st); }
static errval_t capsend_broadcast(struct capsend_mc_st *bc_st, struct capsend_destset *dests, struct capability *cap, capsend_send_fn send_cont) { errval_t err; size_t dest_count; bool init_destset = false; size_t online_monitors = num_monitors_online(); // do not count self when calculating #dest cores dest_count = online_monitors - 1; DEBUG_CAPOPS("%s: dest_count = %d\n", __FUNCTION__, dest_count); DEBUG_CAPOPS("%s: num_queued = %d\n", __FUNCTION__, bc_st->num_queued); DEBUG_CAPOPS("%s: num_pending = %d\n", __FUNCTION__, bc_st->num_pending); if (dests && dests->set == NULL) { dests->set = calloc(dest_count, sizeof(coreid_t)); dests->capacity = dest_count; dests->count = 0; init_destset = true; } else if (dests) { dest_count = dests->count; } err = capsend_mc_init(bc_st, cap, send_cont, dest_count, true); if (err_is_fail(err)) { free(bc_st); } if (init_destset || !dests) { for (coreid_t dest = 0; dest < MAX_COREID && bc_st->num_queued < dest_count; dest++) { if (dest == my_core_id) { // do not send to self continue; } err = capsend_mc_enqueue(bc_st, dest); if (err_is_ok(err) && dests) { // if we're initializing destination set, add destination // cores that we were able to enqueue msg for to set. dests->set[dests->count++] = dest; } if (err_no(err) == MON_ERR_NO_MONITOR_FOR_CORE) { // no connection for this core, skip continue; } else if (err_no(err) == MON_ERR_CAPOPS_BUSY) { debug_printf("monitor.%d not ready to participate in distops, skipping\n", dest); } else if (err_is_fail(err)) { // failure, disable broadcast bc_st->do_send = false; if (!bc_st->num_queued) { // only cleanup of no messages have been enqueued free(bc_st->msg_st_arr); free(bc_st); } return err; } } } else { for (int i = 0; i < dest_count; i++) { coreid_t dest = dests->set[i]; err = capsend_mc_enqueue(bc_st, dest); if (err_no(err) == MON_ERR_NO_MONITOR_FOR_CORE) { // no connection for this core, skip continue; } else if (err_no(err) == MON_ERR_CAPOPS_BUSY) { debug_printf("monitor.%d not ready to participate in distops, skipping\n", dest); } else if (err_is_fail(err)) { // failure, disable broadcast bc_st->do_send = false; if (!bc_st->num_queued) { // only cleanup of no messages have been enqueued free(bc_st->msg_st_arr); free(bc_st); } return err; } } } if (!bc_st->num_pending && dest_count > 1) { // XXX: needs sane error -SG return MON_ERR_NO_MONITOR_FOR_CORE; } return SYS_ERR_OK; }