Cleanup and doc

This commit is contained in:
Baptiste Wicht 2016-09-27 15:13:57 +02:00
parent 7343b48e8d
commit 0d567e5332
No known key found for this signature in database
GPG Key ID: C5566B6C7F884532
2 changed files with 96 additions and 24 deletions

View File

@ -1,6 +1,5 @@
//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the terms of the MIT License.
// Copyright Baptiste Wicht 2013-2016. // Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
// http://www.opensource.org/licenses/MIT)
//=======================================================================
@ -10,13 +9,15 @@
#include "assert.hpp"
/*!
* \brief A static bitmap.
*
* This bitmap cannot be extended. The data must be provided via one of its init functions.
*/
struct static_bitmap {
typedef uint64_t data_type;
using data_type = uint64_t; ///< The word type
static constexpr const size_t bits_per_word = sizeof(data_type) * 8;
size_t words;
data_type* data;
static constexpr const size_t bits_per_word = sizeof(data_type) * 8; ///< The number of bits stored in each word
template<typename Array>
void init(Array& array){
@ -29,33 +30,51 @@ struct static_bitmap {
data = d;
}
/*!
* \brief Returns the word in which the bit is
*/
static constexpr size_t word_offset(size_t bit){
return bit / bits_per_word;
}
/*!
* \brief Returns the offset of the bit inside its word
*/
static constexpr size_t bit_offset(size_t bit){
return bit % bits_per_word;
}
/*
* \brief Constructs a bit mask for the given bit
*/
static constexpr data_type bit_mask(size_t bit){
return static_cast<data_type>(1) << bit_offset(bit);
}
/*!
* \brief Clear the complete bit map (set everything to zero)
*/
void clear_all(){
for(size_t i = 0; i < words; ++i){
data[i] = 0;
}
}
/*!
* \brief Set the complete bit map (set everything to one)
*/
void set_all(){
for(size_t i = 0; i < words; ++i){
data[i] = ~static_cast<data_type>(0);
}
}
size_t free_bit() const {
/*!
* \brief Returns the first set bit in the bit map
*/
size_t set_bit() const {
for(size_t w = 0; w < words; ++w){
if(data[w] > 0){
if(data[w]){
for(size_t b = 0; b < bits_per_word; ++b){
if(data[w] & bit_mask(b)){
return w * bits_per_word + b;
@ -67,7 +86,10 @@ struct static_bitmap {
thor_unreachable("static_bitmap has no free bit");
}
size_t free_word() const {
/*!
* \brief Returns the first set word in the bit map
*/
size_t set_word() const {
for(size_t w = 0; w < words; ++w){
if(data[w] == ~static_cast<data_type>(0)){
return w * bits_per_word;
@ -77,17 +99,30 @@ struct static_bitmap {
thor_unreachable("static_bitmap has no free word");
}
/*!
* \brief Indicates if the given bit is set
*/
bool is_set(size_t bit) const {
return data[word_offset(bit)] & bit_mask(bit);
}
/*!
* \brief Sets the given bit to 1
*/
void set(size_t bit){
data[word_offset(bit)] |= bit_mask(bit);
}
/*!
* \brief clear the given bit to 1
*/
void unset(size_t bit){
data[word_offset(bit)] &= ~bit_mask(bit);
}
private:
size_t words; ///< Number of words used in the bitmap
data_type* data; ///< The data storage
};
#endif

View File

@ -13,32 +13,51 @@
#include "bitmap.hpp"
#include "logging.hpp"
/*!
* \brief Returns the nth power of x
*/
template <class T>
inline constexpr T pow(T const& x, size_t n){
return n > 0 ? x * pow(x, n - 1) : 1;
}
/*!
* \brief Buddy allocator system.
*
* This is used to allocate physical and virtual memory
*/
template<size_t Levels, size_t Unit>
struct buddy_allocator {
static constexpr const size_t levels = Levels;
static constexpr const size_t max_block = pow(2, levels - 1);
static constexpr const size_t levels = Levels; ///< The number of levels in the allocator
static constexpr const size_t max_block = pow(2, levels - 1); ///< The size of the maximum block
std::array<static_bitmap, levels> bitmaps;
std::array<static_bitmap, levels> bitmaps; ///< The bit maps for each level
size_t first_address;
size_t last_address;
size_t first_address; ///< The first managed address
size_t last_address; ///< The last managed address
public:
/*!
* \brief Sets the memory range of the allocator
*/
void set_memory_range(size_t first, size_t last){
first_address = first;
last_address = last;
}
/*!
* \brief Initialize the layer I
* \param words The number of words
* \param data The memory to use
*/
template<size_t I>
void init(size_t words, uint64_t* data){
bitmaps[I].init(words, data);
}
/*!
* \brief Initialize the allocator
*/
void init(){
//By default all blocks are free
for(auto& bitmap : bitmaps){
@ -46,6 +65,9 @@ public:
}
}
/*!
* \brief Allocate memory for the given amount of pages
*/
size_t allocate(size_t pages){
if(pages > max_block){
if(pages > max_block * static_bitmap::bits_per_word){
@ -55,7 +77,7 @@ public:
} else {
// Select a level for which a whole word can hold the necessary pages
auto l = word_level(pages);
auto index = bitmaps[l].free_word();
auto index = bitmaps[l].set_word();
auto address = block_start(l, index);
if(address + level_size(l) >= last_address){
@ -72,7 +94,7 @@ public:
}
} else {
auto l = level(pages);
auto index = bitmaps[l].free_bit();
auto index = bitmaps[l].set_bit();
auto address = block_start(l, index);
if(address + level_size(l) >= last_address){
@ -86,6 +108,11 @@ public:
}
}
/*!
* \brief Free allocated memory pages
* \param address The allocated memory
* \param pages The number of pages to free
*/
void free(size_t address, size_t pages){
if(pages > max_block){
if(pages > max_block * static_bitmap::bits_per_word){
@ -108,17 +135,17 @@ public:
}
}
/*!
* \brief The size of the given level
*/
static size_t level_size(size_t level){
size_t size = 1;
for(size_t i = 0; i < level; ++i){
size *= 2;
}
return size;
return pow(2, level);
}
private:
/*!
* \brief Returns the level to use for the given amount of pages
*/
static size_t level(size_t pages){
if(pages > 64){
return 7;
@ -153,6 +180,11 @@ private:
return levels;
}
/*!
* \brief Mark the given buddy as used
* \param l The used level
* \param index The used index
*/
void mark_used(size_t l, size_t index){
//Mark all sub blocks as taken
taken_down(l, index);
@ -164,6 +196,11 @@ private:
taken_up(l, index);
}
/*!
* \brief Mark the given buddy as free
* \param l The freed level
* \param index The freeed index
*/
void mark_free(size_t l, size_t index){
//Free all sub blocks
free_down(l, index);