mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 09:46:20 +00:00
Add a bit array and bit allocator, issue #247
Add a allocator using bit maps to maintain used/unused caps. It supports the allocation of 2^n aligned caps solely and freeing of caps. Fixes #247
This commit is contained in:
parent
67fdc1b44b
commit
44ef8912d6
67
base-nova/include/base/bit_allocator.h
Normal file
67
base-nova/include/base/bit_allocator.h
Normal file
@ -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 <base/bit_array.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
template<addr_t WORDS>
|
||||
class Bit_allocator
|
||||
{
|
||||
protected:
|
||||
Bit_array<WORDS> _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_ */
|
131
base-nova/include/base/bit_array.h
Normal file
131
base-nova/include/base/bit_array.h
Normal file
@ -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 <base/stdint.h>
|
||||
|
||||
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 <addr_t WORDS>
|
||||
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_ */
|
@ -19,17 +19,19 @@
|
||||
#define _INCLUDE__BASE__CAP_SEL_ALLOC_H_
|
||||
|
||||
#include <base/stdint.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/bit_allocator.h>
|
||||
|
||||
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();
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
23
base-nova/src/base/env/cap_sel_alloc.cc
vendored
23
base-nova/src/base/env/cap_sel_alloc.cc
vendored
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user