1  /*
   2   * \brief  Allocator using bitmaps
   3   * \author Alexander Boettcher
   4   * \author Stefan Kalkowski
   5   * \date   2012-06-14
   6   */

   7  
   8  /*
   9   * Copyright (C) 2012-2013 Genode Labs GmbH
  10   *
  11   * This file is part of the Genode OS framework, which is distributed
  12   * under the terms of the GNU General Public License version 2.
  13   */

  14  
  15  #ifndef _INCLUDE__UTIL__BIT_ALLOCATOR_H_
  16  #define _INCLUDE__UTIL__BIT_ALLOCATOR_H_
  17  
  18  #include <util/bit_array.h>
  19  
  20  namespace Genode { template<unsigned> class Bit_allocator; } 
  21  
  22  
  23  template<unsigned BITS>
  24  class Genode::Bit_allocator
  25  {
  26     protected:
  27  
  28        enum {
  29           BITS_PER_BYTE = 8UL,
  30           BITS_PER_WORD = sizeof(addr_t) * BITS_PER_BYTE,
  31           BITS_ALIGNED  = (BITS + BITS_PER_WORD - 1UL)
  32                           & ~(BITS_PER_WORD - 1UL),
  33        }
;

  34  
  35        using Array = Bit_array<BITS_ALIGNED>;
  36  
  37        addr_t _next;
  38        Array  _array;
  39  
  40        /**
  41         * Reserve consecutive number of bits
  42         *
  43         * \noapi
  44         */

  45        void _reserve(addr_t bit_start, size_t const num)
  46        {
  47           if (!num) return;
  48  
  49           _array.set(bit_start, num);

  50        }

  51  
  52     public:
  53  
  54        class Out_of_indices : Exception {};
  55  
  56        Bit_allocator() : _next(0) {
  57           _reserve(BITS, BITS_ALIGNED - BITS); }

  58  
  59        addr_t alloc(size_t const num_log2 = 0)
  60        {
  61           addr_t const step = 1UL << num_log2;
  62           addr_t max = ~0UL;

  63  
  64           do {
  65              try {
  66                 /* throws exception if array is accessed outside bounds */
  67                 for (addr_t i = _next & ~(step - 1); i < max; i += step) {
  68                    if (_array.get(i, step))
  69                       continue;

  70  
  71                    _array.set(i, step);
  72                    _next = i + step;
  73                    return i;

  74                 }

  75              }
 catch (typename Array::Invalid_index_access) { }

  76  
  77              max = _next;
  78              _next = 0;

  79  
  80           }
 while (max != 0);
  81  
  82           throw Out_of_indices();

  83        }

  84  
  85        void free(addr_t const bit_start, size_t const num_log2 = 0)
  86        {
  87           _array.clear(bit_start, 1UL << num_log2);
  88           _next = bit_start;

  89        }

  90  }
;

  91  
  92  #endif /* _INCLUDE__UTIL__BIT_ALLOCATOR_H_ */