]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/kmem_alloc.cpp
update
[l4.git] / kernel / fiasco / src / kern / kmem_alloc.cpp
1 INTERFACE:
2
3 #include "mapped_alloc.h"
4 #include "spin_lock.h"
5 #include "lock_guard.h"
6 #include "initcalls.h"
7
8 class Buddy_alloc;
9 class Mem_region_map_base;
10 class Kip;
11
12 class Kmem_alloc : public Mapped_allocator
13 {
14   Kmem_alloc();
15
16 public:
17   typedef Buddy_alloc Alloc;
18 private:
19   typedef Spin_lock Lock;
20   static Lock lock;
21   static Alloc *a;
22   static unsigned long _orig_free;
23 };
24
25
26 IMPLEMENTATION:
27
28 #include <cassert>
29
30 #include "config.h"
31 #include "kdb_ke.h"
32 #include "kip.h"
33 #include "mem_region.h"
34 #include "buddy_alloc.h"
35 #include "panic.h"
36
37 static Kmem_alloc::Alloc _a;
38 Kmem_alloc::Alloc *Kmem_alloc::a = &_a;
39 Kmem_alloc::Lock Kmem_alloc::lock;
40 unsigned long Kmem_alloc::_orig_free;
41
42 PUBLIC static FIASCO_INIT
43 void
44 Kmem_alloc::init()
45 {
46   static Kmem_alloc al;
47   Mapped_allocator::allocator(&al);
48 }
49
50 PUBLIC
51 void
52 Kmem_alloc::dump() const
53 { a->dump(); }
54
55 PUBLIC
56 void *
57 Kmem_alloc::alloc(size_t o)
58 {
59   return unaligned_alloc(1UL << o);
60 }
61
62
63 PUBLIC
64 void
65 Kmem_alloc::free(size_t o, void *p)
66 {
67   unaligned_free(1UL << o, p);
68 }
69
70 PUBLIC 
71 void *
72 Kmem_alloc::unaligned_alloc(unsigned long size)
73 {
74   assert(size >=8 /*NEW INTERFACE PARANIOIA*/);
75   void* ret;
76
77   {
78     Lock_guard<Lock> guard(&lock);
79     ret = a->alloc(size);
80   }
81
82   if (!ret)
83     {
84       Mapped_alloc_reaper::morecore (/* desperate= */ true);
85
86       Lock_guard<Lock> guard (&lock);
87       ret = a->alloc(size);
88     }
89
90   return ret;
91 }
92
93 PUBLIC
94 void
95 Kmem_alloc::unaligned_free(unsigned long size, void *page)
96 {
97   assert(size >=8 /*NEW INTERFACE PARANIOIA*/);
98   Lock_guard<Lock> guard (&lock);
99   a->free(page, size);
100 }
101
102
103 PRIVATE static FIASCO_INIT
104 unsigned long
105 Kmem_alloc::create_free_map(Kip const *kip, Mem_region_map_base *map)
106 {
107   unsigned long available_size = 0;
108   Mem_desc const *md = kip->mem_descs();
109   Mem_desc const *const md_end = md + kip->num_mem_descs();
110
111   for (; md < md_end; ++md)
112     {
113       if (!md->valid())
114         {
115           const_cast<Mem_desc*>(md)->type(Mem_desc::Undefined);
116           continue;
117         }
118
119       if (md->is_virtual())
120         continue;
121
122       unsigned long s = md->start();
123       unsigned long e = md->end();
124
125       // Sweep out stupid descriptors (that have the end before the start)
126
127       switch (md->type())
128         {
129         case Mem_desc::Conventional:
130           s = (s + Config::PAGE_SIZE - 1) & ~(Config::PAGE_SIZE - 1);
131           e = ((e + 1) & ~(Config::PAGE_SIZE - 1)) - 1;
132           if (e <= s)
133             break;
134           available_size += e - s + 1;
135           if (!map->add(Mem_region(s, e)))
136             panic("Kmem_alloc::create_free_map(): memory map too small");
137           break;
138         case Mem_desc::Reserved:
139         case Mem_desc::Dedicated:
140         case Mem_desc::Shared:
141         case Mem_desc::Arch:
142         case Mem_desc::Bootloader:
143           s = s & ~(Config::PAGE_SIZE - 1);
144           e = ((e + Config::PAGE_SIZE) & ~(Config::PAGE_SIZE - 1)) - 1;
145           if (!map->sub(Mem_region(s, e)))
146             panic("Kmem_alloc::create_free_map(): memory map too small");
147           break;
148         default:
149           break;
150         }
151     }
152
153   return available_size;
154 }