<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 "magic.h"
#include "caplock.h"
#include "capqueue.h"
#include "dom_invocations.h"
#include "internal.h"
#include "delete_int.h"
#include <if/mem_rpcclient_defs.h>

struct delete_remote_mc_st {
    struct capsend_mc_st mc_st;
    struct delete_st *del_st;
    errval_t status;
};

struct delete_remote_result_msg_st {
    struct intermon_msg_queue_elem queue_elem;
    errval_t status;
    genvaddr_t st;
};

static void delete_trylock_cont(void *st);

static void
delete_result__rx(errval_t status, struct delete_st *del_st, bool locked)
{
    errval_t err;

    if (locked) {
        caplock_unlock(del_st->capref);
    }

    err = slot_free(del_st->newcap);
    if (err_is_fail(err)) {
        DEBUG_ERR(err, "freeing reclamation slot, will leak");
    }

    delete_result_handler_t handler = del_st->result_handler;
    void *st = del_st->st;
    free(del_st);
    handler(status, st);
}

void
send_new_ram_cap(struct capref cap)
{
    errval_t err, result;

    struct capability cap_data;
    err = monitor_cap_identify(cap, &cap_data);
    assert(err_is_ok(err));
    assert(cap_data.type == ObjType_RAM);
    struct RAM ram = cap_data.u.ram;

    struct ram_alloc_state *ram_alloc_state = get_ram_alloc_state();
    thread_mutex_lock(&ram_alloc_state->ram_alloc_lock);

    struct mem_rpc_client *b = get_mem_client();
    // XXX: This should not be an RPC! It could stall the monitor, but
    // we trust mem_serv for the moment.
    err = b->vtbl.free_monitor(b, cap, ram.base, ram.bits, &result);
    assert(err_is_ok(err));
    assert(err_is_ok(result));

    thread_mutex_unlock(&ram_alloc_state->ram_alloc_lock);

    err = cap_delete(cap);
    assert(err_is_ok(err));
}

static void delete_wait__fin(void *st_)
{
    struct delete_st *st = (struct delete_st*)st_;
    delete_result__rx(SYS_ERR_OK, st, false);
}

static void delete_last(struct delete_st* del_st)
{
    errval_t err;
    bool locked = true;

    err = monitor_delete_last(del_st->capref.croot, del_st->capref.cptr,
                              del_st->capref.bits, del_st->newcap);
    GOTO_IF_ERR(err, report_error);
    if (err_no(err) == SYS_ERR_RAM_CAP_CREATED) {
        send_new_ram_cap(del_st->newcap);
        err = SYS_ERR_OK;
    }

    // at this point the cap has become "unlocked" because it is either deleted
    // or in a clear/delete queue
    locked = false;

    if (!del_st->wait) {
        goto report_error;
    }

    delete_queue_wait(&del_st->qn, MKCLOSURE(delete_wait__fin, del_st));

    return;

report_error:
    delete_result__rx(err, del_st, locked);
}

/*
 * Non-moveable cap types: deleting all foreign copies when last owned copy of
 * cap is deleted
 */

static errval_t
delete_remote__send(struct intermon_binding *b, intermon_caprep_t *caprep,
                    struct capsend_mc_st *st)
{
    return intermon_capops_delete_remote__tx(b, NOP_CONT, *caprep,
                                             (genvaddr_t)st);
}

static void
delete_remote__enq(struct capability *cap, struct delete_st *st)
{
    errval_t err;
    struct delete_remote_mc_st *mc_st;

    err = malloce(sizeof(*mc_st), &mc_st);
    GOTO_IF_ERR(err, report_error);
    mc_st->del_st = st;

    err = capsend_copies(cap, delete_remote__send,
                         (struct capsend_mc_st*)mc_st);
    GOTO_IF_ERR(err, report_error);

    return;

report_error:
    delete_result__rx(err, st, true);
}

