diff --git a/base-nova/include/base/bit_allocator.h b/base-nova/include/base/bit_allocator.h
new file mode 100644
index 000000000..4cc966b3a
--- /dev/null
+++ b/base-nova/include/base/bit_allocator.h
@@ -0,0 +1,67 @@
+/*
+ * \brief Allocator using bitmaps to maintain cap space
+ * \author Alexander Boettcher
+ * \date 2012-06-14
+ */
+
+/*
+ * Copyright (C) 2012 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _INCLUDE__BASE__BIT_ALLOCATOR_H_
+#define _INCLUDE__BASE__BIT_ALLOCATOR_H_
+
+#include
+
+namespace Genode {
+
+ template
+ class Bit_allocator
+ {
+ protected:
+ Bit_array _array;
+
+ void _reserve(addr_t bit_start, size_t const num_cap)
+ {
+ if (!num_cap) return;
+
+ _array.set(bit_start, num_cap);
+ }
+
+ public:
+
+ addr_t alloc(size_t const num_log2)
+ {
+ addr_t const step = 1UL << num_log2;
+ addr_t i = 0;
+
+ try {
+ /*
+ * Throws exception if array is
+ * accessed outside bounds
+ */
+ while (true) {
+ if (_array.get(i, step)) {
+ i += step;
+ continue;
+ }
+ _array.set(i, step);
+ return i;
+ }
+ } catch (Bit_array_invalid_index_access) {}
+
+ throw Bit_array_out_of_indexes();
+ }
+
+ void free(addr_t const bit_start,
+ size_t const num_log2)
+ {
+ _array.clear(bit_start, 1UL << num_log2);
+ }
+
+ };
+}
+#endif /* _INCLUDE__BASE__BIT_ALLOCATOR_H_ */
diff --git a/base-nova/include/base/bit_array.h b/base-nova/include/base/bit_array.h
new file mode 100644
index 000000000..165195c6b
--- /dev/null
+++ b/base-nova/include/base/bit_array.h
@@ -0,0 +1,131 @@
+/*
+ * \brief Allocator using bitmaps to maintain cap space
+ * \author Alexander Boettcher
+ * \date 2012-06-14
+ */
+
+/*
+ * Copyright (C) 2012 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _INCLUDE__BASE__BIT_ARRAY_H_
+#define _INCLUDE__BASE__BIT_ARRAY_H_
+
+#include
+
+namespace Genode {
+
+ class Bit_array_invalid_index_access{};
+ class Bit_array_invalid_clear{};
+ class Bit_array_invalid_set{};
+ class Bit_array_out_of_indexes{};
+
+ template
+ class Bit_array
+ {
+ private:
+
+ enum {
+ _BITS_PER_BYTE = 8UL,
+ _BITS_PER_WORD = sizeof(addr_t) * _BITS_PER_BYTE,
+ };
+
+ addr_t _words[WORDS];
+
+ addr_t _word(addr_t index) const
+ {
+ return index / _BITS_PER_WORD;
+ }
+
+ void _check_range(addr_t const index,
+ addr_t const width) const
+ {
+ if ((index >= WORDS * _BITS_PER_WORD) ||
+ width > WORDS * _BITS_PER_WORD ||
+ WORDS * _BITS_PER_WORD - width < index)
+ throw Bit_array_invalid_index_access();
+ }
+
+ addr_t _mask(addr_t const index, addr_t const width,
+ addr_t &rest) const
+ {
+ addr_t const shift = index - _word(index) * _BITS_PER_WORD;
+
+ rest = width + shift > _BITS_PER_WORD ?
+ width + shift - _BITS_PER_WORD : 0;
+
+ if (width >= _BITS_PER_WORD)
+ return ~0UL << shift;
+ else
+ return ((1UL << width) - 1) << shift;
+
+ }
+
+ void _set(addr_t index, addr_t width, bool free)
+ {
+ _check_range(index, width);
+
+ addr_t rest, word, mask;
+ do {
+ word = _word(index);
+ mask = _mask(index, width, rest);
+
+ if (free) {
+ if ((_words[word] & mask) != mask)
+ throw Bit_array_invalid_clear();
+ _words[word] &= ~mask;
+ } else {
+ if (_words[word] & mask)
+ throw Bit_array_invalid_set();
+ _words[word] |= mask;
+ }
+
+ index = (_word(index) + 1) * _BITS_PER_WORD;
+ width = rest;
+
+ } while (rest);
+ }
+
+ public:
+
+ Bit_array()
+ {
+ for (addr_t i = 0; i < WORDS; i++) _words[i] = 0UL;
+ }
+
+ /**
+ * Return true if at least one bit is set between
+ * index until index + width - 1
+ */
+ bool get(addr_t index, addr_t width) const
+ {
+ _check_range(index, width);
+
+ bool used = false;
+ addr_t rest, mask;
+ do {
+ mask = _mask(index, width, rest);
+ used = _words[_word(index)] & mask;
+ index = (_word(index) + 1) * _BITS_PER_WORD;
+ width = rest;
+ } while (!used && rest);
+
+ return used;
+ }
+
+ void set(addr_t const index, addr_t const width)
+ {
+ _set(index, width, false);
+ }
+
+ void clear(addr_t const index, addr_t const width)
+ {
+ _set(index, width, true);
+ }
+ };
+
+}
+#endif /* _INCLUDE__BASE__BIT_ARRAY_H_ */
diff --git a/base-nova/include/base/cap_sel_alloc.h b/base-nova/include/base/cap_sel_alloc.h
index 6ec0671af..b7b4a4e9c 100644
--- a/base-nova/include/base/cap_sel_alloc.h
+++ b/base-nova/include/base/cap_sel_alloc.h
@@ -19,17 +19,19 @@
#define _INCLUDE__BASE__CAP_SEL_ALLOC_H_
#include
+#include
+#include
namespace Genode {
- class Cap_selector_allocator
+ class Cap_selector_allocator : public Bit_allocator<4096>
{
public:
/**
* Constructor
*/
- Cap_selector_allocator();
+ Cap_selector_allocator();
/**
* Allocate range of capability selectors
@@ -60,6 +62,7 @@ namespace Genode {
* \return PD selector
*/
static unsigned pd_sel();
+
};
/**
diff --git a/base-nova/src/base/env/cap_sel_alloc.cc b/base-nova/src/base/env/cap_sel_alloc.cc
index 1c21d6068..614cd4a68 100644
--- a/base-nova/src/base/env/cap_sel_alloc.cc
+++ b/base-nova/src/base/env/cap_sel_alloc.cc
@@ -4,7 +4,7 @@
* \author Sebastian Sumpf
* \date 2010-01-19
*
- * This is a NOVA-specific addition to the process enviroment.
+ * This is a NOVA-specific addition to the process environment.
*/
/*
@@ -71,39 +71,32 @@ static Alloc_lock *alloc_lock()
}
-static int _cap_free;
-
-
addr_t Cap_selector_allocator::alloc(size_t num_caps_log2)
{
alloc_lock()->lock();
- int num_caps = 1 << num_caps_log2;
- int ret_base = (_cap_free + num_caps - 1) & ~(num_caps - 1);
- _cap_free = ret_base + num_caps;
+ addr_t ret_base = Bit_allocator::alloc(num_caps_log2);
alloc_lock()->unlock();
return ret_base;
}
-
void Cap_selector_allocator::free(addr_t cap, size_t num_caps_log2)
{
- /*
- * We don't free capability selectors because revoke is not supported
- * on NOVA yet, anyway.
- */
+ alloc_lock()->lock();
+ Bit_allocator::free(cap, num_caps_log2);
+ alloc_lock()->unlock();
+
}
unsigned Cap_selector_allocator::pd_sel() { return __local_pd_sel; }
-
-Cap_selector_allocator::Cap_selector_allocator()
+Cap_selector_allocator::Cap_selector_allocator() : Bit_allocator<4096>()
{
/* initialize lock */
alloc_lock();
/* the first free selector is used for the lock */
- _cap_free = __first_free_cap_selector + 1;
+ Bit_allocator::_reserve(0, __first_free_cap_selector + 1);
}