13 struct Head : cxx::H_list_item
17 static void link(cxx::H_list<Head> &h, void *b, unsigned idx)
25 typedef cxx::H_list_bss<Head> B_list;
28 template< int MIN_LOG2_SIZE, int NUM_SIZES, int MAX_MEM >
29 class Buddy_t_base : public Buddy_base
34 Min_log2_size = MIN_LOG2_SIZE,
35 Min_size = 1UL << MIN_LOG2_SIZE,
36 Num_sizes = NUM_SIZES,
37 Max_size = Min_size << (NUM_SIZES - 1),
44 // the number of bits in the bitmap is given by the amount of the smallest
45 // supported blocks. We need an extra bit in the case that the Max_mem
46 // is no multiple of Max_size to ensure that buddy() does not access
48 Buddy_bits = (Max_mem + Min_size - 1)/Min_size
49 + !!(Max_mem & (Max_size-1))
51 B_list _free[Num_sizes];
52 Bitmap<Buddy_bits> _free_map;
56 class Buddy_alloc : public Buddy_t_base<10, 8, Config::kernel_mem_max>
61 //----------------------------------------------------------------------------
70 template<int A, int B, int M>
73 Buddy_t_base<A,B,M>::buddy(void *block, unsigned long index, Head **new_block)
75 //printf("buddy(%p, %ld)\n", block, index);
76 unsigned long const size = Min_size << index;
77 unsigned long const n_size = size << 1;
78 if (index + 1 >= Num_sizes)
80 unsigned long b = (unsigned long)block;
81 unsigned long _buddy = b & ~(n_size-1);
82 *new_block = (Head*)_buddy;
86 Head * const _buddy_h = (Head*)_buddy;
88 // this test may access one bit behind our maximum, this is safe because
89 // we allocated an extra bit
90 if (_free_map[(_buddy - _base)/Min_size] && _buddy_h->index == index)
97 template<int A, int B, int M>
100 Buddy_t_base<A,B,M>::free(void *block, unsigned long size)
102 assert_kdb ((unsigned long)block >= _base);
103 assert_kdb ((unsigned long)block - _base < Max_mem);
104 assert_kdb (!_free_map[((unsigned long)block - _base) / Min_size]);
106 //if (_debug) printf("Buddy::free(%p, %ld)\n", block, size);
107 unsigned size_index = 0;
108 while (((unsigned long)Min_size << size_index) < size)
111 if (size != (unsigned long)Min_size << size_index)
112 WARNX(Info, "Buddy::free: Size mismatch: %lx v %lx\n",
113 size, (unsigned long)Min_size << size_index);
116 // no need to look for a buddy if we already have the biggest block size
117 while (size_index + 1 < Num_sizes)
120 b = buddy(block, size_index, &n);
123 //if (!_b && _debug) dump();
124 //if (_debug) printf(" found buddy %p (n=%p size=%ld)\n", b, n, size_index+1);
134 //printf(" link free %p\n", block);
135 Head::link(_free[size_index], block, size_index);
136 _free_map.set_bit(((unsigned long)block - _base) / Min_size);
137 //if (_b && _debug) dump();
142 template<int A, int B, int M>
144 Buddy_t_base<A,B,M>::add_mem(void *b, unsigned long size)
146 unsigned long start = (unsigned long)b;
147 unsigned long al_start;
148 al_start = (start + Min_size - 1) & ~(Min_size -1);
150 //printf("Buddy::add_mem(%p, %lx): al_start=%lx; _base=%lx\n", b, size, al_start, _base);
153 if (size <= al_start-start)
156 size -= (al_start-start);
157 size &= ~(Min_size -1);
161 free((void*)al_start, Min_size);
162 al_start += Min_size;
172 template<int A, int B, int M>
175 Buddy_t_base<A,B,M>::split(Head *b, unsigned size_index, unsigned i)
177 //unsigned si = size_index;
178 //printf("Buddy::split(%p, %d, %d)\n", b, size_index, i);
179 for (; i > size_index; ++size_index)
181 unsigned long buddy = (unsigned long)b + (Min_size << size_index);
182 Head::link(_free[size_index], (void*)buddy, size_index);
183 _free_map.set_bit((buddy - _base) / Min_size);
190 template<int A, int B, int M>
193 Buddy_t_base<A,B,M>::alloc(unsigned long size)
195 unsigned size_index = 0;
196 while (((unsigned long)Min_size << size_index) < size)
199 if (size != (unsigned long)Min_size << size_index)
200 WARNX(Info, "Buddy::alloc: Size mismatch: %lx v %lx\n",
201 size, (unsigned long)Min_size << size_index);
203 //printf("[%u]: Buddy::alloc(%ld)[ret=%p]: size_index=%d\n", Proc::cpu_id(), size, __builtin_return_address(0), size_index);
205 for (unsigned i = size_index; i < Num_sizes; ++i)
207 Head *f = _free[i].front();
211 split(f, size_index, i);
212 _free_map.clear_bit(((unsigned long)f - _base) / Min_size);
213 //printf("[%u]: =%p\n", Proc::cpu_id(), f);
221 template< int A, int B, int M >
223 Buddy_t_base<A,B,M>::dump() const
225 printf("Buddy_alloc [%d,%d]\n", Min_size, Num_sizes);
226 for (unsigned i = 0; i < Num_sizes; ++i)
229 B_list::Const_iterator h = _free[i].begin();
230 printf(" [%d] %p(%ld)", Min_size << i, *h, h != _free[i].end() ? h->index : 0UL);
231 while (h != _free[i].end())
235 printf(" -> %p(%ld)", *h, *h?h->index:0UL);
250 Buddy_base::init(unsigned long base)
254 template< int A, int B, int M >
256 Buddy_t_base<A,B,M>::avail() const
259 for (unsigned i = 0; i < Num_sizes; ++i)
261 for (B_list::Const_iterator h = _free[i].begin(); h != _free[i].end(); ++h)
262 a += (Min_size << i);