static void
delete_remote_result__send(struct intermon_binding *b, struct intermon_msg_queue_elem *e)
{
    errval_t err;
    struct delete_remote_result_msg_st *msg_st = (struct delete_remote_result_msg_st*)e;
    err = intermon_capops_delete_remote_result__tx(b, NOP_CONT, msg_st->status, msg_st->st);
    PANIC_IF_ERR(err, "failed to send delete_remote_result msg");
    free(msg_st);
}

static void
delete_remote_result__enq(coreid_t dest, errval_t status, genvaddr_t st)
{
    errval_t err;

    struct delete_remote_result_msg_st *msg_st;
    err = calloce(1, sizeof(*msg_st), &msg_st);
    PANIC_IF_ERR(err, "allocating delete_remote_result st");

    msg_st->queue_elem.cont = delete_remote_result__send;
    msg_st->status = status;
    msg_st->st = st;

    err = capsend_target(dest, (struct msg_queue_elem*)msg_st);
    PANIC_IF_ERR(err, "failed to send delete_remote result");
}

void
delete_remote__rx(struct intermon_binding *b, intermon_caprep_t caprep,
                  genvaddr_t st)
{
    errval_t err, err2;
    struct capability cap;
    struct intermon_state *inter_st = (struct intermon_state*)b->st;
    coreid_t from = inter_st->core_id;
    caprep_to_capability(&caprep, &cap);
    struct capref capref;

    err = slot_alloc(&capref);
    GOTO_IF_ERR(err, send_err);

    err = monitor_copy_if_exists(&cap, capref);
    if (err_is_fail(err)) {
        if (err_no(err) != SYS_ERR_CAP_NOT_FOUND) {
            // not found implies there were no copies, so everything is OK
            err = SYS_ERR_OK;
        }
        goto free_slot;
    }

    err = monitor_delete_copies(capref);
    err2 = cap_delete(capref);
    DEBUG_IF_ERR(err2, "deleting temp delete_remote cap");
    if (err_is_ok(err) && err_is_fail(err2)) {
        err = err2;
    }
<commit_msg>Fixed reversed condition in delete_remote handling.<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 "magic.h"
#include "caplock.h"
#include "capqueue.h"
#include "dom_invocations.h"
#include "internal.h"
#include "delete_int.h"
#include <if/mem_rpcclient_defs.h>

struct delete_remote_mc_st {
    struct capsend_mc_st mc_st;
    struct delete_st *del_st;
    errval_t status;
};

struct delete_remote_result_msg_st {
    struct intermon_msg_queue_elem queue_elem;
    errval_t status;
    genvaddr_t st;
};

static void delete_trylock_cont(void *st);

static void
delete_result__rx(errval_t status, struct delete_st *del_st, bool locked)
{
    errval_t err;

    if (locked) {
        caplock_unlock(del_st->capref);
    }

    err = slot_free(del_st->newcap);
    if (err_is_fail(err)) {
        DEBUG_ERR(err, "freeing reclamation slot, will leak");
    }

    delete_result_handler_t handler = del_st->result_handler;
    void *st = del_st->st;
    free(del_st);
    handler(status, st);
}

void
send_new_ram_cap(struct capref cap)
{
    errval_t err, result;

    struct capability cap_data;
    err = monitor_cap_identify(cap, &cap_data);
    assert(err_is_ok(err));
    assert(cap_data.type == ObjType_RAM);
    struct RAM ram = cap_data.u.ram;

    struct ram_alloc_state *ram_alloc_state = get_ram_alloc_state();
    thread_mutex_lock(&ram_alloc_state->ram_alloc_lock);

    struct mem_rpc_client *b = get_mem_client();
    // XXX: This should not be an RPC! It could stall the monitor, but
    // we trust mem_serv for the moment.
    err = b->vtbl.free_monitor(b, cap, ram.base, ram.bits, &result);
    assert(err_is_ok(err));
    assert(err_is_ok(result));

    thread_mutex_unlock(&ram_alloc_state->ram_alloc_lock);

    err = cap_delete(cap);
    assert(err_is_ok(err));
}

static void delete_wait__fin(void *st_)
{
    struct delete_st *st = (struct delete_st*)st_;
    delete_result__rx(SYS_ERR_OK, st, false);
}

static void delete_last(struct delete_st* del_st)
{
    errval_t err;
    bool locked = true;

    err = monitor_delete_last(del_st->capref.croot, del_st->capref.cptr,
                              del_st->capref.bits, del_st->newcap);
    GOTO_IF_ERR(err, report_error);
    if (err_no(err) == SYS_ERR_RAM_CAP_CREATED) {
        send_new_ram_cap(del_st->newcap);
        err = SYS_ERR_OK;
    }

    // at this point the cap has become "unlocked" because it is either deleted
    // or in a clear/delete queue
    locked = false;

    if (!del_st->wait) {
        goto report_error;
    }

    delete_queue_wait(&del_st->qn, MKCLOSURE(delete_wait__fin, del_st));

    return;

report_error:
    delete_result__rx(err, del_st, locked);
}

/*
 * Non-moveable cap types: deleting all foreign copies when last owned copy of
 * cap is deleted
 */

static errval_t
delete_remote__send(struct intermon_binding *b, intermon_caprep_t *caprep,
                    struct capsend_mc_st *st)
{
    return intermon_capops_delete_remote__tx(b, NOP_CONT, *caprep,
                                             (genvaddr_t)st);
}

static void
delete_remote__enq(struct capability *cap, struct delete_st *st)
{
    errval_t err;
    struct delete_remote_mc_st *mc_st;

    err = malloce(sizeof(*mc_st), &mc_st);
    GOTO_IF_ERR(err, report_error);
    mc_st->del_st = st;

    err = capsend_copies(cap, delete_remote__send,
                         (struct capsend_mc_st*)mc_st);
    GOTO_IF_ERR(err, report_error);

    return;

report_error:
    delete_result__rx(err, st, true);
}

static void
delete_remote_result__send(struct intermon_binding *b, struct intermon_msg_queue_elem *e)
{
    errval_t err;
    struct delete_remote_result_msg_st *msg_st = (struct delete_remote_result_msg_st*)e;
    err = intermon_capops_delete_remote_result__tx(b, NOP_CONT, msg_st->status, msg_st->st);
    PANIC_IF_ERR(err, "failed to send delete_remote_result msg");
    free(msg_st);
}

static void
delete_remote_result__enq(coreid_t dest, errval_t status, genvaddr_t st)
{
    errval_t err;

    struct delete_remote_result_msg_st *msg_st;
    err = calloce(1, sizeof(*msg_st), &msg_st);
    PANIC_IF_ERR(err, "allocating delete_remote_result st");

    msg_st->queue_elem.cont = delete_remote_result__send;
    msg_st->status = status;
    msg_st->st = st;

    err = capsend_target(dest, (struct msg_queue_elem*)msg_st);
    PANIC_IF_ERR(err, "failed to send delete_remote result");
}

void
delete_remote__rx(struct intermon_binding *b, intermon_caprep_t caprep,
                  genvaddr_t st)
{
    errval_t err, err2;
    struct capability cap;
    struct intermon_state *inter_st = (struct intermon_state*)b->st;
    coreid_t from = inter_st->core_id;
    caprep_to_capability(&caprep, &cap);
    struct capref capref;

    err = slot_alloc(&capref);
    GOTO_IF_ERR(err, send_err);

    err = monitor_copy_if_exists(&cap, capref);
    if (err_is_fail(err)) {
        if (err_no(err) == SYS_ERR_CAP_NOT_FOUND) {
            // not found implies there were no copies, so everything is OK
            err = SYS_ERR_OK;
        }
        goto free_slot;
    }

    err = monitor_delete_copies(capref);
    err2 = cap_delete(capref);
    DEBUG_IF_ERR(err2, "deleting temp delete_remote cap");
    if (err_is_ok(err) && err_is_fail(err2)) {
        err = err2;
    }

{'fraction_non_alphanumeric': 0.10274460880413473, 'fraction_numerical': 0.002673320263767599, 'mean_word_length': 3.5199355618203785, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7560517', 'n_tokens_mistral': 4133, 'n_tokens_neox': 4035, 'n_words': 893}