void thread_set_mask_channels(bool m);
bool thread_get_mask_channels(void);
+void thread_store_recv_slot(struct capref recv_slot);
+struct capref thread_get_next_recv_slot(void);
+
extern __thread thread_once_t thread_once_local_epoch;
extern void thread_once_internal(thread_once_t *control, void (*func)(void));
}
/**
+ * \brief Store receive slot provided by rpc in thread state
+ */
+void thread_store_recv_slot(struct capref recv_slot)
+{
+ struct thread *me = thread_self();
+ assert(me);
+
+ assert(me->recv_slot_count < 15);
+
+ me->recv_slots[me->recv_slot_count++] = recv_slot;
+}
+
+struct capref thread_get_next_recv_slot(void)
+{
+ struct thread *me = thread_self();
+
+ if (me->recv_slot_count == 0) {
+ return NULL_CAP;
+ }
+
+ return me->recv_slots[--me->recv_slot_count];
+}
+
+/**
* \brief Yield the calling thread
*
* Switches to the next runnable thread in this dispatcher, or if none is
[],
C.SBlank,
- C.SComment "allocate a new receive slot if we're not in RPC and used the last one",
- C.If (need_slot_alloc "cap")
- [C.Ex $ C.Assignment errvar $
- C.Call "lmp_chan_alloc_recv_slot" [chanaddr],
- C.If (C.Call "err_is_fail" [errvar])
- [report_user_err $
- C.Call "err_push" [errvar, C.Variable "LIB_ERR_LMP_ALLOC_RECV_SLOT"]]
- []
- ] [],
+ C.SComment "get or allocate a new receive slot if needed",
+ C.If (C.Unary C.Not $ C.Call "capref_is_null" [C.Variable "cap"])
+ [
+ localvar (C.TypeName "struct capref") "nextslot" (Just (
+ C.Call "thread_get_next_recv_slot" []
+ )),
+ C.If (C.Call "capref_is_null" [ C.Variable "nextslot" ]) [
+ C.Ex $ C.Assignment errvar $
+ C.Call "lmp_chan_alloc_recv_slot" [chanaddr],
+ C.If (C.Call "err_is_fail" [errvar])
+ [report_user_err $
+ C.Call "err_push" [errvar, C.Variable "LIB_ERR_LMP_ALLOC_RECV_SLOT"]]
+ []
+ ] [
+ C.Ex $ C.Call "lmp_chan_set_recv_slot" [chanaddr, C.Variable "nextslot" ]
+ ]
+ ] [],
C.SBlank,
C.SComment "is this the start of a new message?",
| (afl, word) <- zip wl [0..]],
case cap of
Just (CapFieldTransfer _ af) -> C.StmtList [
- C.SComment "Update recv slot if we're in RPC, otherwise we do slot alloc earlier",
- C.If in_rpc [
- C.If (C.Unary C.Not (C.Call "capref_is_null" [(argfield_expr RX mn af)]))
- [
- C.Ex $ C.Call "lmp_chan_set_recv_slot"
- [chanaddr, (argfield_expr RX mn af)]
- ] [
- C.Ex $ C.Call "assert"
- [C.Unary C.Not (C.StringConstant
- "Flounder LMP: cap RX in RPC, but no new recv slot provided")]
- ]
- ] [],
- C.SComment "Store received cap in provided capref",
C.Ex $ C.Assignment (argfield_expr RX mn af) (C.Variable "cap")
]
Nothing -> C.StmtList [],
is_cap_arg (Arg _ _) = False
rx_cap_args = filter is_cap_arg rxargs
binding_save_rx_slot (Arg tr (Name an)) = C.Ex $
- C.Assignment (rpc_rx_union_elem n an) (C.DerefPtr $ C.Variable an)
+ C.Call "thread_store_recv_slot" [(C.DerefPtr $ C.Variable an)]
binding_save_rx_slots = C.StmtList [ binding_save_rx_slot c | c <- rx_cap_args ]
token_name = "token"
outgoing_token = bindvar `C.DerefField` "outgoing_token"