diff --git a/base-nova/include/base/ipc_msgbuf.h b/base-nova/include/base/ipc_msgbuf.h index 491da21647..887e61e532 100644 --- a/base-nova/include/base/ipc_msgbuf.h +++ b/base-nova/include/base/ipc_msgbuf.h @@ -21,9 +21,6 @@ #ifndef _INCLUDE__BASE__IPC_MSGBUF_H_ #define _INCLUDE__BASE__IPC_MSGBUF_H_ -/* Genode includes */ -#include - /* NOVA includes */ #include #include @@ -51,11 +48,7 @@ namespace Genode { /** * Portal capability selectors to delegate */ - struct { - addr_t sel; - unsigned rights; - bool trans_map; - } _snd_pt_sel [MAX_CAP_ARGS]; + Native_capability _snd_pt_sel [MAX_CAP_ARGS]; /** * Base of portal receive window @@ -117,20 +110,25 @@ namespace Genode { /** * Reset portal capability selector payload */ - inline void snd_reset() { _snd_pt_sel_cnt = 0; } + inline void snd_reset() { + + for (unsigned i = 0; i < MAX_CAP_ARGS; i++) { + +_snd_pt_sel[i]; + _snd_pt_sel[i] = Native_capability(); + } + + _snd_pt_sel_cnt = 0; + } /** * Append portal capability selector to message buffer */ - inline bool snd_append_pt_sel(addr_t pt_sel, unsigned rights, - bool trans_map) + inline bool snd_append_pt_sel(Native_capability const &cap) { if (_snd_pt_sel_cnt >= MAX_CAP_ARGS - 1) return false; - _snd_pt_sel[_snd_pt_sel_cnt ].sel = pt_sel; - _snd_pt_sel[_snd_pt_sel_cnt ].rights = rights; - _snd_pt_sel[_snd_pt_sel_cnt++].trans_map = trans_map; + _snd_pt_sel[_snd_pt_sel_cnt++ ] = cap; return true; } @@ -157,9 +155,10 @@ namespace Genode { if (i >= _snd_pt_sel_cnt) return Nova::Obj_crd(); - trans_map = _snd_pt_sel[i].trans_map; - return Nova::Obj_crd(_snd_pt_sel[i].sel, 0, - _snd_pt_sel[i].rights); + trans_map = _snd_pt_sel[i].trans_map(); + + return Nova::Obj_crd(_snd_pt_sel[i].local_name(), 0, + _snd_pt_sel[i].dst().rights()); } /** @@ -194,13 +193,15 @@ namespace Genode { /** * Return received portal-capability selector */ - addr_t rcv_pt_sel() + void rcv_pt_sel(Native_capability &cap) { + if (_rcv_pt_sel_cnt >= _rcv_pt_sel_max) { + cap = Native_capability(); + return; + } + /* return only received or translated caps */ - if (_rcv_pt_sel_cnt < _rcv_pt_sel_max) - return _rcv_pt_sel[_rcv_pt_sel_cnt++].sel; - else - return INVALID_INDEX; + cap = Native_capability(_rcv_pt_sel[_rcv_pt_sel_cnt++].sel); } /** @@ -245,37 +246,38 @@ namespace Genode { nova_die(); _rcv_pt_cap_free [_rcv_pt_sel[i].sel - rcv_pt_base()] = USED_CAP; + cap_map()->remove(_rcv_pt_sel[i].sel - rcv_pt_base(), 0); + reinit = true; } - /* revoke received caps which are unused */ - for (unsigned i = 0; i < MAX_CAP_ARGS; i++) { - if (i < new_max && _rcv_pt_cap_free[i] == FREE_INVALID) + /* if old receive window was smaller, we need to re-init */ + for (unsigned i = 0; !reinit && i < new_max; i++) + if (_rcv_pt_cap_free[i] == FREE_INVALID) reinit = true; - if (_rcv_pt_cap_free[i] == UNUSED_CAP) - Nova::revoke(Nova::Obj_crd(rcv_pt_base() + i, 0), true); - } - _rcv_pt_sel_cnt = 0; _rcv_pt_sel_max = 0; /* we can keep the cap selectors if none was used */ if (keep && !reinit) { - /* free rest of indexes if new_max is smaller then last window */ - for (unsigned i = new_max; i < MAX_CAP_ARGS; i++) - if (_rcv_pt_cap_free[i] == FREE_SEL) - cap_selector_allocator()->free(rcv_pt_base() + i, 0); + for (unsigned i = 0; i < MAX_CAP_ARGS; i++) { + /* revoke received caps which are unused */ + if (_rcv_pt_cap_free[i] == UNUSED_CAP) + Nova::revoke(Nova::Obj_crd(rcv_pt_base() + i, 0), true); + + /* free rest of indexes if new_max is smaller then last window */ + if (i >= new_max && _rcv_pt_cap_free[i] == FREE_SEL) + cap_map()->remove(rcv_pt_base() + i, 0, false); + } return false; } - /* keep used selectors, free up rest */ - for (unsigned i = 0; i < MAX_CAP_ARGS; i++) { - if (_rcv_pt_cap_free[i] == UNUSED_CAP || - _rcv_pt_cap_free[i] == FREE_SEL) - cap_selector_allocator()->free(rcv_pt_base() + i, 0); - } + /* decrease ref count if valid selector */ + for (unsigned i = 0; i < MAX_CAP_ARGS; i++) + if (_rcv_pt_cap_free[i] != FREE_INVALID) + cap_map()->remove(rcv_pt_base() + i, 0, _rcv_pt_cap_free[i] == FREE_SEL); return true; } @@ -316,10 +318,9 @@ namespace Genode { /* allocate receive window if necessary, otherwise use old one */ if (rcv_invalid() || rcv_cleanup(true, 1U << _rcv_wnd_log2)) { - try { - _rcv_pt_base = cap_selector_allocator()->alloc(_rcv_wnd_log2); - } catch (Bit_array_out_of_indexes) { - _rcv_pt_base = INVALID_INDEX; + _rcv_pt_base = cap_map()->insert(_rcv_wnd_log2); + + if (_rcv_pt_base == INVALID_INDEX) { /* no mappings can be received */ utcb->crd_rcv = Nova::Obj_crd(); return false; @@ -357,8 +358,6 @@ namespace Genode { for (unsigned short i = 0; i < MAX_CAP_ARGS; i++) _rcv_pt_cap_free [i] = (i >= max) ? FREE_INVALID : FREE_SEL; - addr_t max = 1UL << utcb->crd_rcv.order(); - for (unsigned i = 0; i < rcv_items; i++) { Utcb::Item * item = utcb->get_item(i); if (!item) diff --git a/base-nova/src/base/ipc/ipc.cc b/base-nova/src/base/ipc/ipc.cc index 1072badf7d..19a2dca1c5 100644 --- a/base-nova/src/base/ipc/ipc.cc +++ b/base-nova/src/base/ipc/ipc.cc @@ -30,17 +30,13 @@ using namespace Nova; void Ipc_ostream::_marshal_capability(Native_capability const &cap) { - if (cap.valid()) - _snd_msg->snd_append_pt_sel(cap.local_name(), - cap.dst().rights(), - cap.trans_map()); + _snd_msg->snd_append_pt_sel(cap); } void Ipc_istream::_unmarshal_capability(Native_capability &cap) { - addr_t pt_sel = _rcv_msg->rcv_pt_sel(); - cap = Native_capability(pt_sel); + _rcv_msg->rcv_pt_sel(cap); }