<commit_before>/*
 * Copyright (c) 2012 ETH Zurich.
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached LICENSE file.
 * If you do not find this file, copies can be found by writing to:
 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
 */

#include <barrelfish/barrelfish.h>
#include "monitor.h"
#include "capops.h"
#include "capsend.h"
#include "caplock.h"
#include "internal.h"
#include "delete_int.h"
#include "dom_invocations.h"
#include "monitor_debug.h"

struct revoke_slave_st *slaves_head = 0, *slaves_tail = 0;

struct revoke_master_st {
    struct delete_queue_node del_qn;
    struct domcapref cap;
    struct capability rawcap;
    struct capsend_mc_st revoke_mc_st;
    struct capsend_destset dests;
    revoke_result_handler_t result_handler;
    void *st;
    bool local_fin, remote_fin;
};

struct revoke_slave_st {
    struct intermon_msg_queue_elem im_qn;
    struct delete_queue_node del_qn;
    struct capability rawcap;
    struct capref cap;
    coreid_t from;
    genvaddr_t st;
    errval_t status;
    struct revoke_slave_st *next;
};

static void revoke_result__rx(errval_t result,
                              struct revoke_master_st *st,
                              bool locked);
static void revoke_retrieve__rx(errval_t result, void *st_);
static void revoke_local(struct revoke_master_st *st);
static void revoke_no_remote(struct revoke_master_st *st);
static errval_t revoke_mark__send(struct intermon_binding *b,
                                  intermon_caprep_t *caprep,
                                  struct capsend_mc_st *mc_st);
static void revoke_ready__send(struct intermon_binding *b,
                               struct intermon_msg_queue_elem *e);
static errval_t revoke_commit__send(struct intermon_binding *b,
                                    intermon_caprep_t *caprep,
                                    struct capsend_mc_st *mc_st);
static void revoke_slave_steps__fin(void *st);
static void revoke_done__send(struct intermon_binding *b,
                              struct intermon_msg_queue_elem *e);
static void revoke_master_steps__fin(void *st);

void
capops_revoke(struct domcapref cap,
              revoke_result_handler_t result_handler,
              void *st)
{
    errval_t err;

    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
        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 void
revoke_result__rx(errval_t result,
                  struct revoke_master_st *st,
                  bool locked)
{
    DEBUG_CAPOPS("%s\n", __FUNCTION__);
    errval_t err;

    if (locked) {
        caplock_unlock(st->cap);
    }

    if (err_is_ok(result)) {
        // clear the remote copies bit
        err = monitor_domcap_remote_relations(st->cap.croot, st->cap.cptr,
                                              st->cap.bits, 0, RRELS_COPY_BIT,
                                              NULL);
        if (err_is_fail(err) && err_no(err) != SYS_ERR_CAP_NOT_FOUND) {
            DEBUG_ERR(err, "resetting remote copies bit after revoke");
        }
    }

    st->result_handler(result, st->st);
}

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 {
        revoke_local(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");
<commit_msg>monitor: distops: add missing free + assert in retrieve.<commit_after>/*
 * Copyright (c) 2012 ETH Zurich.
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached LICENSE file.
 * If you do not find this file, copies can be found by writing to:
 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
 */

#include <barrelfish/barrelfish.h>
#include "monitor.h"
#include "capops.h"
#include "capsend.h"
#include "caplock.h"
#include "internal.h"
#include "delete_int.h"
#include "dom_invocations.h"
#include "monitor_debug.h"

struct revoke_slave_st *slaves_head = 0, *slaves_tail = 0;

struct revoke_master_st {
    struct delete_queue_node del_qn;
    struct domcapref cap;
    struct capability rawcap;
    struct capsend_mc_st revoke_mc_st;
    struct capsend_destset dests;
    revoke_result_handler_t result_handler;
    void *st;
    bool local_fin, remote_fin;
};

struct revoke_slave_st {
    struct intermon_msg_queue_elem im_qn;
    struct delete_queue_node del_qn;
    struct capability rawcap;
    struct capref cap;
    coreid_t from;
    genvaddr_t st;
    errval_t status;
    struct revoke_slave_st *next;
};

static void revoke_result__rx(errval_t result,
                              struct revoke_master_st *st,
                              bool locked);
static void revoke_retrieve__rx(errval_t result, void *st_);
static void revoke_local(struct revoke_master_st *st);
static void revoke_no_remote(struct revoke_master_st *st);
static errval_t revoke_mark__send(struct intermon_binding *b,
                                  intermon_caprep_t *caprep,
                                  struct capsend_mc_st *mc_st);
static void revoke_ready__send(struct intermon_binding *b,
                               struct intermon_msg_queue_elem *e);
static errval_t revoke_commit__send(struct intermon_binding *b,
                                    intermon_caprep_t *caprep,
                                    struct capsend_mc_st *mc_st);
static void revoke_slave_steps__fin(void *st);
static void revoke_done__send(struct intermon_binding *b,
                              struct intermon_msg_queue_elem *e);
static void revoke_master_steps__fin(void *st);

void
capops_revoke(struct domcapref cap,
              revoke_result_handler_t result_handler,
              void *st)
{
    errval_t err;

    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
        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 void
revoke_result__rx(errval_t result,
                  struct revoke_master_st *st,
                  bool locked)
{
    DEBUG_CAPOPS("%s\n", __FUNCTION__);
    errval_t err;

    if (locked) {
        caplock_unlock(st->cap);
    }

    if (err_is_ok(result)) {
        // clear the remote copies bit
        err = monitor_domcap_remote_relations(st->cap.croot, st->cap.cptr,
                                              st->cap.bits, 0, RRELS_COPY_BIT,
                                              NULL);
        if (err_is_fail(err) && err_no(err) != SYS_ERR_CAP_NOT_FOUND) {
            DEBUG_ERR(err, "resetting remote copies bit after revoke");
        }
    }

    st->result_handler(result, st->st);
    free(st);
}

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);
    }
}

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");

{'fraction_non_alphanumeric': 0.08897330800759772, 'fraction_numerical': 0.0029991002699190244, 'mean_word_length': 2.4319039451114923, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 34, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4011055', 'n_tokens_mistral': 3362, 'n_tokens_neox': 3238, 'n_words': 732}