1  /*
   2   * \brief  Heap partition
   3   * \author Norman Feske
   4   * \date   2006-05-15
   5   */

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

  13  
  14  #ifndef _INCLUDE__BASE__HEAP_H_
  15  #define _INCLUDE__BASE__HEAP_H_
  16  
  17  #include <util/list.h>
  18  #include <ram_session/ram_session.h>
  19  #include <rm_session/rm_session.h>
  20  #include <base/allocator_avl.h>
  21  #include <base/lock.h>
  22  
  23  namespace Genode {
  24  
  25     /**
  26      * Heap that uses dataspaces as backing store
  27      *
  28      * The heap class provides an allocator that uses a list of dataspaces of a ram
  29      * session as backing store. One dataspace may be used for holding multiple blocks.
  30      */

  31     class Heap : public Allocator
  32     {
  33        private:
  34  
  35           enum {
  36              MIN_CHUNK_SIZE =   4*1024,  /* in machine words */
  37              MAX_CHUNK_SIZE = 256*1024
  38           }
;

  39  
  40           class Dataspace : public List<Dataspace>::Element
  41           {
  42              public:
  43  
  44                 Ram_dataspace_capability cap;
  45                 void  *local_addr;
  46  
  47                 Dataspace(Ram_dataspace_capability c, void *a)
  48                 : cap(c), local_addr(a) {}

  49  
  50                 inline void * operator new(Genode::size_t, void* addr) {
  51                    return addr; }

  52                 inline void operator delete(void*) { }

  53           }
;

  54  
  55           class Dataspace_pool : public List<Dataspace>
  56           {
  57              private:
  58  
  59                 Ram_session *_ram_session;  /* ram session for backing store */
  60                 Rm_session  *_rm_session;   /* region manager                */

  61  
  62              public:
  63  
  64                 /**
  65                  * Constructor
  66                  */

  67                 Dataspace_pool(Ram_session *ram_session, Rm_session *rm_session):
  68                    _ram_session(ram_session), _rm_session(rm_session)
 { }

  69  
  70                 /**
  71                  * Destructor
  72                  */

  73                 ~Dataspace_pool();

  74  
  75                 /**
  76                  * Expand dataspace by specified size
  77                  *
  78                  * \param size      number of bytes to add to the dataspace pool
  79                  * \param md_alloc  allocator to expand. This allocator is also
  80                  *                  used for meta data allocation (only after
  81                  *                  being successfully expanded).
  82                  * \throw           Rm_session::Invalid_dataspace,
  83                  *                  Rm_session::Region_conflict
  84                  * \return          0 on success or negative error code
  85                  */

  86                 int expand(size_t size, Range_allocator *alloc);

  87  
  88                 void reassign_resources(Ram_session *ram, Rm_session *rm) {
  89                    _ram_session = ram, _rm_session = rm; }

  90           }
;

  91  
  92           /*
  93            * NOTE: The order of the member variables is important for
  94            *       the calling order of the destructors!
  95            */

  96  
  97           Lock           _lock;
  98           Dataspace_pool _ds_pool;      /* list of dataspaces */
  99           Allocator_avl  _alloc;        /* local allocator    */
 100           size_t         _quota_limit;
 101           size_t         _quota_used;
 102           size_t         _chunk_size;
 103  
 104           /**
 105            * Try to allocate block at our local allocator
 106            *
 107            * \return true on success
 108            *
 109            * This function is a utility used by `alloc` to avoid
 110            * code duplication.
 111            */

 112           bool _try_local_alloc(size_t size, void **out_addr);

 113  
 114        public:
 115  
 116           enum { UNLIMITED = ~0 };
 117  
 118           Heap(Ram_session *ram_session,
 119                Rm_session  *rm_session,
 120                size_t       quota_limit = UNLIMITED,
 121                void        *static_addr = 0,
 122                size_t       static_size = 0)

 123           :
 124              _ds_pool(ram_session, rm_session),
 125              _alloc(0),
 126              _quota_limit(quota_limit), _quota_used(0),
 127              _chunk_size(MIN_CHUNK_SIZE)

 128           {
 129              if (static_addr)
 130                 _alloc.add_range((addr_t)static_addr, static_size);

 131           }

 132  
 133           /**
 134            * Reconfigure quota limit
 135            *
 136            * \return  negative error code if new quota limit is higher than
 137            *          currently used quota.
 138            */

 139           int quota_limit(size_t new_quota_limit);

 140  
 141           /**
 142            * Re-assign RAM and RM sessions
 143            */

 144           void reassign_resources(Ram_session *ram, Rm_session *rm) {
 145              _ds_pool.reassign_resources(ram, rm); }

 146  
 147  
 148           /*************************
 149            ** Allocator interface **
 150            *************************/

 151  
 152           bool   alloc(size_t, void **);
 153           void   free(void *, size_t);
 154           size_t consumed() { return _quota_used; }
 155           size_t overhead(size_t size) { return _alloc.overhead(size); }

 156           bool   need_size_for_free() const override { return false; }
 157     }
;

 158  
 159  
 160     /**
 161      * Heap that allocates each block at a separate dataspace
 162      */

 163     class Sliced_heap : public Allocator
 164     {
 165        private:
 166  
 167           class Block;
 168  
 169           Ram_session    *_ram_session;  /* ram session for backing store */
 170           Rm_session     *_rm_session;   /* region manager                */
 171           size_t          _consumed;     /* number of allocated bytes     */
 172           List<Block>     _block_list;   /* list of allocated blocks      */
 173           Lock            _lock;         /* serialize allocations         */

 174  
 175        public:
 176  
 177           /**
 178            * Constructor
 179            */

 180           Sliced_heap(Ram_session *ram_session, Rm_session *rm_session);

 181  
 182           /**
 183            * Destructor
 184            */

 185           ~Sliced_heap();

 186  
 187  
 188           /*************************
 189            ** Allocator interface **
 190            *************************/

 191  
 192           bool   alloc(size_t, void **);
 193           void   free(void *, size_t);
 194           size_t consumed() { return _consumed; }
 195           size_t overhead(size_t size);

 196           bool   need_size_for_free() const override { return false; }
 197     }
;

 198  }

 199  
 200  #endif /* _INCLUDE__BASE__HEAP_H_ */