26 next->prev_next = prev_next;
30 static void link(Head **h, void *b, unsigned idx)
37 (*h)->prev_next = &(n->next);
43 template< int MIN_LOG2_SIZE, int NUM_SIZES, int MAX_MEM >
44 class Buddy_t_base : public Buddy_base
49 Min_log2_size = MIN_LOG2_SIZE,
50 Min_size = 1UL << MIN_LOG2_SIZE,
51 Num_sizes = NUM_SIZES,
52 Max_size = Min_size << NUM_SIZES,
59 // the number of bits in the bitmap is given by the amount of the smallest
60 // supported blocks. We need an extra bit in the case that the Max_mem
61 // is no multiple of Max_size to ensure that buddy() does not access
63 Buddy_bits = (Max_mem + Min_size - 1)/Min_size
64 + !!(Max_mem & (Max_size-1))
66 Head *_free[Num_sizes];
67 Bitmap<Buddy_bits> _free_map;
71 class Buddy_alloc : public Buddy_t_base<10, 8, Config::kernel_mem_max>
76 //----------------------------------------------------------------------------
85 template<int A, int B, int M>
88 Buddy_t_base<A,B,M>::buddy(void *block, unsigned long index, Head **new_block)
90 //printf("buddy(%p, %ld)\n", block, index);
91 unsigned long const size = Min_size << index;
92 unsigned long const n_size = size << 1;
93 if (index + 1 >= Num_sizes)
95 unsigned long b = (unsigned long)block;
96 unsigned long _buddy = b & ~(n_size-1);
97 *new_block = (Head*)_buddy;
101 Head * const _buddy_h = (Head*)_buddy;
103 // this test may access one bit behind our maximum, this is safe because
104 // we allocated an extra bit
105 if (_free_map[(_buddy - _base)/Min_size] && _buddy_h->index == index)
112 template<int A, int B, int M>
115 Buddy_t_base<A,B,M>::free(void *block, unsigned long size)
117 assert_kdb ((unsigned long)block >= _base);
118 assert_kdb ((unsigned long)block - _base < Max_mem);
119 assert_kdb (!_free_map[((unsigned long)block - _base) / Min_size]);
121 //if (_debug) printf("Buddy::free(%p, %ld)\n", block, size);
122 unsigned size_index = 0;
123 while (((unsigned long)Min_size << size_index) < size)
126 if (size != (unsigned long)Min_size << size_index)
127 WARNX(Info, "Buddy::free: Size mismatch: %lx v %lx\n",
128 size, (unsigned long)Min_size << size_index);
131 // no need to look for a buddy if we already have the biggest block size
132 while (size_index + 1 < Num_sizes)
135 b = buddy(block, size_index, &n);
138 //if (!_b && _debug) dump();
139 //if (_debug) printf(" found buddy %p (n=%p size=%ld)\n", b, n, size_index+1);
149 //printf(" link free %p\n", block);
150 Head::link(_free + size_index, block, size_index);
151 _free_map.set_bit(((unsigned long)block - _base) / Min_size);
152 //if (_b && _debug) dump();
157 template<int A, int B, int M>
159 Buddy_t_base<A,B,M>::add_mem(void *b, unsigned long size)
161 unsigned long start = (unsigned long)b;
162 unsigned long al_start;
163 al_start = (start + Min_size - 1) & ~(Min_size -1);
165 //printf("Buddy::add_mem(%p, %lx): al_start=%lx; _base=%lx\n", b, size, al_start, _base);
168 if (size <= al_start-start)
171 size -= (al_start-start);
172 size &= ~(Min_size -1);
176 free((void*)al_start, Min_size);
177 al_start += Min_size;
187 template<int A, int B, int M>
190 Buddy_t_base<A,B,M>::split(Head *b, unsigned size_index, unsigned i)
192 //unsigned si = size_index;
193 //printf("Buddy::split(%p, %d, %d)\n", b, size_index, i);
194 for (; i > size_index; ++size_index)
196 unsigned long buddy = (unsigned long)b + (Min_size << size_index);
197 Head::link(_free + size_index, (void*)buddy, size_index);
198 _free_map.set_bit((buddy - _base) / Min_size);
205 template<int A, int B, int M>
208 Buddy_t_base<A,B,M>::alloc(unsigned long size)
210 unsigned size_index = 0;
211 while (((unsigned long)Min_size << size_index) < size)
214 if (size != (unsigned long)Min_size << size_index)
215 WARNX(Info, "Buddy::alloc: Size mismatch: %lx v %lx\n",
216 size, (unsigned long)Min_size << size_index);
218 //printf("[%u]: Buddy::alloc(%ld)[ret=%p]: size_index=%d\n", Proc::cpu_id(), size, __builtin_return_address(0), size_index);
220 for (unsigned i = size_index; i < Num_sizes; ++i)
226 split(f, size_index, i);
227 _free_map.clear_bit(((unsigned long)f - _base) / Min_size);
228 //printf("[%u]: =%p\n", Proc::cpu_id(), f);
236 template< int A, int B, int M >
238 Buddy_t_base<A,B,M>::dump() const
240 printf("Buddy_alloc [%d,%d]\n", Min_size, Num_sizes);
241 for (unsigned i = 0; i < Num_sizes; ++i)
245 printf(" [%d] %p(%ld)", Min_size << i, h, h?h->index:0UL);
250 printf(" -> %p(%ld)", h, h?h->index:0UL);
265 Buddy_base::init(unsigned long base)
269 template< int A, int B, int M >
271 Buddy_t_base<A,B,M>::avail() const
274 for (unsigned i = 0; i < Num_sizes; ++i)
279 a += (Min_size << i);