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.
7 #include <l4/cxx/exceptions>
8 #include <l4/cxx/auto_ptr>
9 #include <l4/cxx/l4iostream>
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>
20 #include "dataspace_annon.h"
21 #include "dataspace_noncont.h"
23 #include "page_alloc.h"
24 #include "slab_alloc.h"
27 #include "name_space.h"
29 #include "sched_proxy.h"
31 typedef Moe::Q_alloc<Allocator, Slab_alloc> Alloc;
33 template< typename C >
34 class Quota_obj : public C
37 typedef Moe::Q_alloc<Quota_obj<C>, Slab_alloc> Alloc;
38 static Alloc *_allocator()
45 virtual ~Quota_obj() {}
46 void *operator new (size_t size, Moe::Quota *q)
48 if (size != sizeof(Quota_obj))
49 throw L4::Out_of_memory();
51 return _allocator()->alloc(q);
54 void operator delete(void *o)
56 _allocator()->free((Quota_obj*)o);
61 template< typename A1 >
62 Quota_obj(A1 a1) : C(a1) {}
64 template< typename A1, typename A2 >
65 Quota_obj(A1 a1, A2 a2) : C(a1, a2) {}
67 template< typename A1, typename A2, typename A3 >
68 Quota_obj(A1 a1, A2 a2, A3 a3) : C(a1, a2, a3) {}
79 void *Allocator::operator new (size_t, Moe::Quota *q, size_t limit)
81 return slab()->alloc(q, limit);
84 void Allocator::operator delete (void *m) throw()
86 slab()->free((Allocator*)m);
90 Allocator::alloc(unsigned long size, unsigned long flags)
93 throw L4::Bounds_error("stack too small");
95 //L4::cout << "A: \n";
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);
103 mo = Moe::Dataspace_noncont::create(&_quota, size);
105 // L4::cout << "A: mo=" << mo << "\n";
107 //L4::cout << "A[" << this << "]: allocated(" << mo << " " << mo->obj_cap() << ")\n";
111 Allocator::~Allocator()
113 if (Q_object::quota())
114 Q_object::quota()->free(_quota.limit());
118 Allocator::open(int, cxx::String const *argv)
120 unsigned long sz = strtol(argv[0].start(), 0, 0);
123 //L4::cerr << "could not parse quota value!\n";
126 Allocator *child = new (&_quota, sz) Allocator(sz);
127 object_pool.cap_alloc()->alloc(child);
132 class LLog : public Moe::Log
138 LLog(char const *t, int l, unsigned char col) : Log()
154 Allocator::disp_factory(l4_umword_t, L4::Ipc_iostream &ios)
156 L4::Factory::Proto o;
159 L4::Cap<L4::Kobject> ko;
163 case L4Re::Protocol::Namespace:
164 ko = object_pool.cap_alloc()->alloc(new (&_quota) Quota_obj<Moe::Name_space>());
169 case L4Re::Protocol::Rm:
170 ko = object_pool.cap_alloc()->alloc(new (&_quota) Quota_obj<Region_map>());
175 case L4::Factory::Protocol:
176 case L4Re::Protocol::Mem_alloc:
181 if (!tag.is_of_int()) // ignore sign
183 Allocator *child = new (&_quota, tag.value<long>()) Allocator(tag.value<long>());
184 ko = object_pool.cap_alloc()->alloc(child);
196 if (!tag.is_of<char const *>())
203 if (col.is_of<char const *>())
204 color = LLog::color_value(cxx::String(col.value<char const*>(),
206 else if(col.is_of_int())
207 color = col.value<l4_mword_t>();
211 Moe::Log *l = new (&_quota) Quota_obj<LLog>(tag.value<char const*>(), tag.length(), color);
212 ko = object_pool.cap_alloc()->alloc(l);
219 case L4::Scheduler::Protocol:
221 if (!_sched_prio_limit)
224 L4::Ipc::Varg p_max, p_base, cpus;
229 if (!p_max.is_of_int() || !p_base.is_of_int())
232 if (p_max.value<l4_mword_t>() > _sched_prio_limit
233 || p_base.value<l4_mword_t>() > _sched_prio_limit)
236 if (p_max.value<l4_mword_t>() <= p_base.value<l4_mword_t>())
239 l4_umword_t cpu_mask = ~0UL;
241 if (!cpus.is_of<void>() && cpus.is_of_int())
242 cpu_mask = cpus.value<l4_umword_t>();
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);
253 case L4Re::Dataspace::Protocol:
255 L4::Ipc::Varg size, flags;
256 ios >> size >> flags;
258 if (!size.is_of_int())
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));
265 // L4::cout << "MO=" << mo.get() << "\n";
266 ko = object_pool.cap_alloc()->alloc(mo.get());
268 //L4::cout << "MO_CAP=" << mo->obj_cap() << "\n";
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>
285 Allocator::dispatch(l4_umword_t obj, L4::Ipc_iostream &ios)
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);
298 case L4Re::Protocol::Mem_alloc:
303 case L4Re::Mem_alloc_::Alloc:
307 ios >> size >> flags;
309 //L4::cout << "MEM: alloc ... " << size << "; " << flags << "\n";
310 cxx::Auto_ptr<Moe::Dataspace> mo(alloc(size,flags));
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";
319 case L4Re::Mem_alloc_::Free:
321 l4_umword_t rc1, rc2;
323 Moe::Dataspace *mo = 0;
325 if ((rc1 & 0xe) == 0xc) // XXX: change with cap.id_received()
326 mo = dynamic_cast<Moe::Dataspace*>(object_pool.find(rc2));
329 // FIXME: check if dataspace comes from this allocator
331 if (!mo || mo->is_static())
334 object_pool.cap_alloc()->free(mo);
343 case L4Re::Protocol::Debug:
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());
352 return -L4_EBADPROTO;
358 Allocator::root_allocator()
360 static Allocator ra(~0, 300000);