message cap_send_request(con_id_t con_id,
capid_t capid,
caprep cap,
+ errval err,
bool give_away,
bool has_descendents,
coremask on_cores,
bool null_cap);
- message cap_send_reply(con_id_t con_id,
- capid_t capid,
- errval err);
message span_domain_request(state_id_t state_id,
genpaddr vnodebase,
message bind_multihop_intermon_reply(vci_t receiver_vci, vci_t sender_vci, errval err);
message multihop_message(vci_t vci, uint8 direction, uint8 flags, uint32 ack, uint8 payload[size]);
- message multihop_cap_send(vci_t vci, uint8 direction, capid_t capid, caprep cap, bool null_cap);
- message multihop_cap_reply(vci_t vci, uint8 direction, capid_t capid, errval err);
+ message multihop_cap_send(vci_t vci, uint8 direction, capid_t capid, errval err, caprep cap, bool null_cap);
};
cap cap,
capid_t capid,
uint8 give_away);
- response cap_send_reply(
- uintptr conn_id,
- capid_t capid,
- errval err);
response cap_receive_request(
uintptr conn_id,
+ errval err,
cap cap,
capid_t capid);
message multihop_message(vci_t vci, uint8 direction, uint8 flags, uint32 ack, uint8 payload[size]);
// cap transfer
- call multihop_cap_send(vci_t vci, uint8 direction, cap cap, capid_t capid);
- response multihop_cap_reply(vci_t vci, uint8 direction, capid_t capid, errval err);
+ call multihop_cap_send(vci_t vci, uint8 direction, errval err, cap cap, capid_t capid);
};
/// Handlers for incoming/outgoing capabilities on the monitor binding
struct monitor_cap_handlers {
void *st; ///< state pointer passed to handler functions
- void (*cap_receive_handler)(void *st, struct capref cap, uint32_t capid);
- void (*cap_send_reply_handler)(void *st, uint32_t capid, errval_t success);
+ void (*cap_receive_handler)(void *st, errval_t success, struct capref cap,
+ uint32_t capid);
};
/* XXX: duplicate of monitor_bind_continuation_fn in generated code */
/// Handler for incoming LMP messages from the monitor binding with an
/// indirected cap for a UMP/BMP/... channel
static void cap_receive_request_handler(struct monitor_binding *b,
- uintptr_t conn_id,
+ uintptr_t conn_id, errval_t success,
struct capref cap, uint32_t capid)
{
/* XXX: this relies on the monitor_cap_handlers table being the first thing
* in every channel state struct */
struct monitor_cap_handlers *h = (void *)conn_id;
assert(h->cap_receive_handler != NULL);
- h->cap_receive_handler(h->st, cap, capid);
-}
-
-static void cap_send_reply_handler(struct monitor_binding *b, uintptr_t conn_id,
- uint32_t capid, errval_t err)
-{
- /* XXX: this relies on the monitor_cap_handlers table being the first thing
- * in every channel state struct */
- struct monitor_cap_handlers *h = (void *)conn_id;
- assert(h->cap_send_reply_handler != NULL);
- h->cap_send_reply_handler(h->st, capid, err);
+ h->cap_receive_handler(h->st, success, cap, capid);
}
/// vtable for handlers declared in this file
// functions after we bind to the monitor
static struct monitor_rx_vtbl monitor_rx_vtbl = {
.cap_receive_request = cap_receive_request_handler,
- .cap_send_reply = cap_send_reply_handler,
};
static void monitor_accept_recv_handler(void *arg)
// send the message
err = mon_binding->tx_vtbl.multihop_cap_send(mon_binding, _continuation,
- mc->vci, mc->direction, cap, cap_state->tx_capnum);
+ mc->vci, mc->direction,
+ SYS_ERR_OK, cap,
+ cap_state->tx_capnum);
if (err_is_ok(err)) {
// increase capability number
*
*/
static void multihop_handle_capability(struct monitor_binding *mon_closure,
- multihop_vci_t vci, uint8_t direction, struct capref cap, uint32_t capid)
+ multihop_vci_t vci, uint8_t direction, errval_t msgerr,
+ struct capref cap, uint32_t capid)
{
struct multihop_chan *mc = multihop_chan_mappings_lookup(vci);
assert(mc->cap_handlers.cap_receive_handler != NULL);
// deliver capability to the handler
- mc->cap_handlers.cap_receive_handler(mc->cap_handlers.st, cap, capid);
-}
-
-/**
- * \ brief Handle a capability reply
- */
-static void multihop_handle_capability_reply(
- struct monitor_binding *mon_closure, multihop_vci_t vci, uint8_t direction,
- uint32_t capid, errval_t msgerr)
-{
-
- struct multihop_chan *mc = multihop_chan_mappings_lookup(vci);
- assert(mc->connstate == MULTIHOP_CONNECTED);
- assert(mc->cap_handlers.cap_send_reply_handler != NULL);
- mc->cap_handlers.cap_send_reply_handler(mc->cap_handlers.st, capid, msgerr);
+ mc->cap_handlers.cap_receive_handler(mc->cap_handlers.st, msgerr, cap, capid);
}
///////////////////////////////////////////////////////
mb->rx_vtbl.multihop_bind_client_reply = &multihop_bind_reply_handler; // handler for incoming reply messages from the monitor
mb->rx_vtbl.multihop_message = &handle_multihop_message; // handler for incoming messages from the monitor
mb->rx_vtbl.multihop_cap_send = &multihop_handle_capability; // handler for incoming capabilities from the monitor
- mb->rx_vtbl.multihop_cap_reply = &multihop_handle_capability_reply; // handler for capability reply messages
}
-- Name of the caps receive handlers
caps_rx_handler_name :: String -> String
caps_rx_handler_name ifn = ifscope ifn "multihop_caps_rx_handler"
-caps_rx_reply_handler_name ifn = ifscope ifn "multihop_caps_reply_handler"
-- Names of the control functions
change_waitset_fn_name, control_fn_name :: String -> String
multihop_connect_handler_proto name,
multihop_rx_handler_proto name,
multihop_caps_rx_handler_proto name,
- multihop_caps_reply_rx_handler_proto name,
C.Blank
]
multihop_caps_rx_handler_params :: [C.Param]
multihop_caps_rx_handler_params = [C.Param (C.Ptr C.Void) "arg",
+ C.Param (C.TypeName "errval_t") "success",
C.Param (C.Struct "capref") "cap",
C.Param (C.TypeName "uint32_t") "capid"]
-
-multihop_caps_reply_rx_handler_proto :: String -> C.Unit
-multihop_caps_reply_rx_handler_proto ifn = C.GVarDecl C.Extern C.NonConst
- (C.Function C.NoScope C.Void multihop_caps_reply_rx_handler_params)
- (caps_rx_reply_handler_name ifn) Nothing
-
-multihop_caps_reply_rx_handler_params = [C.Param (C.Ptr C.Void) "arg",
- C.Param (C.TypeName "uint32_t") "capid",
- C.Param (C.TypeName "errval_t") "success"]
-
+
------------------------------------------------------------------------
-- Language mapping: Create the stub (implementation) for this interconnect driver
------------------------------------------------------------------------
C.MultiComment [ "Cap receive handlers" ],
caps_rx_handler arch ifn types messages msg_specs,
- caps_reply_rx_handler arch ifn,
C.Blank,
C.MultiComment [ "Message sender functions" ],
[C.AddressOf $ C.DerefField multihop_bind_var "chan",
C.StructConstant "monitor_cap_handlers"
[("st", C.Variable "st"),
- ("cap_receive_handler", C.Variable (caps_rx_handler_name ifn)),
- ("cap_send_reply_handler", C.Variable (caps_rx_reply_handler_name ifn))
+ ("cap_receive_handler", C.Variable (caps_rx_handler_name ifn))
]]]
[ C.Ex $ C.Call (multihop_destroy_fn_name ifn) [multihop_bind_var]],
[C.AddressOf $ C.DerefField multihop_bind_var "chan",
C.StructConstant "monitor_cap_handlers"
[("st", multihop_bind_var),
- ("cap_receive_handler", C.Variable (caps_rx_handler_name ifn)),
- ("cap_send_reply_handler", C.Variable (caps_rx_reply_handler_name ifn))
+ ("cap_receive_handler", C.Variable (caps_rx_handler_name ifn))
]],
C.SBlank,
C.Ex $ C.Call "assert" [C.Binary C.Equals (C.Variable "capid") (capst `C.FieldOf` "rx_capnum")],
C.SBlank,
+ C.SComment "Check if there's an associated error",
+ C.SComment "FIXME: how should we report this to the user? at present we just deliver a NULL capref",
+ C.If (C.Call "err_is_fail" [C.Variable "success"])
+ [C.Ex $ C.Call "DEBUG_ERR"
+ [C.Variable "success", C.StringConstant "could not send cap over multihop channel"]
+ ] [],
+ C.SBlank,
+
C.SComment "Switch on current incoming message",
C.Switch (C.DerefField bindvar "rx_msgnum") cases
[C.Ex $ C.Call "assert"
rx_msgfrag_field = C.DerefField bindvar "rx_msg_fragment"
is_last = (ncap + 1 == length caps)
-
--- handle a caps reply message
-caps_reply_rx_handler :: Arch -> String -> C.Unit
-caps_reply_rx_handler arch ifn =
- C.FunctionDef C.NoScope C.Void (caps_rx_reply_handler_name ifn) multihop_caps_reply_rx_handler_params
- [
- localvar (C.Ptr $ C.Struct $ intf_bind_type ifn) intf_bind_var (Just $ C.Variable "arg"),
- C.SBlank,
-
- C.If (C.Call "err_is_fail" [C.Variable "success"])
- [C.Ex $ C.Call "DEBUG_ERR"
- [C.Variable "success", C.StringConstant "could not send cap over multihop channel"],
- report_user_err $ C.Variable "success"
- ] []
- ]
-- Name of the cap send/recv handlers
cap_rx_handler_name p ifn = ump_ifscope p ifn "cap_rx_handler"
-cap_tx_reply_handler_name p ifn = ump_ifscope p ifn "cap_tx_reply_handler"
-- Names of the control functions
change_waitset_fn_name p ifn = ump_ifscope p ifn "change_waitset"
C.MultiComment [ "Cap send/receive handlers" ],
cap_rx_handler p ifn types messages msg_specs,
- cap_tx_reply_handler p ifn,
C.Blank,
C.UnitList $ if has_caps then
rx_fragment_increment
= C.Ex $ C.PostInc $ C.DerefField bindvar "rx_msg_fragment"
-cap_tx_reply_handler :: UMPParams -> String -> C.Unit
-cap_tx_reply_handler p ifn
- = C.FunctionDef C.Static C.Void (cap_tx_reply_handler_name p ifn)
- [C.Param (C.Ptr C.Void) "st",
- C.Param (C.TypeName "uint32_t") "capid",
- C.Param (C.TypeName "errval_t") "err"]
- [
- localvar (C.Ptr $ C.Struct $ intf_bind_type ifn) intf_bind_var (Just $ C.Variable "st"),
- C.If (C.Call "err_is_fail" [errvar])
- [C.Ex $ C.Call "DEBUG_ERR" [errvar,
- C.StringConstant "monitor refused to accept cap for UMP send"],
- report_user_tx_err $
- C.Call "err_push" [errvar, C.Variable "LIB_ERR_MONITOR_CAP_SEND"]] []
- ]
-
cap_rx_handler :: UMPParams -> String -> [TypeDef] -> [MessageDef] -> [MsgSpec] -> C.Unit
cap_rx_handler p ifn typedefs msgdefs msgspecs
= C.FunctionDef C.Static C.Void (cap_rx_handler_name p ifn)
[C.Param (C.Ptr C.Void) "arg",
+ C.Param (C.TypeName "errval_t") "success",
C.Param (C.Struct "capref") "cap",
C.Param (C.TypeName "uint32_t") "capid"]
- [
- handler_preamble p ifn,
+ [handler_preamble p ifn,
- C.Ex $ C.Call "assert" [C.Binary C.Equals
+ C.Ex $ C.Call "assert" [C.Binary C.Equals
(C.Variable "capid")
(capst `C.FieldOf` "rx_capnum")],
- C.SBlank,
-
- C.SComment "Switch on current incoming message",
- C.Switch (C.DerefField bindvar "rx_msgnum") cases
+ C.SBlank,
+
+ C.SComment "Check if there's an associated error",
+ C.SComment "FIXME: how should we report this to the user? at present we just deliver a NULL capref",
+ C.If (C.Call "err_is_fail" [C.Variable "success"])
+ [C.Ex $ C.Call "DEBUG_ERR" [errvar,
+ C.StringConstant "error in cap transfer"]]
+ [],
+ C.SBlank,
+
+ C.SComment "Switch on current incoming message",
+ C.Switch (C.DerefField bindvar "rx_msgnum") cases
[C.Ex $ C.Call "assert"
[C.Unary C.Not $ C.StringConstant "invalid message number"],
report_user_err (C.Variable "FLOUNDER_ERR_INVALID_STATE")]
- ]
+ ]
where
umpst = C.DerefField my_bindvar "ump_state"
capst = umpst `C.FieldOf` "capst"
C.SComment "setup cap handlers",
C.Ex $ C.Assignment (C.FieldOf handlers "st") my_bindvar,
C.Ex $ C.Assignment (C.FieldOf handlers "cap_receive_handler")
- (C.Variable $ cap_rx_handler_name p ifn),
- C.Ex $ C.Assignment (C.FieldOf handlers "cap_send_reply_handler")
- (C.Variable $ cap_tx_reply_handler_name p ifn) ]
+ (C.Variable $ cap_rx_handler_name p ifn) ]
where
chanvar = my_bindvar `C.DerefField` "ump_state" `C.FieldOf` "chan"
handlers = chanvar `C.FieldOf` "cap_handlers"
static void cap_receive_request_handler(struct monitor_binding *b,
struct monitor_msg_queue_elem *e);
-static void cap_send_reply_handler(struct intermon_binding *b,
- struct intermon_msg_queue_elem *e);
struct cap_receive_request_state {
struct monitor_msg_queue_elem elem;
struct intermon_binding *b;
};
-struct cap_send_reply_state {
- struct intermon_msg_queue_elem elem;
- struct intermon_cap_send_reply__args args;
-};
-
-static void cap_send_reply_cont(struct intermon_binding *b,
- uintptr_t your_mon_id, uint32_t capid,
- errval_t err)
-{
- errval_t err2;
-
- /* Send reply back to the requesting monitor */
- err2 = b->tx_vtbl.cap_send_reply(b, NOP_CONT, your_mon_id, capid, err);
- if (err_is_fail(err2)) {
- if(err_no(err2) == FLOUNDER_ERR_TX_BUSY) {
- struct cap_send_reply_state *me =
- malloc(sizeof(struct cap_send_reply_state));
- struct intermon_state *st = b->st;
- me->args.con_id = your_mon_id;
- me->args.capid = capid;
- me->args.err = err;
- me->elem.cont = cap_send_reply_handler;
-
- err = intermon_enqueue_send(b, &st->queue, get_default_waitset(),
- &me->elem.queue);
- if (err_is_fail(err)) {
- USER_PANIC_ERR(err, "intermon_enqueue_send failed");
- }
- return;
- }
-
- USER_PANIC_ERR(err, "cap send reply to monitor failed");
- }
-}
-
-static void cap_send_reply_handler(struct intermon_binding *b,
- struct intermon_msg_queue_elem *e)
-{
- struct cap_send_reply_state *st = (struct cap_send_reply_state *)e;
- cap_send_reply_cont(b, st->args.con_id, st->args.capid, st->args.err);
- free(e);
-}
-
static void
cap_receive_request_enqueue(struct monitor_binding *domain_binding,
- uintptr_t domain_id, struct capref cap,
- uint32_t capid, uintptr_t your_mon_id,
- struct intermon_binding *b)
+ uintptr_t domain_id, errval_t msgerr,
+ struct capref cap, uint32_t capid,
+ uintptr_t your_mon_id,
+ struct intermon_binding *b)
{
errval_t err;
malloc(sizeof(struct cap_receive_request_state));
assert(me != NULL);
me->args.conn_id = domain_id;
+ me->args.err = msgerr;
me->args.cap = cap;
me->args.capid = capid;
me->your_mon_id = your_mon_id;
static void
cap_receive_request_cont(struct monitor_binding *domain_binding,
- uintptr_t domain_id, struct capref cap,
+ uintptr_t domain_id, errval_t msgerr,
+ struct capref cap,
uint32_t capid, uintptr_t your_mon_id,
struct intermon_binding *b)
{
cont = MKCONT(destroy_outgoing_cap, capp);
}
err = domain_binding->tx_vtbl.
- cap_receive_request(domain_binding, cont, domain_id, cap, capid);
+ cap_receive_request(domain_binding, cont, domain_id, msgerr, cap, capid);
if (err_is_fail(err)) {
free(capp);
if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
- cap_receive_request_enqueue(domain_binding, domain_id, cap, capid,
- your_mon_id, b);
- return;
- }
-
- if (!capref_is_null(cap)) {
- err2 = cap_destroy(cap);
- if (err_is_fail(err2)) {
- USER_PANIC_ERR(err, "cap_destroy failed");
+ cap_receive_request_enqueue(domain_binding, domain_id, msgerr, cap,
+ capid, your_mon_id, b);
+ } else {
+ if (!capref_is_null(cap)) {
+ err2 = cap_destroy(cap);
+ if (err_is_fail(err2)) {
+ USER_PANIC_ERR(err, "cap_destroy failed");
+ }
}
- err = err_push(err, MON_ERR_CAP_SEND);
- }
- goto reply;
- }
-
-reply:
- if(err_is_fail(err)) {
- cap_send_reply_cont(b, your_mon_id, capid, err);
+ // TODO: handle sanely: kill dispatcher/teardown binding/etc.
+ USER_PANIC_ERR(err, "error delivering cap to local dispatcher");
+ }
}
}
{
struct cap_receive_request_state *st =
(struct cap_receive_request_state *)e;
- cap_receive_request_cont(b, st->args.conn_id, st->args.cap, st->args.capid,
- st->your_mon_id, st->b);
+ cap_receive_request_cont(b, st->args.conn_id, st->args.err, st->args.cap,
+ st->args.capid, st->your_mon_id, st->b);
free(e);
}
static void cap_send_request(struct intermon_binding *b,
mon_id_t my_mon_id, uint32_t capid,
- intermon_caprep_t caprep,
+ intermon_caprep_t caprep, errval_t msgerr,
bool give_away, bool remote_has_desc,
intermon_coremask_t on_cores,
bool null_cap)
err = slot_alloc(&cap);
if (err_is_fail(err)) {
err = err_push(err, LIB_ERR_SLOT_ALLOC);
- goto reply;
+ goto send_error;
}
err = monitor_cap_create(cap, capability, core_id);
}
+do_send: ;
/* Get the user domain's connection and connection id */
struct monitor_binding *domain_binding = conn->domain_binding;
uintptr_t domain_id = conn->domain_id;
/* Try to send cap to the user domain, but only if the queue is empty */
struct monitor_state *mst = domain_binding->st;
if (msg_queue_is_empty(&mst->queue)) {
- cap_receive_request_cont(domain_binding, domain_id, cap, capid,
+ cap_receive_request_cont(domain_binding, domain_id, msgerr, cap, capid,
your_mon_id, b);
} else {
// don't allow sends to bypass the queue
- cap_receive_request_enqueue(domain_binding, domain_id, cap, capid,
+ cap_receive_request_enqueue(domain_binding, domain_id, msgerr, cap, capid,
your_mon_id, b);
}
- goto out;
+ free(on_cores);
+ return;
cleanup2:
err2 = cap_destroy(cap);
if (err_is_fail(err2)) {
USER_PANIC_ERR(err2, "slot_free failed");
}
-reply:
- cap_send_reply_cont(b, your_mon_id, capid, err);
-out:
- free(on_cores);
-}
-
-struct monitor_cap_send_reply_state {
- struct monitor_msg_queue_elem elem;
- struct monitor_cap_send_reply__args args;
-};
-
-static void monitor_cap_send_reply_handler(struct monitor_binding *b,
- struct monitor_msg_queue_elem *e);
-
-static void monitor_cap_send_reply_cont(struct monitor_binding *domain_binding,
- uintptr_t domain_id, uint32_t capid,
- errval_t msgerr)
-{
- errval_t err;
-
- err = domain_binding->tx_vtbl.cap_send_reply(domain_binding, NOP_CONT,
- domain_id, capid, msgerr);
- if (err_is_fail(err)) {
- if(err_no(err) == FLOUNDER_ERR_TX_BUSY) {
- struct monitor_cap_send_reply_state *me =
- malloc(sizeof(struct monitor_cap_send_reply_state));
- struct monitor_state *st = domain_binding->st;
- me->args.conn_id = domain_id;
- me->args.capid = capid;
- me->args.err = msgerr;
- me->elem.cont = monitor_cap_send_reply_handler;
-
- err = monitor_enqueue_send(domain_binding, &st->queue,
- get_default_waitset(), &me->elem.queue);
- if (err_is_fail(err)) {
- USER_PANIC_ERR(err, "monitor_enqueue_send failed");
- }
- return;
- }
-
- USER_PANIC_ERR(err, "cap send reply to user failed");
- }
-}
-
-static void monitor_cap_send_reply_handler(struct monitor_binding *b,
- struct monitor_msg_queue_elem *e)
-{
- struct monitor_cap_send_reply_state *st =
- (struct monitor_cap_send_reply_state *)e;
- monitor_cap_send_reply_cont(b, st->args.conn_id,
- st->args.capid, st->args.err);
- free(e);
-}
-
-static void cap_send_reply(struct intermon_binding *binding,
- con_id_t con_id, uint32_t capid,
- errval_t msgerr)
-{
- struct remote_conn_state *conn = remote_conn_lookup(con_id);
- assert(conn != NULL);
-
- /* Forward reply */
- uintptr_t domain_id = conn->domain_id;
- struct monitor_binding *domain_binding = conn->domain_binding;
- monitor_cap_send_reply_cont(domain_binding, domain_id, capid, msgerr);
+send_error:
+ msgerr = err;
+ cap = NULL_CAP;
+ goto do_send;
}
static void span_domain_request(struct intermon_binding *b,
.spawnd_image_request = spawnd_image_request,
.cap_send_request = cap_send_request,
- .cap_send_reply = cap_send_reply,
.span_domain_request = span_domain_request,
.span_domain_reply = span_domain_reply,
uint32_t capid;
uint8_t give_away;
struct capability capability;
+ errval_t msgerr;
bool has_descendants;
coremask_t on_cores;
};
static void cap_send_request_2(uintptr_t my_mon_id, struct capref cap,
uint32_t capid, struct capability capability,
+ errval_t msgerr,
uint8_t give_away, bool has_descendants,
coremask_t on_cores);
assert (err_is_ok(err));
} else {
cap_send_request_2(st->my_mon_id, st->cap, st->capid, st->capability,
- st->give_away, st->has_descendants, st->on_cores);
+ st->msgerr, st->give_away, st->has_descendants,
+ st->on_cores);
}
}
uintptr_t my_mon_id, struct capref cap,
uint32_t capid, uint8_t give_away)
{
- errval_t err;
+ errval_t err, msgerr = SYS_ERR_OK;
struct capability capability;
bool has_descendants;
coremask_t on_cores;
+ if (!capref_is_null(cap)) {
+ err = monitor_cap_identify(cap, &capability);
+ if (err_is_fail(err)) {
+ USER_PANIC_ERR(err, "monitor_cap_identify failed, ignored");
+ return;
+ }
+
+ // if we can't transfer the cap, it is delivered as NULL
+ if (!monitor_can_send_cap(&capability)) {
+ cap = NULL_CAP;
+ msgerr = MON_ERR_CAP_SEND;
+ }
+ }
+
if (capref_is_null(cap)) {
// we don't care about capabilities, has_descendants, or on_cores here,
// make the compiler happy though
static struct capability null_capability;
static coremask_t null_mask;
cap_send_request_2(my_mon_id, cap, capid, null_capability,
- give_away, false, null_mask);
- return;
- }
-
- err = monitor_cap_identify(cap, &capability);
- if (err_is_fail(err)) {
- USER_PANIC_ERR(err, "monitor_cap_identify failed, ignored");
- return;
- }
-
- if (!monitor_can_send_cap(&capability)) {
- struct remote_conn_state *rcs = remote_conn_lookup(my_mon_id);
- err = b->tx_vtbl.cap_send_reply(b, NOP_CONT, rcs->domain_id, capid,
- MON_ERR_CAP_SEND);
- assert(err_is_ok(err));
- return;
- }
-
- if (!give_away) {
+ msgerr, give_away, false, null_mask);
+ } else if (!give_away) {
if (!rcap_db_exists(&capability)) {
err = monitor_cap_remote(cap, true, &has_descendants);
if (err_is_fail(err)) {
send_cap_st->cap = cap;
send_cap_st->capability = capability;
send_cap_st->capid = capid;
+ send_cap_st->msgerr = msgerr;
send_cap_st->give_away = give_away;
send_cap_st->has_descendants = has_descendants;
send_cap_st->on_cores = on_cores;
assert (err_is_ok(err));
// continues in cap_send_request_2 (after cap_send_request_cb)
- } else {
+ } else { // give_away cap
err = monitor_cap_remote(cap, true, &has_descendants);
if (err_is_fail(err)) {
USER_PANIC_ERR(err, "monitor_cap_remote failed");
// TODO ensure that no more copies of this cap are on this core
static coremask_t null_mask;
// call continuation directly
- cap_send_request_2(my_mon_id, cap, capid, capability, give_away,
+ cap_send_request_2(my_mon_id, cap, capid, capability, msgerr, give_away,
has_descendants, null_mask);
}
}
struct intermon_msg_queue_elem elem;
uintptr_t your_mon_id;
uint32_t capid;
+ errval_t msgerr;
intermon_caprep_t caprep;
uint8_t give_away;
bool has_descendants;
struct cap_send_request_state *st = (struct cap_send_request_state*)e;
err = b->tx_vtbl.cap_send_request(b, NOP_CONT, st->your_mon_id, st->capid,
- st->caprep, st->give_away,
+ st->caprep, st->msgerr, st->give_away,
st->has_descendants, st->on_cores.bits,
st->null_cap);
if (err_is_fail(err)) {
ms->your_mon_id = st->your_mon_id;
ms->capid = st->capid;
ms->caprep = st->caprep;
+ ms->msgerr = st->msgerr;
ms->give_away = st->give_away;
ms->has_descendants = st->has_descendants;
ms->on_cores = st->on_cores;
static void cap_send_request_2(uintptr_t my_mon_id, struct capref cap,
uint32_t capid, struct capability capability,
+ errval_t msgerr,
uint8_t give_away, bool has_descendants,
coremask_t on_cores)
{
err = binding->tx_vtbl.
cap_send_request(binding, NOP_CONT, your_mon_id, capid,
- caprep, give_away, has_descendants, on_cores.bits,
+ caprep, msgerr, give_away, has_descendants, on_cores.bits,
null_cap);
if (err_is_fail(err)) {
if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
ms->your_mon_id = your_mon_id;
ms->capid = capid;
ms->caprep = caprep;
+ ms->msgerr = msgerr;
ms->give_away = give_away;
ms->has_descendants = has_descendants;
ms->on_cores = on_cores;
static inline void multihop_cap_send_intermon_forward(
struct intermon_binding *b, multihop_vci_t vci, uint8_t direction,
- uint32_t capid, intermon_caprep_t caprep, bool null_cap);
+ uint32_t capid, errval_t msgerr, intermon_caprep_t caprep, bool null_cap);
static void multihop_cap_send_forward_cont(struct monitor_binding *b,
struct monitor_msg_queue_elem *e);
inline static void multihop_cap_send_forward(struct monitor_binding *b,
- multihop_vci_t vci, uint8_t direction, uint32_t capid, struct capref cap);
-
-inline static void multihop_intermon_cap_send_reply(struct intermon_binding *b,
- multihop_vci_t vci, uint8_t direction, uint32_t capid, errval_t err);
-
-inline static void multihop_monitor_cap_send_reply(
- struct monitor_binding *mon_binding, multihop_vci_t vci, uint8_t direction,
- uint32_t capid, errval_t msgerr);
+ multihop_vci_t vci, uint8_t direction, uint32_t capid, errval_t msgerr,
+ struct capref cap);
// intermonitor capability forwarding state
struct multihop_intermon_capability_forwarding_state {
*/
static void multihop_cap_send_request_handler(
struct monitor_binding *monitor_binding, multihop_vci_t vci,
- uint8_t direction, struct capref cap, uint32_t capid)
+ uint8_t direction, errval_t msgerr, struct capref cap, uint32_t capid)
{
MULTIHOP_DEBUG(
bool null_cap = capref_is_null(cap);
bool has_descendants;
+ // XXX: this field is ignored when the local dispatcher originates the cap
+ msgerr = SYS_ERR_OK;
+
// get forwarding information
struct monitor_multihop_chan_state *chan_state = forwarding_table_lookup(
vci);
struct intermon_binding *b = dir->binding.intermon_binding;
if (!null_cap) {
-
// get binary representation of capability
err = monitor_cap_identify(cap, &capability);
if (err_is_fail(err)) {
return;
}
+ // if we can't transfer the cap, it is delivered as NULL
if (!monitor_can_send_cap(&capability)) {
-
- // if we can't send this capability, we send an reply back
- // the the dispatcher
- direction = multihop_get_opposite_direction(chan_state, direction,
- &dir);
- multihop_monitor_cap_send_reply(dir->binding.monitor_binding,
- dir->vci, direction, capid, MON_ERR_CAP_SEND);
- return;
+ cap = NULL_CAP;
+ null_cap = true;
+ msgerr = MON_ERR_CAP_SEND;
}
+ }
+
+ if (!null_cap) {
+ // FIXME: this seems to be totally bogus. it assumes a give_away cap -AB
// mark capability as remote
err = monitor_cap_remote(cap, true, &has_descendants);
me->args.vci = dir->vci;
me->args.direction = direction;
me->args.capid = capid;
+ me->args.err = msgerr;
me->args.cap = caprep;
me->args.null_cap = null_cap;
me->elem.cont = multihop_cap_send_intermon_forward_cont;
struct multihop_intermon_capability_forwarding_state *st =
(struct multihop_intermon_capability_forwarding_state *) e;
multihop_cap_send_intermon_forward(b, st->args.vci, st->args.direction,
- st->args.capid, st->args.cap, st->args.null_cap);
+ st->args.capid, st->args.err, st->args.cap, st->args.null_cap);
free(e);
}
*/
static inline void multihop_cap_send_intermon_forward(
struct intermon_binding *b, multihop_vci_t vci, uint8_t direction,
- uint32_t capid, intermon_caprep_t caprep, bool null_cap)
+ uint32_t capid, errval_t msgerr, intermon_caprep_t caprep, bool null_cap)
{
errval_t err;
// try to forward
- err = b->tx_vtbl.multihop_cap_send(b, NOP_CONT, vci, direction, capid,
+ err = b->tx_vtbl.multihop_cap_send(b, NOP_CONT, vci, direction, capid, msgerr,
caprep, null_cap);
if (err_is_fail(err)) {
me->args.vci = vci;
me->args.direction = direction;
me->args.capid = capid;
+ me->args.err = msgerr;
me->args.cap = caprep;
me->args.null_cap = null_cap;
me->elem.cont = multihop_cap_send_intermon_forward_cont;
*/
static void multihop_intermon_cap_send_handler(
struct intermon_binding *intermon_binding, multihop_vci_t vci,
- uint8_t direction, uint32_t capid, intermon_caprep_t caprep,
- bool null_cap)
+ uint8_t direction, uint32_t capid, errval_t msgerr,
+ intermon_caprep_t caprep, bool null_cap)
{
MULTIHOP_DEBUG(
err = slot_alloc(&cap);
if (err_is_fail(err)) {
- // send a reply back indicating that we failed
+ // send a msg indicating that we failed
// to allocate a slot for the capability
- direction = multihop_get_opposite_direction(chan_state,
- direction, &dir);
- multihop_intermon_cap_send_reply(dir->binding.intermon_binding,
- direction, dir->vci, capid, err);
- return;
+ cap = NULL_CAP;
+ msgerr = err;
+ goto do_send;
}
// create capability
if (err_is_fail(err)) {
slot_free(cap);
- // send a reply back indicating that we failed
+ // send a msg indicating that we failed
// to create the capability
- err = err_push(err, MON_ERR_CAP_CREATE);
- direction = multihop_get_opposite_direction(chan_state,
- direction, &dir);
- multihop_intermon_cap_send_reply(dir->binding.intermon_binding,
- dir->vci, direction, capid, err);
- return;
+ cap = NULL_CAP;
+ msgerr = err_push(err, MON_ERR_CAP_CREATE);
+ goto do_send;
}
// mark capability as remote
}
}
+do_send: ;
// enqueue the capability in order to be forwarded to
// the local dispatcher
struct monitor_binding *b = dir->binding.monitor_binding;
me->args.direction = direction;
me->args.cap = cap;
me->args.capid = capid;
+ me->args.err = msgerr;
me->elem.cont = multihop_cap_send_forward_cont;
err = monitor_enqueue_send(b, &ist->queue, get_default_waitset(),
me->args.vci = dir->vci;
me->args.direction = direction;
me->args.capid = capid;
+ me->args.err = msgerr;
me->args.cap = caprep;
me->args.null_cap = null_cap;
me->elem.cont = multihop_cap_send_intermon_forward_cont;
struct multihop_capability_forwarding_state *st =
(struct multihop_capability_forwarding_state *) e;
multihop_cap_send_forward(b, st->args.vci, st->args.direction,
- st->args.capid, st->args.cap);
+ st->args.capid, st->args.err, st->args.cap);
free(e);
}
*
*/
inline static void multihop_cap_send_forward(struct monitor_binding *b,
- multihop_vci_t vci, uint8_t direction, uint32_t capid, struct capref cap)
+ multihop_vci_t vci, uint8_t direction, uint32_t capid, errval_t msgerr,
+ struct capref cap)
{
errval_t err;
// try to send
- err = b->tx_vtbl.multihop_cap_send(b, NOP_CONT, vci, direction, cap, capid);
+ err = b->tx_vtbl.multihop_cap_send(b, NOP_CONT, vci, direction, msgerr,
+ cap, capid);
if (err_is_fail(err)) {
if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
me->args.direction = direction;
me->args.cap = cap;
me->args.capid = capid;
+ me->args.err = msgerr;
me->elem.cont = multihop_cap_send_forward_cont;
err = monitor_enqueue_send_at_front(b, &ist->queue,
}
}
-// intermonitor capability reply forwarding state
-struct multihop_intermon_cap_send_reply_state {
- struct intermon_msg_queue_elem elem;
- struct intermon_multihop_cap_reply__args args;
-};
-
-// continue function for intermonitor capability reply forwarding
-static void multihop_intermon_cap_send_reply_busy_cont(
- struct intermon_binding *b, struct intermon_msg_queue_elem *e)
-{
- struct multihop_intermon_cap_send_reply_state *st =
- (struct multihop_intermon_cap_send_reply_state *) e;
- multihop_intermon_cap_send_reply(b, st->args.vci, st->args.direction,
- st->args.capid, st->args.err);
- free(e);
-}
-
-/**
- * Forward a reply to next monitor
- */
-inline static void multihop_intermon_cap_send_reply(struct intermon_binding *b,
- multihop_vci_t vci, uint8_t direction, uint32_t capid, errval_t err)
-{
-
- errval_t err2;
- err2 = b->tx_vtbl.multihop_cap_reply(b, NOP_CONT, vci, direction, capid,
- err);
-
- if (err_is_fail(err2)) {
- if (err_no(err2) == FLOUNDER_ERR_TX_BUSY) {
-
- struct multihop_intermon_cap_send_reply_state *me = malloc(
- sizeof(struct multihop_intermon_cap_send_reply_state));
- struct intermon_state *ist = b->st;
- me->args.vci = vci;
- me->args.direction = direction;
- me->args.capid = capid;
- me->args.err = err;
- me->elem.cont = multihop_intermon_cap_send_reply_busy_cont;
-
- err2 = intermon_enqueue_send(b, &ist->queue, get_default_waitset(),
- &me->elem.queue);
- assert(err_is_ok(err2));
- return;
- }
-
- USER_PANIC_ERR(err2,
- "Could not forward cap reply over multi-hop channel\n");
- }
-}
-
-// struct for reply monitor forwarding state
-struct multihop_monitor_cap_send_reply_state {
- struct monitor_msg_queue_elem elem;
- struct monitor_multihop_cap_reply__args args;
-};
-
-// continue function for monitor capability reply forwarding
-static void multihop_monitor_cap_send_reply_busy_cont(struct monitor_binding *b,
- struct monitor_msg_queue_elem *e)
-{
- struct multihop_monitor_cap_send_reply_state *st =
- (struct multihop_monitor_cap_send_reply_state *) e;
- multihop_monitor_cap_send_reply(b, st->args.vci, st->args.direction,
- st->args.capid, st->args.err);
- free(e);
-}
-
-/**
- * Forward a reply message to a local dispatcher
- */
-inline static void multihop_monitor_cap_send_reply(
- struct monitor_binding *mon_binding, multihop_vci_t vci, uint8_t direction,
- uint32_t capid, errval_t msgerr)
-{
-
- errval_t err;
- err = mon_binding->tx_vtbl.multihop_cap_reply(mon_binding, NOP_CONT, vci,
- direction, capid, msgerr);
-
- if (err_is_fail(err)) {
- if (err_no(err) == FLOUNDER_ERR_TX_BUSY) {
- struct multihop_monitor_cap_send_reply_state *me = malloc(
- sizeof(struct multihop_monitor_cap_send_reply_state));
- assert(me != NULL);
- struct monitor_state *ist = mon_binding->st;
- me->args.vci = vci;
- me->args.direction = direction;
- me->args.capid = capid;
- me->args.err = msgerr;
- me->elem.cont = multihop_monitor_cap_send_reply_busy_cont;
-
- err = monitor_enqueue_send(mon_binding, &ist->queue,
- get_default_waitset(), &me->elem.queue);
- assert(err_is_ok(err));
- return;
- }
- }
-}
-
-/**
- * \brief Handler a capability reply coming from another monitor
- */
-static void multihop_intermon_cap_reply_handler(
- struct intermon_binding *intermon_binding, multihop_vci_t vci,
- uint8_t direction, uint32_t capid, errval_t msgerr)
-{
- struct monitor_multihop_chan_state *chan_state = forwarding_table_lookup(
- vci);
- struct direction *dir = multihop_get_direction(chan_state, direction);
-
- if (dir->type == MULTIHOP_ENDPOINT) { // we have to forward the reply to a local dispatcher
- multihop_monitor_cap_send_reply(dir->binding.monitor_binding, dir->vci,
- direction, capid, msgerr);
- } else {
- // we have to forward the reply to the next hop
- multihop_intermon_cap_send_reply(dir->binding.intermon_binding,
- dir->vci, direction, capid, msgerr);
- }
-}
-
///////////////////////////////////////////////////////
// INITIALIZATION
&multihop_intermon_bind_reply_handler;
ib->rx_vtbl.multihop_message = &intermon_multihop_message_handler;
ib->rx_vtbl.multihop_cap_send = &multihop_intermon_cap_send_handler;
- ib->rx_vtbl.multihop_cap_reply = &multihop_intermon_cap_reply_handler;
ib->rx_vtbl.multihop_routing_table_request =
&multihop_handle_routing_table_request;
ib->rx_vtbl.multihop_routing_table_response =