diff --git a/base-foc/include/base/cap_sel_alloc.h b/base-foc/include/base/cap_sel_alloc.h index 71d8eb043..396d2f830 100644 --- a/base-foc/include/base/cap_sel_alloc.h +++ b/base-foc/include/base/cap_sel_alloc.h @@ -22,28 +22,30 @@ #ifndef _INCLUDE__BASE__CAP_SEL_ALLOC_H_ #define _INCLUDE__BASE__CAP_SEL_ALLOC_H_ +/* Genode includes */ #include +#include +#include +#include +#include + +/* Fiasco.OC includes */ +namespace Fiasco { +#include +#include +} namespace Genode { class Capability_allocator { - private: + protected: - addr_t _cap_idx; - - /** - * Constructor - */ - Capability_allocator(); + Capability_allocator() {} + virtual ~Capability_allocator() {} public: - /** - * Return singleton instance of 'Capability_allocator' - */ - static Capability_allocator* allocator(); - /** * Allocate range of capability selectors * @@ -52,7 +54,18 @@ namespace Genode * \return first capability selector of allocated range, * or 0 if allocation failed */ - addr_t alloc(size_t num_caps = 1); + virtual addr_t alloc(size_t num_caps = 1) = 0; + + + /** + * Allocate or find a capability selector + * + * \param id Genode's global capability id we're looking for + * \return return a previously allocated cap-selector associated + * with the given id, or a new one, that is associated + * with the id from now on. + */ + virtual addr_t alloc_id(unsigned id) = 0; /** * Release range of capability selectors @@ -60,7 +73,152 @@ namespace Genode * \param cap first capability selector of range * \param num_caps_log2 number of capability selectors to free. */ - void free(addr_t cap, size_t num_caps = 1); + virtual void free(addr_t cap, size_t num_caps = 1) = 0; + }; + + + Capability_allocator* cap_alloc(); + + + template + class Capability_allocator_tpl : public Capability_allocator + { + private: + + /** + * Low-level lock to protect the allocator + * + * We cannot use a normal Genode lock because this lock is used by code + * executed prior the initialization of Genode. + */ + class Alloc_lock + { + private: + + int _state; + + public: + + enum State { LOCKED, UNLOCKED }; + + /** + * Constructor + */ + Alloc_lock() : _state(UNLOCKED) {} + + void lock() + { + while (!Genode::cmpxchg(&_state, UNLOCKED, LOCKED)) + Fiasco::l4_ipc_sleep(Fiasco::l4_ipc_timeout(0, 0, 500, 0)); + } + + void unlock() { _state = UNLOCKED; } + }; + + + /** + * Node in the capability cache, + * associates global cap ids with kernel-capabilities. + */ + class Cap_node : public Avl_node + { + private: + + friend class Capability_allocator_tpl; + + unsigned long _id; + addr_t _kcap; + + public: + + Cap_node() : _id(0), _kcap(0) {} + Cap_node(unsigned long id, addr_t kcap) + : _id(id), _kcap(kcap) {} + + bool higher(Cap_node *n) { + return n->_id > _id; } + + Cap_node *find_by_id(unsigned long id) + { + if (_id == id) return this; + + Cap_node *n = Avl_node::child(id > _id); + return n ? n->find_by_id(id) : 0; + } + + + unsigned long id() const { return _id; } + addr_t kcap() const { return _kcap; } + bool valid() const { return _id || _kcap; } + }; + + + addr_t _cap_idx; /* start cap-selector */ + Cap_node _data[SZ]; /* cache-nodes backing store */ + Avl_tree _tree; /* cap cache */ + Alloc_lock _lock; + + public: + + /** + * Constructor + */ + Capability_allocator_tpl() + : _cap_idx(Fiasco::Fiasco_capability::USER_BASE_CAP) { } + + + /************************************ + ** Capability_allocator interface ** + ************************************/ + + addr_t alloc(size_t num_caps) + { + _lock.lock(); + int ret_base = _cap_idx; + _cap_idx += num_caps * Fiasco::L4_CAP_SIZE; + _lock.unlock(); + return ret_base; + } + + addr_t alloc_id(unsigned id) + { + _lock.lock(); + Cap_node *n = _tree.first(); + if (n) + n = n->find_by_id(id); + _lock.unlock(); + + if (n) { + return n->kcap(); + } + + addr_t kcap = alloc(1); + + _lock.lock(); + for (unsigned i = 0; i < SZ; i++) + if (!_data[i].valid()) { + _data[i]._id = id; + _data[i]._kcap = kcap; + _tree.insert(&_data[i]); + break; + } + _lock.unlock(); + return kcap; + } + + void free(addr_t cap, size_t num_caps) + { + _lock.lock(); + + for (unsigned i = 0; i < SZ; i++) + if (!_data[i]._kcap == cap) { + _tree.remove(&_data[i]); + _data[i]._kcap = 0; + _data[i]._id = 0; + break; + } + _lock.unlock(); + } }; } diff --git a/base-foc/include/base/ipc.h b/base-foc/include/base/ipc.h index 040e3586f..414872fe9 100644 --- a/base-foc/include/base/ipc.h +++ b/base-foc/include/base/ipc.h @@ -19,7 +19,6 @@ namespace Fiasco { #include -#include #include } @@ -46,10 +45,13 @@ inline void Genode::Ipc_istream::_unmarshal_capability(Genode::Native_capability } /* allocate new cap slot and grant cap to it out of receive window */ - Genode::addr_t cap_sel = Capability_allocator::allocator()->alloc(); - l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP, - l4_obj_fpage(_rcv_msg->rcv_cap_sel(), 0, L4_FPAGE_RWX), - cap_sel | L4_ITEM_MAP | L4_MAP_ITEM_GRANT); + Genode::addr_t cap_sel = cap_alloc()->alloc_id(unique_id); + l4_msgtag_t tag = l4_task_cap_valid(L4_BASE_TASK_CAP, cap_sel); + if (!tag.label()) { + l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP, + l4_obj_fpage(_rcv_msg->rcv_cap_sel(), 0, L4_FPAGE_RWX), + cap_sel | L4_ITEM_MAP | L4_MAP_ITEM_GRANT); + } cap = Native_capability(cap_sel, unique_id); } diff --git a/base-foc/include/base/ipc_msgbuf.h b/base-foc/include/base/ipc_msgbuf.h index b276f36c6..6f1225e89 100644 --- a/base-foc/include/base/ipc_msgbuf.h +++ b/base-foc/include/base/ipc_msgbuf.h @@ -66,7 +66,7 @@ namespace Genode { * Constructor */ Msgbuf_base() - : _rcv_cap_sel_base(Capability_allocator::allocator()->alloc(MAX_CAP_ARGS)) + : _rcv_cap_sel_base(cap_alloc()->alloc(MAX_CAP_ARGS)) { rcv_reset(); snd_reset(); diff --git a/base-foc/src/base/env/cap_sel_alloc.cc b/base-foc/src/base/env/cap_sel_alloc.cc index 4e03dea45..f92598368 100644 --- a/base-foc/src/base/env/cap_sel_alloc.cc +++ b/base-foc/src/base/env/cap_sel_alloc.cc @@ -1,5 +1,5 @@ /* - * \brief Capability-selector allocator + * \brief Capability-selector allocator for non-core tasks. * \author Stefan Kalkowski * \date 2010-12-06 * @@ -15,93 +15,10 @@ /* Genode includes */ #include -#include -#include -#include -/* Fiasco.OC includes */ -namespace Fiasco { -#include -#include -} -using namespace Genode; - -/** - * First available capability selector for custom use - * - * Must be initialized by the startup code - */ -static unsigned long __first_free_cap_selector = - Fiasco::Fiasco_capability::USER_BASE_CAP; - -/** - * Low-level lock to protect the allocator - * - * We cannot use a normal Genode lock because this lock is used by code - * executed prior the initialization of Genode. - */ -class Alloc_lock +Genode::Capability_allocator* Genode::cap_alloc() { - private: - - int _state; - - public: - - enum State { LOCKED, UNLOCKED }; - - /** - * Constructor - */ - Alloc_lock() : _state(UNLOCKED) {} - - void lock() - { - while (!Genode::cmpxchg(&_state, UNLOCKED, LOCKED)) - Fiasco::l4_ipc_sleep(Fiasco::l4_ipc_timeout(0, 0, 500, 0)); - } - - void unlock() { _state = UNLOCKED; } -}; - - -/** - * Return lock used to protect capability selector allocations - */ -static Alloc_lock *alloc_lock() -{ - static Alloc_lock alloc_lock_inst; - return &alloc_lock_inst; -} - - -addr_t Capability_allocator::alloc(size_t num_caps) -{ - alloc_lock()->lock(); - int ret_base = _cap_idx; - _cap_idx += num_caps * Fiasco::L4_CAP_SIZE; - alloc_lock()->unlock(); - return ret_base; -} - - -void Capability_allocator::free(addr_t cap, size_t num_caps_log2) -{ -// PWRN("Not yet implemented!"); -} - - -Capability_allocator::Capability_allocator() -: _cap_idx(__first_free_cap_selector) -{ - /* initialize lock */ - alloc_lock(); -} - - -Capability_allocator* Capability_allocator::allocator() -{ - static Capability_allocator inst; - return &inst; + static Genode::Capability_allocator_tpl<8192> _alloc; + return &_alloc; } diff --git a/base-foc/src/core/cap_session_component.cc b/base-foc/src/core/cap_session_component.cc index 40c7a5d85..e0ca25d6f 100644 --- a/base-foc/src/core/cap_session_component.cc +++ b/base-foc/src/core/cap_session_component.cc @@ -63,14 +63,14 @@ Native_capability Cap_session_component::alloc(Cap_session_component *session, * Allocate new badge, and ipc-gate and set badge as gate-label */ unsigned long badge = Badge_allocator::allocator()->alloc(); - Native_thread gate = Capability_allocator::allocator()->alloc(); + Native_thread gate = cap_alloc()->alloc_id(badge); l4_msgtag_t tag = l4_factory_create_gate(L4_BASE_FACTORY_CAP, gate, n->pt()->native_thread(), badge); if (l4_msgtag_has_error(tag)) { PERR("l4_factory_create_gate failed!"); - Capability_allocator::allocator()->free(gate); + cap_alloc()->free(gate); Badge_allocator::allocator()->free(badge); return cap; } else @@ -117,15 +117,17 @@ void Cap_session_component::free(Native_capability cap) return; Capability_tree::tree()->remove(n); - Badge_allocator::allocator()->free(n->badge()); l4_msgtag_t tag = l4_task_unmap(L4_BASE_TASK_CAP, l4_obj_fpage(cap.dst(), 0, 0), L4_FP_ALL_SPACES | L4_FP_DELETE_OBJ); if (l4_msgtag_has_error(tag)) PERR("destruction of ipc-gate %lx failed!", (unsigned long) cap.dst()); + /* free badge _after_ invalidating all caps */ + Badge_allocator::allocator()->free(n->badge()); + /* free explicilty allocated cap-selector */ - Capability_allocator::allocator()->free(n->gate()); + cap_alloc()->free(n->gate()); destroy(platform_specific()->core_mem_alloc(), n); } @@ -228,3 +230,10 @@ Capability_tree* Capability_tree::tree() static Capability_tree _tree; return &_tree; } + + +Genode::Capability_allocator* Genode::cap_alloc() +{ + static Genode::Capability_allocator_tpl<20*1024> _alloc; + return &_alloc; +} diff --git a/base-foc/src/core/cpu_session_extension.cc b/base-foc/src/core/cpu_session_extension.cc index 40a193870..5b7001f8b 100644 --- a/base-foc/src/core/cpu_session_extension.cc +++ b/base-foc/src/core/cpu_session_extension.cc @@ -53,7 +53,7 @@ Genode::Cpu_session_component::native_cap(Genode::Thread_capability cap) Cpu_thread_component *thread = _lookup_thread(cap); if (!thread) return Native_capability(); - return Native_capability(thread->platform_thread()->native_thread(), -1); + return thread->platform_thread()->thread_cap(); } @@ -61,11 +61,11 @@ Genode::Native_capability Genode::Cpu_session_component::alloc_irq() { using namespace Fiasco; - Fiasco_capability irq_cap(Genode::Capability_allocator::allocator()->alloc()); + Fiasco_capability irq_cap(Genode::cap_alloc()->alloc()); l4_msgtag_t res = l4_factory_create_irq(L4_BASE_FACTORY_CAP, irq_cap); if (l4_error(res)) PWRN("Allocation of irq object failed!"); - return Genode::Native_capability(irq_cap, -1); + return Genode::Native_capability(irq_cap, Badge_allocator::allocator()->alloc()); } diff --git a/base-foc/src/core/include/platform_pd.h b/base-foc/src/core/include/platform_pd.h index c6c2a5f54..590c65ca0 100644 --- a/base-foc/src/core/include/platform_pd.h +++ b/base-foc/src/core/include/platform_pd.h @@ -43,6 +43,7 @@ namespace Genode { }; Native_task _l4_task_cap; /* L4 task capability slot */ + unsigned _badge; Native_capability _parent; bool _parent_cap_mapped; bool _task_cap_mapped; @@ -109,6 +110,7 @@ namespace Genode { *******************************/ Native_task native_task() { return _l4_task_cap; } + unsigned badge() { return _badge; } Native_thread parent_cap() { return _parent.dst(); } }; } diff --git a/base-foc/src/core/include/platform_thread.h b/base-foc/src/core/include/platform_thread.h index fa56ff43d..bfe47fe10 100644 --- a/base-foc/src/core/include/platform_thread.h +++ b/base-foc/src/core/include/platform_thread.h @@ -39,6 +39,7 @@ namespace Genode { friend class Platform_pd; bool _core_thread; + unsigned _badge; Native_capability _thread_cap; Native_capability _gate_cap; Native_capability _remote_gate_cap; diff --git a/base-foc/src/core/irq_session_component.cc b/base-foc/src/core/irq_session_component.cc index d88c37ae3..54fe8226a 100644 --- a/base-foc/src/core/irq_session_component.cc +++ b/base-foc/src/core/irq_session_component.cc @@ -50,7 +50,7 @@ bool Irq_session_component::Interrupt::higher(Irq_session_component::Interrupt * Irq_session_component::Interrupt::Interrupt() -: _cap(Capability_allocator::allocator()->alloc()), _sem(), number(0) {} +: _cap(cap_alloc()->alloc()), _sem(), number(0) {} Native_thread Irq_session_component::Interrupt_handler::handler_cap() diff --git a/base-foc/src/core/pd_session_extension.cc b/base-foc/src/core/pd_session_extension.cc index 661f7c33b..f4778b4e2 100644 --- a/base-foc/src/core/pd_session_extension.cc +++ b/base-foc/src/core/pd_session_extension.cc @@ -19,5 +19,4 @@ Genode::Native_capability Genode::Pd_session_component::task_cap() { - return Native_capability(_pd.native_task(), - Badge_allocator::allocator()->alloc()); } + return Native_capability(_pd.native_task(), _pd.badge()); } diff --git a/base-foc/src/core/platform_pd.cc b/base-foc/src/core/platform_pd.cc index 187e9c23e..a226c4cdb 100644 --- a/base-foc/src/core/platform_pd.cc +++ b/base-foc/src/core/platform_pd.cc @@ -44,7 +44,7 @@ static addr_t core_utcb_base() { void Platform_pd::_create_pd(bool syscall) { if (!_l4_task_cap.valid()) - _l4_task_cap = Capability_allocator::allocator()->alloc(); + _l4_task_cap = cap_alloc()->alloc(); if (syscall) { if (!_l4_task_cap) @@ -154,6 +154,7 @@ void Platform_pd::map_task_cap() Platform_pd::Platform_pd(bool create, Native_task task_cap) : _l4_task_cap(task_cap), + _badge(create ? Badge_allocator::allocator()->alloc() : 0), _parent_cap_mapped(false), _task_cap_mapped(false) { @@ -170,5 +171,7 @@ Platform_pd::~Platform_pd() if (_threads[i]) _threads[i]->unbind(); } + _destroy_pd(); + Badge_allocator::allocator()->free(_badge); } diff --git a/base-foc/src/core/platform_thread.cc b/base-foc/src/core/platform_thread.cc index af9e57666..1ab623c79 100644 --- a/base-foc/src/core/platform_thread.cc +++ b/base-foc/src/core/platform_thread.cc @@ -212,7 +212,7 @@ void Platform_thread::_create_thread() void Platform_thread::_finalize_construction(const char *name, unsigned prio) { /* create irq for new thread */ - _irq_cap = Capability_allocator::allocator()->alloc(); + _irq_cap = cap_alloc()->alloc(); l4_msgtag_t tag = l4_factory_create_irq(L4_BASE_FACTORY_CAP, _irq_cap); if (l4_msgtag_has_error(tag)) PWRN("creating thread's irq failed"); @@ -236,8 +236,9 @@ void Platform_thread::_finalize_construction(const char *name, unsigned prio) Platform_thread::Platform_thread(const char *name, unsigned prio) : _core_thread(false), - _thread_cap(Capability_allocator::allocator()->alloc(), - Badge_allocator::allocator()->alloc()), + _badge(Badge_allocator::allocator()->alloc()), + _thread_cap(cap_alloc()->alloc_id(_badge), + _badge), _node(_thread_cap.local_name(), 0, this, _thread_cap.dst()), _utcb(0), _platform_pd(0), @@ -272,8 +273,9 @@ Platform_thread::Platform_thread(Native_thread cap, const char *name) Platform_thread::Platform_thread(const char *name) : _core_thread(true), - _thread_cap(Capability_allocator::allocator()->alloc(), - Badge_allocator::allocator()->alloc()), + _badge(Badge_allocator::allocator()->alloc()), + _thread_cap(cap_alloc()->alloc_id(_badge), + _badge), _node(_thread_cap.local_name(), 0, this, _thread_cap.dst()), _utcb(0), _platform_pd(0), @@ -302,6 +304,6 @@ Platform_thread::~Platform_thread() /* remove the thread capability */ Capability_tree::tree()->remove(&_node); - Badge_allocator::allocator()->free(_thread_cap.local_name()); - Capability_allocator::allocator()->free(_thread_cap.dst()); + cap_alloc()->free(_thread_cap.dst()); + Badge_allocator::allocator()->free(_badge); } diff --git a/base-foc/src/core/signal_source_component.cc b/base-foc/src/core/signal_source_component.cc index 7c6aa15f6..339438925 100644 --- a/base-foc/src/core/signal_source_component.cc +++ b/base-foc/src/core/signal_source_component.cc @@ -19,6 +19,7 @@ /* core includes */ #include +#include namespace Fiasco { #include @@ -68,10 +69,11 @@ Signal_source_component::Signal_source_component(Rpc_entrypoint *ep) { using namespace Fiasco; - Fiasco_capability irq = Capability_allocator::allocator()->alloc(); + unsigned long badge = Badge_allocator::allocator()->alloc(); + Fiasco_capability irq = cap_alloc()->alloc_id(badge); l4_msgtag_t res = l4_factory_create_irq(L4_BASE_FACTORY_CAP, irq); if (l4_error(res)) PERR("Allocation of irq object failed!"); - _blocking_semaphore = Native_capability(irq, -1); + _blocking_semaphore = Native_capability(irq, badge); } diff --git a/base-foc/src/core/target.inc b/base-foc/src/core/target.inc index 27530aff6..eac9a047b 100644 --- a/base-foc/src/core/target.inc +++ b/base-foc/src/core/target.inc @@ -28,7 +28,6 @@ SRC_CC = main.cc \ irq_session_component.cc \ signal_session_component.cc \ signal_source_component.cc \ - cap_sel_alloc.cc \ dump_alloc.cc \ context_area.cc \ cap_session_component.cc \ @@ -53,5 +52,4 @@ vpath dump_alloc.cc $(GEN_CORE_DIR) vpath context_area.cc $(GEN_CORE_DIR) vpath thread.cc $(REP_DIR)/src/base/thread vpath thread_bootstrap.cc $(REP_DIR)/src/base/thread -vpath cap_sel_alloc.cc $(REP_DIR)/src/base/env vpath %.cc $(REP_DIR)/src/core diff --git a/ports-foc/src/lib/l4lx/include/dataspace.h b/ports-foc/src/lib/l4lx/include/dataspace.h index de1553b5f..26ba02061 100644 --- a/ports-foc/src/lib/l4lx/include/dataspace.h +++ b/ports-foc/src/lib/l4lx/include/dataspace.h @@ -50,7 +50,7 @@ namespace L4lx { Genode::size_t size, Genode::Dataspace_capability ds) : _name(name), _size(size), _cap(ds), - _ref(Genode::Capability_allocator::allocator()->alloc()) {} + _ref(Genode::cap_alloc()->alloc()) {} /*************** diff --git a/ports-foc/src/lib/l4lx/l4_re_c_dataspace.cc b/ports-foc/src/lib/l4lx/l4_re_c_dataspace.cc index 1b762294c..6a6777875 100644 --- a/ports-foc/src/lib/l4lx/l4_re_c_dataspace.cc +++ b/ports-foc/src/lib/l4lx/l4_re_c_dataspace.cc @@ -22,6 +22,7 @@ namespace Fiasco { #include #include +#include } using namespace Fiasco; diff --git a/ports-foc/src/lib/l4lx/l4_re_c_util_cap.cc b/ports-foc/src/lib/l4lx/l4_re_c_util_cap.cc index 4ca8319f9..f203ef352 100644 --- a/ports-foc/src/lib/l4lx/l4_re_c_util_cap.cc +++ b/ports-foc/src/lib/l4lx/l4_re_c_util_cap.cc @@ -28,7 +28,7 @@ extern "C" { l4_cap_idx_t l4re_util_cap_alloc(void) { - l4_cap_idx_t ret = Genode::Capability_allocator::allocator()->alloc(); + l4_cap_idx_t ret = Genode::cap_alloc()->alloc(); if (DEBUG) PDBG("ret=%lx", ret); diff --git a/ports-foc/src/lib/l4lx/l4lx_task.cc b/ports-foc/src/lib/l4lx/l4lx_task.cc index 62c1f0190..ab51c0531 100644 --- a/ports-foc/src/lib/l4lx/l4lx_task.cc +++ b/ports-foc/src/lib/l4lx/l4lx_task.cc @@ -65,7 +65,7 @@ l4_cap_idx_t l4lx_task_number_allocate(void) */ int l4lx_task_number_free(l4_cap_idx_t task) { - Genode::Capability_allocator::allocator()->free(task); + Genode::cap_alloc()->free(task); return 0; } @@ -84,7 +84,7 @@ int l4lx_task_number_free(l4_cap_idx_t task) int l4lx_task_get_new_task(l4_cap_idx_t parent_id, l4_cap_idx_t *id) { - *id = Genode::Capability_allocator::allocator()->alloc(); + *id = Genode::cap_alloc()->alloc(); return 0; }