]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/moe/server/src/quota.h
update
[l4.git] / l4 / pkg / moe / server / src / quota.h
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 #pragma once
10
11 #include <cstddef>
12 #include <cstdio>
13 #include <gc.h>
14
15 namespace Moe {
16
17
18 class Finalized
19 {
20 public:
21   virtual ~Finalized()
22   { GC_register_finalizer_ignore_self(GC_base(this), 0, 0, 0, 0); }
23
24   static void GC_CALLBACK finalizer(void *obj, void *displ)
25   { reinterpret_cast<Finalized*>((char *)obj + (ptrdiff_t)displ)->~Finalized(); }
26
27   Finalized()
28   {
29     void *base = GC_base((void*)this);
30     if (base != 0)
31       {
32         GC_register_finalizer_ignore_self(base, finalizer, (void *)((char *)this - (char *)base), 0, 0);
33       }
34   }
35 };
36
37 class Quota
38 {
39 public:
40   explicit Quota(size_t limit) : _limit(limit), _used(0) {}
41   bool alloc(size_t s)
42   {
43     if (_limit && (s > _limit))
44       return false;
45
46     if (_limit && (_used > _limit - s))
47       {
48         GC_gcollect_and_unmap();
49         if (_used > _limit - s)
50           return false;
51       }
52
53     _used += s;
54     //printf("Q: alloc(%zx) -> %zx\n", s, _used);
55     return true;
56   }
57
58   void free(size_t s)
59   {
60     _used -= s;
61     //printf("Q: free(%zx) -> %zx\n", s, _used);
62   }
63
64   size_t limit() const { return _limit; }
65   size_t used() const { return _used; }
66
67 private:
68   size_t _limit;
69   size_t _used;
70 };
71
72 struct Quota_guard
73 {
74   Quota *q;
75   size_t amount;
76
77   Quota_guard(Quota *q, size_t amount) : q(q), amount(amount)
78   {
79     if (!q->alloc(amount))
80       throw L4::Out_of_memory();
81   }
82
83   ~Quota_guard()
84   {
85     if (q)
86       q->free(amount);
87   }
88
89   void done()
90   {
91     q = 0;
92   }
93
94   template< typename T >
95   T done(T t)
96   {
97     q = 0;
98     return t;
99   }
100 };
101
102 namespace Q_object_tr {
103   template< typename T, bool B >
104   struct Qtr;
105 }
106
107 class Q_object : public Finalized
108 {
109 protected:
110   Quota *quota() const { return _quota; }
111
112 private:
113   template< typename T, bool B >
114   friend class Q_object_tr::Qtr;
115   Quota *_quota;
116 };
117
118 namespace Q_object_tr {
119   template< typename T, bool B >
120   struct Qtr
121   {
122     struct Obj : public T
123     {
124       Quota *_q;
125     };
126     static Quota *quota(T *o) { return static_cast<Obj*>(o)->_q; }
127     static void quota(T *o, Quota *q) { static_cast<Obj*>(o)->_q = q; }
128   };
129
130   template< typename T >
131   struct Qtr<T, true>
132   {
133     typedef T Obj;
134     static Quota *quota(T *o) { return static_cast<Q_object*>(o)->_quota; }
135     static void quota(T *o, Quota *q) { static_cast<Q_object*>(o)->_quota = q; }
136   };
137 }
138
139 template< typename Type, template <typename T > class Alloc >
140 class Q_alloc
141 {
142 private:
143   static int __is_qobject__(Q_object *) { return 0; }
144   static char __is_qobject__(...) { return 0; }
145   typedef Q_object_tr::Qtr<Type, sizeof(__is_qobject__((Type*)0)) == sizeof(int)> Qtr;
146   typedef typename Qtr::Obj Obj;
147   typedef Alloc<Obj> Allocator;
148
149 public:
150   typedef Type Obj_type;
151
152   Obj_type *alloc(Quota *quota, size_t extra = 0)
153   {
154     Quota_guard g(quota, sizeof(Obj) + extra);
155
156     Obj *o = _alloc.alloc();
157     if (o)
158       {
159         Qtr::quota(o, quota);
160         g.done();
161         return o;
162       }
163
164     throw L4::Out_of_memory();
165   }
166
167   void free(Obj_type *o) throw()
168   {
169     Obj *io = static_cast<Obj*>(o);
170     Qtr::quota(o)->free(sizeof(Obj));
171     _alloc.free(io);
172   }
173
174 private:
175   Allocator _alloc;
176 };
177
178
179 template< typename Alloc >
180 struct Q_alloc_static
181 {
182   static void *_alloc(Quota *q, unsigned long size, unsigned long align)
183   {
184     Quota_guard g(q, size);
185     return g.done(Alloc::_alloc(size, align));
186   }
187
188   static void _free(Quota *q, void *p, unsigned long size) throw()
189   {
190     Alloc::_free(p, size);
191     q->free(size);
192   }
193 };
194
195 }