*/
#include <barrelfish/barrelfish.h>
+#include <barrelfish/deferred.h>
#include "capsend.h"
#include "monitor.h"
#include "capops.h"
free(uo_bc_st);
}
+struct delayed_cleanup_st {
+ struct deferred_event d;
+ struct event_closure ev;
+ struct capref capref;
+ delayus_t delay;
+};
+
+static void defer_free_owner_rx_cap(struct delayed_cleanup_st *st)
+{
+ errval_t err;
+ deferred_event_init(&st->d);
+ err = deferred_event_register(&st->d, get_default_waitset(), st->delay, st->ev);
+ if (err_is_fail(err)) {
+ DEBUG_ERR(err, "unable to register deferred event, leaking cap");
+ free(st);
+ }
+}
+
+static void free_owner_rx_cap(void *st_)
+{
+ errval_t err;
+ struct delayed_cleanup_st *st = st_;
+ err = cap_destroy(st->capref);
+ if (err_no(err) == SYS_ERR_CAP_LOCKED) {
+ // exponential backoff
+ st->delay *= 2;
+ defer_free_owner_rx_cap(st);
+ return;
+ }
+ PANIC_IF_ERR(err, "cap cleanup after update_owner_rx");
+ free(st);
+}
+
void
update_owner__rx_handler(struct intermon_binding *b, intermon_caprep_t caprep, genvaddr_t st)
{
}
if (err_no(err) == SYS_ERR_CAP_NOT_FOUND) {
err = SYS_ERR_OK;
+ slot_free(capref);
+ goto reply;
}
if (err_is_fail(err)) {
USER_PANIC_ERR(err, "failed to update cap ownership");
}
- cap_destroy(capref);
+ err = cap_destroy(capref);
+ if (err_no(err) == SYS_ERR_CAP_LOCKED) {
+ // ownership updates still in flight, delete cap later
+ struct delayed_cleanup_st *dst = malloc(sizeof(*dst));
+ assert(dst);
+ dst->capref = capref;
+ dst->ev = MKCLOSURE(free_owner_rx_cap, dst);
+ dst->delay = 1000; // 1ms delay
+ defer_free_owner_rx_cap(dst);
+ }
+reply:
err = owner_updated(from, st);
if (err_is_fail(err)) {
USER_PANIC_ERR(err, "failed to send ownership update response");
delete_result_handler_t handler = del_st->result_handler;
void *st = del_st->st;
free(del_st);
+ // Delete our copy of domain's rootcn
+ err = cap_destroy(del_st->capref.croot);
+ PANIC_IF_ERR(err, "cleaning up domain's rootcn");
handler(status, st);
}
goto reset_owner;
}
+ // If broadcast doesn't fail, unlock cap only after all nodes have
+ // acknowledged ownership change, see free_owner_recv_cap().
err = capsend_update_owner(domcapref, MKCONT(free_owner_recv_cap, capref));
if (err_is_fail(err)) {
goto reset_owner;
struct retype_output_st *output, void *to_free)
{
DEBUG_CAPOPS("%s\n", __FUNCTION__);
- errval_t err = status;
- if (err_is_ok(err)) {
+ errval_t err;
+ struct domcapref *src = &check->src;
+ struct domcapref *destcn = &output->destcn;
+ if (err_is_ok(status)) {
// the retype may procede
- struct domcapref *src = &check->src;
- struct domcapref *destcn = &output->destcn;
- err = monitor_create_caps(src->croot, destcn->croot, check->type,
+ status = monitor_create_caps(src->croot, destcn->croot, check->type,
check->objsize, check->count, src->cptr,
src->level, check->offset, destcn->cptr,
destcn->level, output->start_slot);
struct result_closure cont = output->cont;
assert(cont.handler);
free(to_free);
- CALLRESCONT(cont, err);
+ // Delete copies of domain's src/dest root cnodes
+ err = cap_destroy(src->croot);
+ PANIC_IF_ERR(err, "deleting monitor's copy of src rootcn");
+ err = cap_destroy(destcn->croot);
+ PANIC_IF_ERR(err, "deleting monitor's copy dest rootcn");
+ CALLRESCONT(cont, status);
}
/**
DEBUG_CAPOPS("%s ## revocation completed, calling %p\n", __FUNCTION__,
st->result_handler);
+ err = cap_destroy(st->cap.croot);
+ PANIC_IF_ERR(err, "deleting monitor's copy of rootcn");
st->result_handler(result, st->st);
free(st);
}