1 /*
2  * Copyright (C) 2015 Kernkonzept GmbH.
3  * Author(s): Sarah Hoffmann <sarah.hoffmann@kernkonzept.com>
4  *
5  * This file is distributed under the terms of the GNU General Public
6  * License, version 2.  Please see the COPYING-GPL-2 file for details.
7  */
8 #pragma once
9 
10 #include <l4/sys/consts.h>
11 #include <l4/cxx/exceptions>
12 #include <l4/cxx/type_traits>
13 #include <l4/cxx/slist>
14 
15 #include <new>
16 #include <cstddef>
17 
18 namespace Moe {
19 
20 class Malloc_page;
21 
22 /**
23  * A basic allocator for any size of chunks.
24  */
25 class Malloc_container
26 {
27 public:
28   class Guarded_alloc
29   {
30   public:
Guarded_alloc(Malloc_container * c,size_t sz,size_t align)31     Guarded_alloc(Malloc_container* c, size_t sz, size_t align)
32     : _c(c)
33     {
34       _p = c->alloc(sz, align);
35       if (L4_UNLIKELY(!_p))
36         throw L4::Out_of_memory();
37     }
38 
~Guarded_alloc()39     ~Guarded_alloc()
40     {
41       if (_p)
42         _c->free(_p);
43     }
44 
45     template <typename T>
release()46     T *release()
47     {
48       T *ret = static_cast<T *>(_p);
49       _p = 0;
50       return ret;
51     }
52 
get()53     void *get() const
54     { return _p; }
55 
56   private:
57     void *_p;
58     Malloc_container* _c;
59   };
60 
61   void *alloc(size_t size, size_t align) throw();
62   void free(void *block) throw();
63   virtual void reparent(Malloc_container *new_container);
64 
65   template <typename T, typename ...ARGS>
make_obj(ARGS &&...args)66   T *make_obj(ARGS &&... args)
67   {
68     Guarded_alloc q(this, sizeof(T), alignof(T));
69 
70     new (q.get()) T(cxx::forward<ARGS>(args)...);
71 
72     return q.release<T>();
73   }
74 
75   template <typename T>
alloc(size_t size)76   T *alloc(size_t size)
77   {
78     Guarded_alloc q(this, sizeof(T) * size, alignof(T));
79 
80     new (q.get()) T[size];
81 
82     return q.release<T>();
83   }
84 
85   static Malloc_container *from_ptr(void const *p) throw();
86 
87 protected:
88   virtual void *get_mem();
89   virtual void free_mem(void *page);
90 
91 private:
92   cxx::S_list<Malloc_page> _pages;
93 };
94 
95 } // namespace
96