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;
}