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