]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/moe/server/src/alloc.cc
update
[l4.git] / l4 / pkg / moe / server / src / alloc.cc
1 /*
2  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3  *               Alexander Warg <warg@os.inf.tu-dresden.de>
4  *     economic rights: Technische Universität Dresden (Germany)
5  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  */
10 #include <l4/cxx/exceptions>
11 #include <l4/cxx/auto_ptr>
12 #include <l4/cxx/l4iostream>
13
14 #include <l4/re/protocols>
15 #include <l4/re/mem_alloc-sys.h>
16 #include <l4/re/mem_alloc>
17 #include <l4/re/util/meta>
18 #include <l4/sys/factory>
19
20 #include <cstdlib>
21
22 #include "alloc.h"
23 #include "dataspace_annon.h"
24 #include "dataspace_noncont.h"
25 #include "globals.h"
26 #include "page_alloc.h"
27 #include "slab_alloc.h"
28 #include "quota.h"
29 #include "region.h"
30 #include "name_space.h"
31 #include "log.h"
32 #include "sched_proxy.h"
33
34 typedef Moe::Q_alloc<Allocator, Slab_alloc> Alloc;
35
36 template< typename C >
37 class Quota_obj : public C
38 {
39 private:
40   typedef Moe::Q_alloc<Quota_obj<C>, Slab_alloc> Alloc;
41   static Alloc *_allocator()
42   {
43     static Alloc _a;
44     return &_a;
45   }
46
47 public:
48   virtual ~Quota_obj() {}
49   void *operator new (size_t size, Moe::Quota *q)
50   {
51     if (size != sizeof(Quota_obj))
52       throw L4::Out_of_memory();
53
54     return _allocator()->alloc(q);
55   }
56
57   void operator delete(void *o)
58   {
59     _allocator()->free((Quota_obj*)o);
60   }
61
62   Quota_obj() : C() {}
63
64   template< typename A1 >
65   Quota_obj(A1 a1) : C(a1) {}
66
67   template< typename A1, typename A2 >
68   Quota_obj(A1 a1, A2 a2) : C(a1, a2) {}
69
70   template< typename A1, typename A2, typename A3 >
71   Quota_obj(A1 a1, A2 a2, A3 a3) : C(a1, a2, a3) {}
72
73
74 };
75
76 static Alloc *slab()
77 {
78   static Alloc _slab;
79   return &_slab;
80 }
81
82 void *Allocator::operator new (size_t, Moe::Quota *q, size_t limit)
83 {
84   return slab()->alloc(q, limit);
85 }
86
87 void Allocator::operator delete (void *m) throw()
88 {
89   slab()->free((Allocator*)m);
90 }
91
92 Moe::Dataspace *
93 Allocator::alloc(unsigned long size, unsigned long flags)
94 {
95   if (size == 0)
96     throw L4::Bounds_error("stack too small");
97
98   //L4::cout << "A: \n";
99   Moe::Dataspace *mo;
100   if (flags & L4Re::Mem_alloc::Continuous
101       || flags & L4Re::Mem_alloc::Pinned)
102     mo = new (&_quota) Moe::Dataspace_annon(size, true,
103         flags & L4Re::Mem_alloc::Super_pages
104           ? L4_SUPERPAGESHIFT : L4_PAGESHIFT);
105   else
106     mo = Moe::Dataspace_noncont::create(&_quota, size);
107
108   // L4::cout << "A: mo=" << mo << "\n";
109
110   //L4::cout << "A[" << this << "]: allocated(" << mo << " " << mo->obj_cap() << ")\n";
111   return mo;
112 }
113
114 Allocator::~Allocator()
115 {
116   if (Q_object::quota())
117     Q_object::quota()->free(_quota.limit());
118 }
119
120 L4::Server_object *
121 Allocator::open(int, cxx::String const *argv)
122 {
123   unsigned long sz = strtol(argv[0].start(), 0, 0);
124   if(!sz)
125     {
126       //L4::cerr << "could not parse quota value!\n";
127       return 0;
128     }
129   Allocator *child = new (&_quota, sz) Allocator(sz);
130   object_pool.cap_alloc()->alloc(child);
131   return child;
132 }
133
134
135 class LLog : public Moe::Log
136 {
137 private:
138   char _tag[32];
139
140 public:
141   LLog(char const *t, int l, unsigned char col) : Log()
142   {
143     if (l > 32)
144       l = 32;
145
146     memcpy(_tag, t, l);
147
148     set_tag(_tag, l);
149
150     set_color(col);
151   }
152
153   virtual ~LLog() {}
154 };
155
156 int
157 Allocator::disp_factory(l4_umword_t r, L4::Ipc::Iostream &ios)
158 {
159   if (!(r & L4_CAP_FPAGE_S))
160     return -L4_EPERM;
161
162   L4::Factory::Proto o;
163   ios >> o;
164
165   L4::Cap<L4::Kobject> ko;
166
167   switch (o)
168     {
169     case L4Re::Protocol::Namespace:
170       ko = object_pool.cap_alloc()->alloc(new (&_quota) Quota_obj<Moe::Name_space>());
171       ko->dec_refcnt(1);
172       ios << ko;
173       return L4_EOK;
174
175     case L4Re::Protocol::Rm:
176       ko = object_pool.cap_alloc()->alloc(new (&_quota) Quota_obj<Region_map>());
177       ko->dec_refcnt(1);
178       ios << ko;
179       return L4_EOK;
180
181     case L4::Factory::Protocol:
182     case L4Re::Protocol::Mem_alloc:
183         {
184           L4::Ipc::Varg tag;
185           ios.get(&tag);
186
187           if (!tag.is_of_int()) // ignore sign
188             return -L4_EINVAL;
189           Allocator *child = new (&_quota, tag.value<long>()) Allocator(tag.value<long>());
190           ko = object_pool.cap_alloc()->alloc(child);
191           ko->dec_refcnt(1);
192           ios << ko;
193
194           return 0;
195         }
196
197     case L4_PROTO_LOG:
198         {
199           L4::Ipc::Varg tag;
200           ios.get(&tag);
201
202           if (!tag.is_of<char const *>())
203             return -L4_EINVAL;
204
205           L4::Ipc::Varg col;
206           ios.get(&col);
207
208           int color;
209           if (col.is_of<char const *>())
210             color = LLog::color_value(cxx::String(col.value<char const*>(),
211                                                   col.length()));
212           else if(col.is_of_int())
213             color = col.value<l4_mword_t>();
214           else
215             color = 7;
216
217           Moe::Log *l = new (&_quota) Quota_obj<LLog>(tag.value<char const*>(), tag.length(), color);
218           ko = object_pool.cap_alloc()->alloc(l);
219           ko->dec_refcnt(1);
220
221           ios << ko;
222           return L4_EOK;
223         }
224
225     case L4::Scheduler::Protocol:
226         {
227           if (!_sched_prio_limit)
228             return -L4_ENODEV;
229
230           L4::Ipc::Varg p_max, p_base, cpus;
231           ios.get(&p_max);
232           ios.get(&p_base);
233           ios.get(&cpus);
234
235           if (!p_max.is_of_int() || !p_base.is_of_int())
236             return -L4_EINVAL;
237
238           if (p_max.value<l4_mword_t>() > _sched_prio_limit
239               || p_base.value<l4_mword_t>() > _sched_prio_limit)
240             return -L4_ERANGE;
241
242           if (p_max.value<l4_mword_t>() <= p_base.value<l4_mword_t>())
243             return -L4_EINVAL;
244
245           l4_umword_t cpu_mask = ~0UL;
246
247           if (!cpus.is_of<void>() && cpus.is_of_int())
248             cpu_mask = cpus.value<l4_umword_t>();
249
250           Sched_proxy *o = new (&_quota) Quota_obj<Sched_proxy>();
251           o->set_prio(p_base.value<l4_mword_t>(), p_max.value<l4_mword_t>());
252           o->restrict_cpus(cpu_mask);
253           ko = object_pool.cap_alloc()->alloc(o);
254           ko->dec_refcnt(1);
255
256           ios << ko;
257           return L4_EOK;
258         }
259     case L4Re::Dataspace::Protocol:
260         {
261           L4::Ipc::Varg size, flags;
262           ios >> size >> flags;
263
264           if (!size.is_of_int())
265             return -L4_EINVAL;
266
267           // L4::cout << "MEM: alloc ... " << size.value<l4_umword_t>() << "; " << flags.value<l4_umword_t>() << "\n";
268           cxx::Auto_ptr<Moe::Dataspace> mo(alloc(size.value<l4_umword_t>(),
269                 flags.is_of_int() ? flags.value<l4_umword_t>() : 0));
270
271           // L4::cout << "MO=" << mo.get() << "\n";
272           ko = object_pool.cap_alloc()->alloc(mo.get());
273           ko->dec_refcnt(1);
274           // L4::cout << "MO_CAP=" << mo->obj_cap() << "\n";
275           ios << ko;
276           mo.release();
277           return L4_EOK;
278         }
279
280     default:
281       return -L4_ENODEV;
282     }
283 }
284
285 // create out annonymous combination of a memory allocctaor and a factory
286 class Moe_allocator :
287   public L4::Kobject_2t<Moe_allocator, L4::Factory, L4Re::Mem_alloc>
288 {};
289
290 int
291 Allocator::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
292 {
293   L4::Opcode op;
294
295   l4_msgtag_t tag;
296   ios >> tag;
297   switch (tag.label())
298     {
299     case L4::Meta::Protocol:
300       return L4Re::Util::handle_meta_request<Moe_allocator>(ios);
301     case L4::Factory::Protocol:
302       return disp_factory(obj, ios);
303
304     case L4Re::Protocol::Mem_alloc:
305       {
306         ios >> op;
307         switch (op)
308           {
309           case L4Re::Mem_alloc_::Alloc:
310             {
311               unsigned long size;
312               unsigned long flags;
313               ios >> size >> flags;
314
315               //L4::cout << "MEM: alloc ... " << size << "; " << flags << "\n";
316               cxx::Auto_ptr<Moe::Dataspace> mo(alloc(size,flags));
317
318               // L4::cout << "MO=" << mo.get() << "\n";
319               L4::Cap<void> o = object_pool.cap_alloc()->alloc(mo.get());
320               //L4::cout << "MO_CAP=" << mo->obj_cap() << "\n";
321               ios << o;
322               mo.release();
323               return L4_EOK;
324             }
325           case L4Re::Mem_alloc_::Free:
326             {
327               l4_umword_t rc1, rc2;
328
329               Moe::Dataspace *mo = 0;
330               ios >> rc1 >> rc2;
331               if ((rc1 & 0xe) == 0xc) // XXX: change with cap.id_received()
332                 mo = dynamic_cast<Moe::Dataspace*>(object_pool.find(rc2));
333
334
335               // FIXME: check if dataspace comes from this allocator 
336
337               if (!mo || mo->is_static())
338                 return -L4_EINVAL;
339
340               object_pool.cap_alloc()->free(mo);
341               mo->unmap();
342               delete mo;
343               return L4_EOK;
344             }
345           default:
346             return -L4_ENOSYS;
347           }
348       }
349     case L4Re::Protocol::Debug:
350       {
351         printf("MOE: mem_alloc: quota: limit=%zd Byte, used=%zd Byte\n",
352                _quota.limit(), _quota.used());
353         printf("MOE: mem_alloc: global: avail=%ld Byte\n",
354                Single_page_alloc_base::_avail());
355         return L4_EOK;
356       }
357     default:
358       return -L4_EBADPROTO;
359     }
360 }
361
362
363 Allocator *
364 Allocator::root_allocator()
365 {
366   static Allocator ra(~0, 300000);
367   return &ra;
368 }