From 0d567e5332f9fbf1a79a626835d28b0a52f71dc3 Mon Sep 17 00:00:00 2001 From: Baptiste Wicht Date: Tue, 27 Sep 2016 15:13:57 +0200 Subject: [PATCH] Cleanup and doc --- kernel/include/bitmap.hpp | 55 ++++++++++++++++++++----- kernel/include/buddy_allocator.hpp | 65 +++++++++++++++++++++++------- 2 files changed, 96 insertions(+), 24 deletions(-) diff --git a/kernel/include/bitmap.hpp b/kernel/include/bitmap.hpp index 1d0d27da..6a688a49 100644 --- a/kernel/include/bitmap.hpp +++ b/kernel/include/bitmap.hpp @@ -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 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(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(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(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 diff --git a/kernel/include/buddy_allocator.hpp b/kernel/include/buddy_allocator.hpp index 39acc59d..d5e4bd0a 100644 --- a/kernel/include/buddy_allocator.hpp +++ b/kernel/include/buddy_allocator.hpp @@ -13,32 +13,51 @@ #include "bitmap.hpp" #include "logging.hpp" +/*! + * \brief Returns the nth power of x + */ template 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 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 bitmaps; + std::array 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 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);