1 /* 2 * (c) 2009 Alexander Warg <warg@os.inf.tu-dresden.de> 3 * economic rights: Technische Universität Dresden (Germany) 4 * 5 * This file is part of TUD:OS and distributed under the terms of the 6 * GNU General Public License 2. 7 * Please see the COPYING-GPL-2 file for details. 8 */ 9 /* 10 * Copyright (C) 2015 Kernkonzept GmbH. 11 * Author(s): Sarah Hoffmann <sarah.hoffmann@kernkonzept.com> 12 * 13 */ 14 #pragma once 15 16 #include <l4/cxx/exceptions> 17 18 #include <new> 19 #include <cstddef> 20 #include <cstdio> 21 #include <cassert> 22 23 #include "malloc.h" 24 #include "page_alloc.h" 25 26 namespace Moe { 27 28 /** 29 * A simple quota manager. 30 */ 31 class Quota 32 { 33 public: Quota(size_t limit)34 explicit Quota(size_t limit) : _limit(limit), _used(0) {} alloc(size_t s)35 bool alloc(size_t s) 36 { 37 if (_limit && (s > _limit || _used > _limit - s)) 38 return false; 39 40 _used += s; 41 //printf("Q: alloc(%zx) -> %zx\n", s, _used); 42 return true; 43 } 44 free(size_t s)45 void free(size_t s) 46 { 47 assert(s <= _used); 48 _used -= s; 49 //printf("Q: free(%zx) -> %zx\n", s, _used); 50 } 51 limit()52 size_t limit() const { return _limit; } used()53 size_t used() const { return _used; } 54 55 private: 56 size_t _limit; 57 size_t _used; 58 }; 59 60 /** 61 * Quota allocator that cleans up on unexpected exit. 62 */ 63 struct Quota_guard 64 { 65 Quota *q; 66 size_t amount; 67 Quota_guardQuota_guard68 Quota_guard() : q(0) {} 69 Quota_guardQuota_guard70 Quota_guard(Quota *q, size_t amount) : q(q), amount(amount) 71 { 72 if (!q->alloc(amount)) 73 throw L4::Out_of_memory(); 74 } 75 ~Quota_guardQuota_guard76 ~Quota_guard() 77 { 78 if (q) 79 q->free(amount); 80 } 81 releaseQuota_guard82 void release() 83 { 84 q = 0; 85 } 86 87 Quota_guard &operator = (Quota_guard &&g) 88 { 89 if (this == &g) 90 return *this; 91 92 if (q) 93 q->free(amount); 94 95 q = g.q; 96 if (q) 97 amount = g.amount; 98 99 g.release(); 100 101 return *this; 102 } 103 104 template< typename T > releaseQuota_guard105 T release(T t) 106 { 107 q = 0; 108 return t; 109 } 110 }; 111 112 /** 113 * Quota-guarded allocator. 114 */ 115 class Q_alloc : public Malloc_container 116 { 117 public: Q_alloc(size_t limit)118 Q_alloc(size_t limit) : _quota(limit) {} 119 quota()120 Quota *quota() { return &_quota; } 121 alloc_pages(unsigned long size,unsigned long align)122 void *alloc_pages(unsigned long size, unsigned long align) 123 { 124 Quota_guard g(quota(), size); 125 return g.release(Single_page_alloc_base::_alloc(size, align)); 126 } 127 free_pages(void * p,unsigned long size)128 void free_pages(void *p, unsigned long size) throw() 129 { 130 Single_page_alloc_base::_free(p, size); 131 quota()->free(size); 132 } 133 134 void reparent(Malloc_container *new_container) override; 135 136 protected: 137 void *get_mem() override; 138 void free_mem(void *page) override; 139 140 Quota _quota; 141 }; 142 143 /** 144 * An object that is saved in quota storage. 145 */ 146 147 class Q_object 148 { 149 public: qalloc()150 Q_alloc *qalloc() const 151 { 152 return static_cast<Q_alloc *>(Malloc_container::from_ptr(this)); 153 } 154 }; 155 156 157 // The static allocator for global memory 158 struct Moe_alloc : public Q_alloc 159 { 160 public: 161 static Moe_alloc *allocator(); 162 163 private: Moe_allocMoe_alloc164 Moe_alloc() : Q_alloc(0) {} 165 }; 166 167 168 /** 169 * An allocator that gets memory from the Q_alloc responsible for 170 * the memory where this allocator is placed. 171 */ 172 template <typename T> 173 class Quota_allocator 174 { 175 public: 176 enum { can_free = true }; 177 throw()178 Quota_allocator() throw() {} throw()179 Quota_allocator(Quota_allocator const &) throw() {} 180 Quota &operator = (Quota const &) = delete; 181 throw()182 ~Quota_allocator() throw() {} 183 alloc()184 T *alloc() throw() 185 { 186 auto *mc = Malloc_container::from_ptr(this); 187 return static_cast<T *>(mc->alloc(sizeof (T), alignof(T))); 188 } 189 free(T * t)190 void free(T *t) throw() 191 { 192 auto *mc = Malloc_container::from_ptr(t); 193 mc->free(t); 194 } 195 }; 196 197 } // namespace 198 199