arena: Use qcaches (slabs) in the arena
[akaros.git] / kern / src / arena.c
1 /* Copyright (c) 2016 Google Inc
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Arena resource allocator, based on Bonwick and Adams's "Magazines and Vmem:
6  * Extending the Slab Allocator to Many CPUs and Arbitrary Resources".
7  *
8  * There are two major arenas (or arena types; see the NUMA discussion below):
9  * base_arena and kpages_arena.  The base_arena consists of all the virtual
10  * addresses of the KERNBASE mapping, and is entirely self-sufficient.  Some
11  * slab caches pull directly from this arena.  The kpages_arena pulls from the
12  * base_arena and adds a level of quantum/slab caching.  Most users will pull
13  * from kpages_arena.
14  *
15  * For jumbo pages, you'd think we'd want a larger page sizes to be the source
16  * for the smaller page size arenas.  E.g. 'base' is a PML3 allocator.  The
17  * problem with that is that a base allocator needs to be self-sufficient, which
18  * means it needs to allocate its own boundary tags.  We'd prefer to use a small
19  * page for that.  So instead, we can flip the hierarchy around.  A base
20  * allocator uses a PGSIZE quantum, and the jumbo allocators are source from
21  * the base arena using an aligned allocation helper for its afunc.  I think,
22  * without a lot of thought, that the fragmentation would be equivalent.
23  *
24  * In the future, we can set up N base_arenas, one for each NUMA domain, each of
25  * which is a source for other NUMA allocators, e.g. kpages_i_arena.  Higher
26  * level allocators (kmalloc()) will need to choose a NUMA domain and call into
27  * the correct allocator.  Each NUMA base arena is self-sufficient: they have no
28  * qcaches and their BTs come from their own free page list.  This just
29  * replicates the default memory allocator across each NUMA node, and at some
30  * point, some generic allocator software needs to pick which node to pull from.
31  * I tried to keep assumptions about a single base_arena to a minimum, but
32  * you'll see some places where the arena code needs to find some base arena for
33  * its BT allocations.  Also note that the base setup happens before we know
34  * about NUMA domains.  The plan is to do a small part of domain 0 during
35  * pmem_init(), then once we know the full memory layout, add in the rest of
36  * domain 0's memory and bootstrap the other domains.
37  *
38  * When it comes to importing spans, it's not clear whether or not we should
39  * import exactly the current allocation request or to bring in more.  If we
40  * don't bring in more, then a child arena will have a span for every allocation
41  * and will return that span to the source whenever the segment is freed.  We'll
42  * never get the Figure 4.4 from the Vmem paper.  Alternatively, we could either
43  * allow partial frees of segments or we could hang on to completely free spans
44  * for a *while*, and possibly require a reclaim callback.  In the meantime, I
45  * added a per-arena scaling factor where we can adjust how much we import.
46  *
47  * TODO:
48  * - Blocking.  We'll probably want to reserve some memory for emergencies to
49  *   help us get out of OOM.  So we might block when we're at low-mem, not at 0.
50  *   We probably should have a sorted list of desired amounts, and unblockers
51  *   poke the CV if the first waiter is likely to succeed.
52  * - qcaching
53  * - We'll need some linkage between sources and parent arenas, with callbacks
54  *   or something when the base arena starts to run low on memory.  Once an
55  *   arena (whether base or o/w) gets the "time to free up memory" call, it can
56  *   call into any of its children, to include slabs and whatever else.
57  *
58  * FAQ:
59  * - Does allocating memory from an arena require it to take a btag?  Yes -
60  *   unless the allocation is for the exact size of an existing btag/segment.
61  * - Why does arena_free() need size?  Isn't it just for sanity checks?  No - it
62  *   is also used to determine which slab/qcache to return the segment to.
63  * - Why does a jumbo page arena use its own import function, instead of just
64  *   xallocing from kpages with alignment?  Because of fragmentation.  kpages
65  *   pulls directly from base, using a normal alloc for its import function
66  *   (afunc).  Because of this, its xalloc needs to request size + align, which
67  *   will fragment base.  It's better for jumbo to call xalloc directly on base,
68  *   in essence pushing the aligned alloc as far down the stack as possible.
69  * - Does the stuff in a qcache (allocated or free/available) count against the
70  *   arena's total/free amounts?  No, at least not the way I did it.  That's why
71  *   it's called amt_total_segs: segments, not free memory.  Those slab/qcaches
72  *   will have their own stats, and it'd be a minor pain to sync up with them
73  *   all the time.  Also, the important stat is when the base arena starts to
74  *   run out of memory, and base arenas don't have qcaches, so it's moot.
75  */
76
77 #include <arena.h>
78 #include <kmalloc.h>
79 #include <string.h>
80 #include <stdio.h>
81 #include <hash.h>
82 #include <slab.h>
83
84 TAILQ_HEAD(arena_tailq, arena);
85 static struct arena_tailq all_arenas = TAILQ_HEAD_INITIALIZER(all_arenas);
86 static spinlock_t all_arenas_lock = SPINLOCK_INITIALIZER;
87
88 struct arena *base_arena;
89 struct arena *kpages_arena;
90
91 /* Misc helpers and forward declarations */
92 static struct btag *__get_from_freelists(struct arena *arena, int list_idx);
93 static bool __account_alloc(struct arena *arena, struct btag *bt, size_t size,
94                             struct btag *new);
95 static void *__xalloc_nextfit(struct arena *arena, size_t size, size_t align,
96                               size_t phase, size_t nocross);
97 static void __try_hash_resize(struct arena *arena, int flags,
98                               void **to_free_addr, size_t *to_free_sz);
99 static void __arena_asserter(struct arena *arena);
100 void print_arena_stats(struct arena *arena, bool verbose);
101
102 /* For NUMA situations, where there are multiple base arenas, we'll need a way
103  * to find *some* base arena.  Ideally, it'll be in the same NUMA domain as
104  * arena. */
105 static struct arena *find_my_base(struct arena *arena)
106 {
107         /* TODO: could walk down sources until is_base is set.  But barring that,
108          * we'd still need a way to find a base arena for some other allocator that
109          * just wants a page.  arena may be NULL, so handle that. */
110         return base_arena;
111 }
112
113 static void setup_qcaches(struct arena *arena, size_t quantum,
114                           size_t qcache_max)
115 {
116         int nr_qcaches = qcache_max / quantum;
117         char kc_name[KMC_NAME_SZ];
118         size_t qc_size;
119
120         if (!nr_qcaches)
121                 return;
122
123         /* TODO: same as with hash tables, here and in slab.c, we ideally want the
124          * nearest kpages arena, but bootstrappers need to use base_alloc. */
125         arena->qcaches = base_alloc(arena, nr_qcaches * sizeof(struct kmem_cache),
126                                     MEM_WAIT);
127         for (int i = 0; i < nr_qcaches; i++) {
128                 qc_size = (i + 1) * quantum;
129                 snprintf(kc_name, KMC_NAME_SZ, "%s_%d", arena->name, qc_size);
130                 __kmem_cache_create(&arena->qcaches[i], kc_name, qc_size, quantum,
131                                     KMC_NOTOUCH | KMC_QCACHE, arena, NULL, NULL);
132         }
133 }
134
135 /* Helper to init.  Split out from create so we can bootstrap. */
136 static void arena_init(struct arena *arena, char *name, size_t quantum,
137                        void *(*afunc)(struct arena *, size_t, int),
138                        void (*ffunc)(struct arena *, void *, size_t),
139                        struct arena *source, size_t qcache_max)
140 {
141         static_assert((ARENA_ALLOC_STYLES & MEM_FLAGS) == 0);
142
143         spinlock_init_irqsave(&arena->lock);
144         arena->import_scale = 0;
145         arena->is_base = FALSE;
146         if (qcache_max % quantum)
147                 panic("Arena %s, qcache_max %p must be a multiple of quantum %p",
148                       name, qcache_max, quantum);
149         arena->quantum = quantum;
150         arena->qcache_max = qcache_max;
151         arena->afunc = afunc;
152         arena->ffunc = ffunc;
153         arena->source = source;
154         if (source)
155                 assert(afunc && ffunc);
156         arena->amt_total_segs = 0;
157         arena->amt_alloc_segs = 0;
158         arena->nr_allocs_ever = 0;
159
160         arena->all_segs = RB_ROOT;
161         BSD_LIST_INIT(&arena->unused_btags);
162         for (int i = 0; i < ARENA_NR_FREE_LISTS; i++)
163                 BSD_LIST_INIT(&arena->free_segs[i]);
164
165         arena->alloc_hash = arena->static_hash;
166         hash_init_hh(&arena->hh);
167         for (int i = 0; i < arena->hh.nr_hash_lists; i++)
168                 BSD_LIST_INIT(&arena->static_hash[i]);
169
170         strlcpy(arena->name, name, ARENA_NAME_SZ);
171         setup_qcaches(arena, quantum, qcache_max);
172
173         spin_lock(&all_arenas_lock);
174         TAILQ_INSERT_TAIL(&all_arenas, arena, next);
175         spin_unlock(&all_arenas_lock);
176 }
177
178 struct arena *arena_create(char *name, void *base, size_t size, size_t quantum,
179                            void *(*afunc)(struct arena *, size_t, int),
180                            void (*ffunc)(struct arena *, void *, size_t),
181                            struct arena *source, size_t qcache_max, int flags)
182 {
183         struct arena *arena;
184
185         /* See note in arena_add() */
186         if (source && base)
187                 panic("Arena can't have both a source and an initial span");
188         arena = kmalloc(sizeof(struct arena), flags);
189         if (!arena)
190                 return 0;
191         arena_init(arena, name, quantum, afunc, ffunc, source, qcache_max);
192         if (base) {
193                 if (!arena_add(arena, base, size, flags)) {
194                         warn("Failed to add base to arena %s, aborting!", arena->name);
195                         arena_destroy(arena);
196                         return 0;
197                 }
198         }
199         return arena;
200 }
201
202 void arena_destroy(struct arena *arena)
203 {
204         struct btag *bt_i, *temp;
205
206         spin_lock(&all_arenas_lock);
207         TAILQ_REMOVE(&all_arenas, arena, next);
208         spin_unlock(&all_arenas_lock);
209
210         for (int i = 0; i < arena->hh.nr_hash_lists; i++)
211                 assert(BSD_LIST_EMPTY(&arena->alloc_hash[i]));
212         if (arena->alloc_hash != arena->static_hash)
213                 kfree(arena->alloc_hash);
214         /* We shouldn't have any spans left.  We can tell we messed up if we had a
215          * source and still have some free segments.  Otherwise, just collect the
216          * free tags on the unused btag list. */
217         for (int i = 0; i < ARENA_NR_FREE_LISTS; i++) {
218                 if (arena->source)
219                         assert(BSD_LIST_EMPTY(&arena->free_segs[i]));
220                 BSD_LIST_FOREACH_SAFE(bt_i, &arena->free_segs[i], misc_link, temp) {
221                         BSD_LIST_REMOVE(bt_i, misc_link);
222                         BSD_LIST_INSERT_HEAD(&arena->unused_btags, bt_i, misc_link);
223                 }
224         }
225         /* To free our BTs, we need to give the page back to the base arena.  The
226          * BTs that are page aligned are the ones we want.  We can just ignore the
227          * others (unlink from the list). */
228         BSD_LIST_FOREACH_SAFE(bt_i, &arena->unused_btags, misc_link, temp) {
229                 if (PGOFF(bt_i->start))
230                         BSD_LIST_REMOVE(bt_i, misc_link);
231         }
232         /* Now the remaining BTs are the first on their page. */
233         BSD_LIST_FOREACH_SAFE(bt_i, &arena->unused_btags, misc_link, temp)
234                 arena_free(find_my_base(arena), (void*)bt_i->start, PGSIZE);
235         kfree(arena);
236 }
237
238 static void __insert_btag(struct rb_root *root, struct btag *bt)
239 {
240         struct rb_node **new = &root->rb_node, *parent = NULL;
241         struct btag *node;
242
243         while (*new) {
244                 node = container_of(*new, struct btag, all_link);
245                 parent = *new;
246                 /* Span (BTAG_SPAN) nodes are ahead (less than) of regular segment nodes
247                  * (BTAG_FREE or BTAG_ALLOC) that have the same start. */
248                 if (bt->start < node->start)
249                         new = &parent->rb_left;
250                 else if (bt->start > node->start)
251                         new = &parent->rb_right;
252                 else if (node->status == BTAG_SPAN)
253                         new = &parent->rb_right;
254                 else
255                         panic("BT %p already in tree %p!", bt, root);
256         }
257         rb_link_node(&bt->all_link, parent, new);
258         rb_insert_color(&bt->all_link, root);
259 }
260
261 /* Helper: tracks a seg pointed to by @bt as being allocated, assuming it is
262  * already off the free list (or was never on).  This doesn't do anything with
263  * all_segs; that's someone else's job (usually bt is already on it). */
264 static void __track_alloc_seg(struct arena *arena, struct btag *bt)
265 {
266         size_t hash_idx;
267
268         bt->status = BTAG_ALLOC;
269         hash_idx = hash_long(bt->start, arena->hh.nr_hash_bits);
270         BSD_LIST_INSERT_HEAD(&arena->alloc_hash[hash_idx], bt, misc_link);
271         arena->hh.nr_items++;
272 }
273
274 /* Helper: untracks a seg pointed to by @bt as being allocated.  Basically,
275  * removes it from the alloc_hash. */
276 static struct btag *__untrack_alloc_seg(struct arena *arena, uintptr_t start)
277 {
278         size_t hash_idx;
279         struct btag *bt_i;
280
281         hash_idx = hash_long(start, arena->hh.nr_hash_bits);
282         BSD_LIST_FOREACH(bt_i, &arena->alloc_hash[hash_idx], misc_link) {
283                 if (bt_i->start == start) {
284                         BSD_LIST_REMOVE(bt_i, misc_link);
285                         assert(bt_i->status == BTAG_ALLOC);
286                         arena->hh.nr_items--;
287                         return bt_i;
288                 }
289         }
290         return NULL;
291 }
292
293 /* Helper, tries to resize our hash table, if necessary.  Call with the lock
294  * held, but beware that this will unlock and relock - meaning, don't rely on
295  * the lock to protect invariants, but hold it as an optimization.
296  *
297  * A lot of the nastiness here is related to the allocation.  Critically, we
298  * might be the base arena, so it'd be nice to unlock before calling into
299  * ourselves (o/w deadlock).  Likewise, we'd like to be able to do a blocking
300  * allocation, if flags has MEM_WAIT.  We'd need to unlock for that too. */
301 static void __try_hash_resize(struct arena *arena, int flags,
302                               void **to_free_addr, size_t *to_free_sz)
303 {
304         struct btag_list *new_tbl, *old_tbl;
305         struct btag *bt_i;
306         unsigned int new_tbl_nr_lists, old_tbl_nr_lists;
307         size_t new_tbl_sz, old_tbl_sz;
308         size_t hash_idx;
309
310         if (!hash_needs_more(&arena->hh))
311                 return;
312         new_tbl_nr_lists = hash_next_nr_lists(&arena->hh);
313         /* We want future checkers to not think we need an increase, to avoid
314          * excessive hash resizers as well as base arena deadlocks (base_alloc must
315          * not call into base_alloc infinitely) */
316         hash_set_load_limit(&arena->hh, SIZE_MAX);
317         spin_unlock_irqsave(&arena->lock);
318         new_tbl_sz = new_tbl_nr_lists * sizeof(struct btag_list);
319         /* Regardless of the caller's style, we'll try and be quick with INSTANT. */
320         flags &= ~ARENA_ALLOC_STYLES;
321         flags |= ARENA_INSTANTFIT;
322         new_tbl = base_zalloc(arena, new_tbl_sz, flags);
323         spin_lock_irqsave(&arena->lock);
324         if (!new_tbl) {
325                 /* Need to reset so future callers will try to grow. */
326                 hash_reset_load_limit(&arena->hh);
327                 spin_unlock_irqsave(&arena->lock);
328                 return;
329         }
330         /* After relocking, we need to re-verify that we want to go ahead.  It's
331          * possible that another thread resized the hash already, which we can
332          * detect because our alloc size is wrong. */
333         if (new_tbl_nr_lists != hash_next_nr_lists(&arena->hh)) {
334                 spin_unlock_irqsave(&arena->lock);
335                 base_free(arena, new_tbl, new_tbl_sz);
336                 return;
337         }
338         old_tbl = arena->alloc_hash;
339         old_tbl_nr_lists = arena->hh.nr_hash_lists;
340         old_tbl_sz = old_tbl_nr_lists * sizeof(struct btag_list);
341         arena->alloc_hash = new_tbl;
342         hash_incr_nr_lists(&arena->hh);
343         for (int i = 0; i < old_tbl_nr_lists; i++) {
344                 while ((bt_i = BSD_LIST_FIRST(&old_tbl[i]))) {
345                         BSD_LIST_REMOVE(bt_i, misc_link);
346                         hash_idx = hash_long(bt_i->start, arena->hh.nr_hash_bits);
347                         BSD_LIST_INSERT_HEAD(&arena->alloc_hash[hash_idx], bt_i, misc_link);
348                 }
349         }
350         hash_reset_load_limit(&arena->hh);
351         if (old_tbl != arena->static_hash) {
352                 *to_free_addr = old_tbl;
353                 *to_free_sz = old_tbl_sz;
354         }
355 }
356
357 /* Typically this will be just checking for one or two BTs on the free list */
358 static bool __has_enough_btags(struct arena *arena, size_t nr_needed)
359 {
360         struct btag *bt_i;
361         size_t so_far = 0;
362
363         BSD_LIST_FOREACH(bt_i, &arena->unused_btags, misc_link) {
364                 so_far++;
365                 if (so_far == nr_needed)
366                         return TRUE;
367         }
368         return FALSE;
369 }
370
371 /* Allocs new boundary tags and puts them on the arena's free list.  Returns 0
372  * on failure, which could happen if MEM_ATOMIC is set).  Hold the lock when you
373  * call this, but note it will unlock and relock.
374  *
375  * The base arena is special in that it must be self-sufficient.  It will create
376  * get its free page from itself.  Other arena's just pull from base in the
377  * normal fashion.  We could pull from kpages_arena, but that would require a
378  * little more special casing.  Maybe in the future.
379  *
380  * Note that BTs are only freed when the arena is destroyed.  We use the fact
381  * that the first BT is at an aligned address to track the specific page it came
382  * from. */
383 static struct btag *__add_more_btags(struct arena *arena, int mem_flags)
384 {
385         struct btag *bt, *tags;
386         size_t nr_bts = PGSIZE / sizeof(struct btag);
387
388         if (arena->is_base) {
389                 bt = __get_from_freelists(arena, LOG2_UP(PGSIZE));
390                 if (!bt) {
391                         /* TODO: block / reclaim if not MEM_ATOMIC.  Remember, we hold the
392                          * lock!  We might need to rework this or get a reserved page. */
393                         if (!(mem_flags & MEM_ATOMIC))
394                                 panic("Base failed to alloc its own btag, OOM!");
395                         return 0;
396                 }
397                 /* __account_alloc() will often need a new BT; specifically when we
398                  * only need part of the segment tracked by the BT.  Since we don't have
399                  * any extra BTs, we'll use the first one on the page we just allocated.
400                  */
401                 tags = (struct btag*)bt->start;
402                 if (__account_alloc(arena, bt, PGSIZE, &tags[0])) {
403                         /* We used the tag[0]; we'll have to skip over it now. */
404                         tags++;
405                         nr_bts--;
406                 }
407         } else {
408                 /* Here's where we unlock and relock around a blocking call */
409                 spin_unlock_irqsave(&arena->lock);
410                 tags = arena_alloc(find_my_base(arena), PGSIZE,
411                                    mem_flags | ARENA_INSTANTFIT);
412                 spin_lock_irqsave(&arena->lock);
413                 if (!tags)
414                         return 0;
415         }
416         for (int i = 0; i < nr_bts; i++)
417                 BSD_LIST_INSERT_HEAD(&arena->unused_btags, &tags[i], misc_link);
418         return tags;
419 }
420
421 /* Helper, returns TRUE when we have enough BTs.  Hold the lock, but note this
422  * will unlock and relock, and will attempt to acquire more BTs.  Returns FALSE
423  * if an alloc failed (MEM_ATOMIC).
424  *
425  * This complexity is so that we never fail an arena operation due to lack of
426  * memory unless the caller has MEM_ATOMIC set.  Further, __get_btag() never
427  * fails, which makes other code easier.  Otherwise, functions that currently
428  * call __get_btag will need one or two BTs passed in from their callers, who
429  * allocate/remove from the list at a place where they can easily fail. */
430 static bool __get_enough_btags(struct arena *arena, size_t nr_needed,
431                                int mem_flags)
432 {
433         if (__has_enough_btags(arena, nr_needed))
434                 return TRUE;
435         /* This will unlock and relock, and maybe block. */
436         if (!__add_more_btags(arena, mem_flags)) {
437                 /* This is the only failure scenario */
438                 assert(mem_flags & MEM_ATOMIC);
439                 return FALSE;
440         }
441         /* Since the lock was held in __add_more_btags, no one should have been able
442          * to drain them.  If someone asked for more than a page worth of BTs,
443          * there's a problem somewhere else. */
444         assert(__has_enough_btags(arena, nr_needed));
445         return TRUE;
446 }
447
448 /* Helper: gets a btag.  All callpaths must have made sure the arena has enough
449  * tags before starting its operation, holding the lock throughout.  Thus, this
450  * cannot fail. */
451 static struct btag *__get_btag(struct arena *arena)
452 {
453         struct btag *ret;
454
455         ret = BSD_LIST_FIRST(&arena->unused_btags);
456         /* All code paths should have made sure that there were enough BTs before
457          * diving in. */
458         assert(ret);
459         BSD_LIST_REMOVE(ret, misc_link);
460         return ret;
461 }
462
463 static void __free_btag(struct arena *arena, struct btag *bt)
464 {
465         BSD_LIST_INSERT_HEAD(&arena->unused_btags, bt, misc_link);
466 }
467
468 /* Helper: adds seg pointed to by @bt to the appropriate free list of @arena. */
469 static void __track_free_seg(struct arena *arena, struct btag *bt)
470 {
471         int list_idx = LOG2_DOWN(bt->size);
472
473         bt->status = BTAG_FREE;
474         BSD_LIST_INSERT_HEAD(&arena->free_segs[list_idx], bt, misc_link);
475 }
476
477 /* Helper: removes seg pointed to by @bt from the appropriate free list of
478  * @arena. */
479 static void __untrack_free_seg(struct arena *arena, struct btag *bt)
480 {
481         BSD_LIST_REMOVE(bt, misc_link);
482 }
483
484 /* Helper: we decided we want to alloc part of @bt, which has been removed from
485  * its old list.  We need @size units.  The rest can go back to the arena.
486  *
487  * Takes @new, which we'll use if we need a new btag.  If @new is NULL, we'll
488  * allocate one.  If we used the caller's btag, we'll return TRUE.  This
489  * complexity is for a base arena's manual btag allocation. */
490 static bool __account_alloc(struct arena *arena, struct btag *bt,
491                             size_t size, struct btag *new)
492 {
493         bool ret = FALSE;
494
495         assert(bt->status == BTAG_FREE);
496         if (bt->size != size) {
497                 assert(bt->size > size);
498                 if (new)
499                         ret = TRUE;
500                 else
501                         new = __get_btag(arena);
502                 new->start = bt->start + size;
503                 new->size = bt->size - size;
504                 bt->size = size;
505                 __track_free_seg(arena, new);
506                 __insert_btag(&arena->all_segs, new);
507         }
508         __track_alloc_seg(arena, bt);
509         arena->amt_alloc_segs += size;
510         arena->nr_allocs_ever++;
511         return ret;
512 }
513
514 /* Helper: gets the first segment from the smallest, populated list. */
515 static struct btag *__get_from_freelists(struct arena *arena, int list_idx)
516 {
517         struct btag *ret = NULL;
518
519         for (int i = list_idx; i < ARENA_NR_FREE_LISTS; i++) {
520                 ret = BSD_LIST_FIRST(&arena->free_segs[i]);
521                 if (ret) {
522                         BSD_LIST_REMOVE(ret, misc_link);
523                         break;
524                 }
525         }
526         return ret;
527 }
528
529 /* Allocates using the 'best fit' policy.  Recall that each free_segs list holds
530  * segments of size [ 2^n, 2^(n+1) )  We try to find the smallest segment on
531  * that list that can satisfy the request.  Otherwise, any segment from a larger
532  * list will suffice. */
533 static void *__alloc_bestfit(struct arena *arena, size_t size)
534 {
535         int list_idx = LOG2_DOWN(size);
536         struct btag *bt_i, *best = NULL;
537
538         BSD_LIST_FOREACH(bt_i, &arena->free_segs[list_idx], misc_link) {
539                 if (bt_i->size >= size) {
540                         if (!best || (best->size > bt_i->size))
541                                 best = bt_i;
542                 }
543         }
544         if (best)
545                 BSD_LIST_REMOVE(best, misc_link);
546         else
547                 best = __get_from_freelists(arena, list_idx + 1);
548         if (!best)
549                 return NULL;
550         __account_alloc(arena, best, size, NULL);
551         return (void*)best->start;
552 }
553
554 static void *__alloc_nextfit(struct arena *arena, size_t size)
555 {
556         return __xalloc_nextfit(arena, size, arena->quantum, 0, 0);
557 }
558
559 /* Instant fit grabs the first segment guaranteed to be big enough.  Note that
560  * we round list_idx up, compared to bestfit's initial list.  That way, you're
561  * always sure you have a big enough segment. */
562 static void *__alloc_instantfit(struct arena *arena, size_t size)
563 {
564         struct btag *ret;
565
566         ret = __get_from_freelists(arena, LOG2_UP(size));
567         if (!ret)
568                 return NULL;
569         __account_alloc(arena, ret, size, NULL);
570         return (void*)ret->start;
571 }
572
573 /* Non-qcache allocation.  Hold the arena's lock.  Note that all allocations are
574  * done in multiples of the quantum. */
575 static void *alloc_from_arena(struct arena *arena, size_t size, int flags)
576 {
577         void *ret;
578         void *to_free_addr = 0;
579         size_t to_free_sz = 0;
580
581         spin_lock_irqsave(&arena->lock);
582         if (!__get_enough_btags(arena, 1, flags & MEM_FLAGS)) {
583                 spin_unlock_irqsave(&arena->lock);
584                 return NULL;
585         }
586         if (flags & ARENA_BESTFIT)
587                 ret = __alloc_bestfit(arena, size);
588         else if (flags & ARENA_NEXTFIT)
589                 ret = __alloc_nextfit(arena, size);
590         else
591                 ret = __alloc_instantfit(arena, size);
592         /* Careful, this will unlock and relock.  It's OK right before an unlock. */
593         __try_hash_resize(arena, flags, &to_free_addr, &to_free_sz);
594         spin_unlock_irqsave(&arena->lock);
595         if (to_free_addr)
596                 base_free(arena, to_free_addr, to_free_sz);
597         return ret;
598 }
599
600 /* It's probably a kernel bug if we're adding the wrong sized segments, whether
601  * via direct add, a source import, or creation. */
602 static void assert_quantum_alignment(struct arena *arena, void *base,
603                                      size_t size)
604 {
605         if (!ALIGNED(base, arena->quantum))
606                 panic("Unaligned base %p for arena %s, quantum %p, source %s", base,
607                       arena->name, arena->quantum,
608                       arena->source ? arena->source->name : "none");
609         if (!ALIGNED(size, arena->quantum))
610                 panic("Unaligned size %p for arena %s, quantum %p, source %s", size,
611                       arena->name, arena->quantum,
612                       arena->source ? arena->source->name : "none");
613 }
614
615 /* Adds segment [@base, @base + @size) to @arena.  We'll add a span tag if the
616  * arena had a source. */
617 static void *__arena_add(struct arena *arena, void *base, size_t size,
618                          int flags)
619 {
620         struct btag *bt, *span_bt;
621
622         /* These are just sanity checks.  Our client is the kernel, and it could
623          * mess with us in other ways, such as adding overlapping spans. */
624         assert_quantum_alignment(arena, base, size);
625         assert(base < base + size);
626         spin_lock_irqsave(&arena->lock);
627         /* Make sure there are two, bt and span. */
628         if (!__get_enough_btags(arena, 2, flags & MEM_FLAGS)) {
629                 spin_unlock_irqsave(&arena->lock);
630                 return NULL;
631         }
632         bt = __get_btag(arena);
633         if (arena->source) {
634                 span_bt = __get_btag(arena);
635                 span_bt->start = (uintptr_t)base;
636                 span_bt->size = size;
637                 span_bt->status = BTAG_SPAN;
638                 /* Note the btag span is not on any list, but it is in all_segs */
639                 __insert_btag(&arena->all_segs, span_bt);
640         }
641         bt->start = (uintptr_t)base;
642         bt->size = size;
643         arena->amt_total_segs += size;
644         __track_free_seg(arena, bt);
645         __insert_btag(&arena->all_segs, bt);
646         spin_unlock_irqsave(&arena->lock);
647         return base;
648 }
649
650 /* Adds segment [@base, @base + @size) to @arena. */
651 void *arena_add(struct arena *arena, void *base, size_t size, int flags)
652 {
653         /* This wasn't clear from the paper, but mixing source spans and manually
654          * added spans seems like a pain when coalescing BTs and freeing. */
655         if (arena->source)
656                 panic("Arenas with sources must not manually add resources.");
657         return __arena_add(arena, base, size, flags);
658 }
659
660 /* Attempt to get more resources, either from a source or by blocking.  Returns
661  * TRUE if we got something.  FALSE on failure (e.g. MEM_ATOMIC). */
662 static bool get_more_resources(struct arena *arena, size_t size, int flags)
663 {
664         void *span;
665         size_t import_size;
666
667         /* MAX check, in case size << scale overflows */
668         import_size = MAX(size, size << arena->import_scale);
669         if (arena->source) {
670                 span = arena->afunc(arena->source, import_size, flags);
671                 if (!span)
672                         return FALSE;
673                 if (!__arena_add(arena, span, import_size, flags)) {
674                         /* We could fail if MEM_ATOMIC and we couldn't get a BT */
675                         warn("Excessively rare failure, tell brho");
676                         arena->ffunc(arena->source, span, import_size);
677                         return FALSE;
678                 }
679         } else {
680                 /* TODO: allow blocking */
681                 if (!(flags & MEM_ATOMIC))
682                         panic("OOM!");
683                 return FALSE;
684         }
685         return TRUE;
686 }
687
688 /* Helper.  For a given size, return the applicable qcache. */
689 static struct kmem_cache *size_to_qcache(struct arena *arena, size_t size)
690 {
691         /* If we ever get grumpy about the costs of dividing (both here and in the
692          * ROUND ops, we could either insist that quantum is a power of two, or
693          * track whether or not it is and use other shifting ops. */
694         return &arena->qcaches[(size / arena->quantum) - 1];
695 }
696
697 void *arena_alloc(struct arena *arena, size_t size, int flags)
698 {
699         void *ret;
700
701         size = ROUNDUP(size, arena->quantum);
702         if (!size)
703                 panic("Arena %s, request for zero", arena->name);
704         if (size <= arena->qcache_max) {
705                 /* NEXTFIT is an error, since free won't know to skip the qcache and
706                  * then we'd be handing an item to the qcache that it didn't alloc. */
707                 if (flags & ARENA_NEXTFIT)
708                         panic("Arena %s, NEXTFIT, but has qcaches.  Use xalloc.",
709                               arena->name);
710                 return kmem_cache_alloc(size_to_qcache(arena, size), flags);
711         }
712         while (1) {
713                 ret = alloc_from_arena(arena, size, flags);
714                 if (ret)
715                         return ret;
716                 /* This is a little nasty.  We asked our source for enough, but it may
717                  * be a bestfit sized chunk, not an instant fit.  Since we already
718                  * failed once, we can just downgrade to BESTFIT, which will likely find
719                  * our recently-allocated span.  Even worse, the source might only give
720                  * us segments that are BESTFIT, and if we only look at the INSTANTFIT,
721                  * we'll keep looping.  The invariant here is that if we
722                  * get_more_resources, then our allocation can succeed if no one else
723                  * grabs that memory first.
724                  *
725                  * We actually have two options here.  Either we downgrade to BESTFIT or
726                  * we round up our request to our source to the nearest power of two.
727                  * Doing so brings some of the fragmentation into our arena, but an
728                  * instant fit is likely to succeed.  Considering how the first item on
729                  * the BESTFIT list is likely ours, downgrading makes sense. */
730                 flags &= ~ARENA_ALLOC_STYLES;
731                 flags |= ARENA_BESTFIT;
732                 if (!get_more_resources(arena, size, flags))
733                         return NULL;
734         }
735 }
736
737 /* Helper: given a BT's start and size, return a starting address within the BT
738  * that satisfies the constraints.  Returns 0 on failure.
739  *
740  * The rough idea is to go from the start, round up to align, add the phase, and
741  * see if it's still within the BT.  The 'nocross' boundary (also an alignment)
742  * complicates things a little. */
743 static uintptr_t __find_sufficient(uintptr_t bt_start, size_t bt_size,
744                                    size_t size, size_t align,
745                                    size_t phase, size_t nocross)
746 {
747         uintptr_t try;
748         size_t try_size;
749
750         try = bt_start;
751         try = ROUNDUP(try, align);
752         try += phase;
753         /* Wraparound due to phase. */
754         if (try < bt_start)
755                 return 0;
756         /* Check wraparound */
757         if (try + size < try)
758                 return 0;
759         /* Too big for BT, no chance. */
760         if (try + size > bt_start + bt_size)
761                 return 0;
762         if (nocross == 0)
763                 return try;
764         /* Got to deal with nocross boundaries.  If we round up from our potential
765          * start and that is beyond our potential finish, we're OK. */
766         if (ROUNDUP(try, nocross) >= try + size)
767                 return try;
768         /* The segment still might have a chance.  Perhaps we started right before a
769          * nocross.  Let's try again, being careful of overflow.  The ROUNDUP
770          * shouldn't trigger a wraparound. */
771         try = ROUNDUP(bt_start, nocross);
772         try_size = bt_size - (try - bt_start);
773         /* Underflow of bt_size - large_number. */
774         if (try_size > bt_size)
775                 return 0;
776         /* The caller has some control over our next invocation's bt_start and
777          * bt_size.  Let's enforce sanity. */
778         if (try + try_size < try)
779                 return 0;
780         return __find_sufficient(try, try_size, size, align, phase, 0);
781 }
782
783 /* Helper: splits bt, which is not on any freelist, at @at, and puts the front
784  * part back on a free list. */
785 static void __split_bt_at(struct arena *arena, struct btag *bt, uintptr_t at)
786 {
787         struct btag *front = __get_btag(arena);
788
789         /* We're changing bt's start, which is its key for its position in the
790          * all_segs tree.  However, we don't need to remove and reinsert it, since
791          * although we increased its start, we know that no BT should be between its
792          * old start and its new start.  That's actually where the front BT will get
793          * inserted (so long as we insert after changing bt's start). */
794         front->status = BTAG_FREE;
795         front->start = bt->start;
796         front->size = at - bt->start;
797         bt->start += front->size;
798         bt->size -= front->size;
799         __track_free_seg(arena, front);
800         __insert_btag(&arena->all_segs, front);
801         /* At this point, bt's old space in all_segs is broken into:
802          * front: [old_start, try), bt: [try, old_end).  front is on the free list.
803          * bt is not. */
804 }
805
806 /* Helper.  We want the first bt >= mindaddr, with prev < minaddr. */
807 static bool __found_least_upper_btag(struct btag *bt, uintptr_t minaddr)
808 {
809         struct rb_node *prev;
810
811         if (bt->start < minaddr)
812                 return FALSE;
813         prev = rb_prev(&bt->all_link);
814         if (!prev)
815                 return TRUE;
816         if (container_of(prev, struct btag, all_link)->start < minaddr)
817                 return TRUE;
818         return FALSE;
819 }
820
821 /* Does the a search in min/max for a segment. */
822 static void *__xalloc_min_max(struct arena *arena, size_t size,
823                               size_t align, size_t phase, size_t nocross,
824                               uintptr_t minaddr, uintptr_t maxaddr)
825 {
826         struct rb_node *node = arena->all_segs.rb_node;
827         struct btag *bt;
828         uintptr_t try;
829
830         /* Find the first bt >= minaddr */
831         while (node) {
832                 bt = container_of(node, struct btag, all_link);
833                 if (__found_least_upper_btag(bt, minaddr))
834                         break;
835                 if (minaddr < bt->start)
836                         node = node->rb_left;
837                 else
838                         node = node->rb_right;
839         }
840         /* Now we're probably at the first start point (or there's no node).  Just
841          * scan from here. */
842         for (/* node set */; node; node = rb_next(node)) {
843                 bt = container_of(node, struct btag, all_link);
844                 try = __find_sufficient(bt->start, bt->size, size, align, phase,
845                                         nocross);
846                 if (!try)
847                         continue;
848                 if (maxaddr && (try + size > maxaddr))
849                         return NULL;
850                 __untrack_free_seg(arena, bt);
851                 if (try != bt->start)
852                         __split_bt_at(arena, bt, try);
853                 __account_alloc(arena, bt, size, NULL);
854                 return (void*)bt->start;
855         }
856         return NULL;
857 }
858
859 /* For xalloc, there isn't any real instant fit, due to the nocross issues.  We
860  * can still try to get a quicker fit by starting on a higher order list. */
861 static void *__xalloc_from_freelists(struct arena *arena, size_t size,
862                                      size_t align, size_t phase, size_t nocross,
863                                      bool try_instant_fit)
864 {
865         int list_idx;
866         struct btag *bt_i;
867         uintptr_t try = 0;
868
869         if (ROUNDUP(size, align) + phase < size)
870                 return NULL;
871         list_idx = LOG2_DOWN(ROUNDUP(size, align) + phase);
872         list_idx += try_instant_fit ? 1 : 0;
873         for (int i = list_idx; i < ARENA_NR_FREE_LISTS; i++) {
874                 BSD_LIST_FOREACH(bt_i, &arena->free_segs[i], misc_link) {
875                         try = __find_sufficient(bt_i->start, bt_i->size, size, align,
876                                                 phase, nocross);
877                         if (try) {
878                                 BSD_LIST_REMOVE(bt_i, misc_link);
879                                 break;
880                         }
881                 }
882                 if (try)
883                         break;
884         }
885         if (!try)
886                 return NULL;
887         if (try != bt_i->start)
888                 __split_bt_at(arena, bt_i, try);
889         __account_alloc(arena, bt_i, size, NULL);
890         return (void*)bt_i->start;
891 }
892
893 static void *__xalloc_nextfit(struct arena *arena, size_t size, size_t align,
894                               size_t phase, size_t nocross)
895 {
896         void *ret;
897
898         /* NEXTFIT is a lot like a minaddr.  We can start from the old addr + 1,
899          * since the implementation of that helper starts a search from minaddr.  If
900          * it fails, we can try again from 1 (quantum, really), skipping 0. */
901         ret = __xalloc_min_max(arena, size, align, phase, nocross,
902                                arena->last_nextfit_alloc + arena->quantum, 0);
903         if (!ret) {
904                 ret = __xalloc_min_max(arena, size, align, phase, nocross,
905                                        arena->quantum, 0);
906         }
907         if (!ret)
908                 return NULL;
909         arena->last_nextfit_alloc = (uintptr_t)ret;
910         return ret;
911 }
912
913 static void *xalloc_from_arena(struct arena *arena, size_t size,
914                                size_t align, size_t phase, size_t nocross,
915                                void *minaddr, void *maxaddr, int flags)
916 {
917         void *ret;
918         void *to_free_addr = 0;
919         size_t to_free_sz = 0;
920
921         spin_lock_irqsave(&arena->lock);
922         /* Need two, since we might split a BT into 3 BTs. */
923         if (!__get_enough_btags(arena, 2, flags & MEM_FLAGS)) {
924                 spin_unlock_irqsave(&arena->lock);
925                 return NULL;
926         }
927         if (minaddr || maxaddr) {
928                 ret = __xalloc_min_max(arena, size, align, phase, nocross,
929                                        (uintptr_t)minaddr, (uintptr_t)maxaddr);
930         } else {
931                 if (flags & ARENA_BESTFIT) {
932                         ret = __xalloc_from_freelists(arena, size, align, phase, nocross,
933                                                       FALSE);
934                 } else if (flags & ARENA_NEXTFIT) {
935                         ret = __xalloc_nextfit(arena, size, align, phase, nocross);
936                 } else {
937                         ret = __xalloc_from_freelists(arena, size, align, phase, nocross,
938                                                       TRUE);
939                 }
940         }
941         /* Careful, this will unlock and relock.  It's OK right before an unlock. */
942         __try_hash_resize(arena, flags, &to_free_addr, &to_free_sz);
943         spin_unlock_irqsave(&arena->lock);
944         if (to_free_addr)
945                 base_free(arena, to_free_addr, to_free_sz);
946         return ret;
947 }
948
949 void *arena_xalloc(struct arena *arena, size_t size, size_t align, size_t phase,
950                    size_t nocross, void *minaddr, void *maxaddr, int flags)
951 {
952         void *ret;
953         size_t req_size;
954
955         size = ROUNDUP(size, arena->quantum);
956         if (!size)
957                 panic("Arena %s, request for zero", arena->name);
958         if (!IS_PWR2(align))
959                 panic("Arena %s, non-power of two align %p", arena->name, align);
960         if (nocross && !IS_PWR2(nocross))
961                 panic("Arena %s, non-power of nocross %p", arena->name, nocross);
962         if (!ALIGNED(align, arena->quantum))
963                 panic("Arena %s, non-aligned align %p", arena->name, align);
964         if (!ALIGNED(nocross, arena->quantum))
965                 panic("Arena %s, non-aligned nocross %p", arena->name, nocross);
966         if (!ALIGNED(phase, arena->quantum))
967                 panic("Arena %s, non-aligned phase %p", arena->name, phase);
968         if (size + align < size)
969                 panic("Arena %s, size %p + align %p overflow%p", arena->name, size,
970                       align);
971         if (size + phase < size)
972                 panic("Arena %s, size %p + phase %p overflow%p", arena->name, size,
973                       phase);
974         if (align + phase < align)
975                 panic("Arena %s, align %p + phase %p overflow%p", arena->name, align,
976                       phase);
977         /* Ok, it's a pain to import resources from a source such that we'll be able
978          * to guarantee we make progress without stranding resources if we have
979          * nocross or min/maxaddr.  For min/maxaddr, when we ask the source, we
980          * aren't easily able to xalloc from their (it may depend on the afunc).
981          * For nocross, we can't easily ask the source for the right span that
982          * satisfies the request (again, no real xalloc).  Some constraints might
983          * not even be possible.
984          *
985          * If we get a span from the source and never use it, then we run a risk of
986          * fragmenting and stranding a bunch of spans in our current arena.  Imagine
987          * the loop where we keep asking for spans (e.g. 8 pgs) and getting
988          * something that doesn't work.  Those 8 pgs are fragmented, and we won't
989          * give them back to the source until we allocate and then free them
990          * (barring some sort of reclaim callback).
991          *
992          * Besides, I don't know if we even need/want nocross/min/maxaddr. */
993         if (arena->source && (nocross || minaddr || maxaddr))
994                 panic("Arena %s, has source, can't xalloc with nocross %p, minaddr %p, or maxaddr %p",
995                       arena->name, nocross, minaddr, maxaddr);
996         while (1) {
997                 ret = xalloc_from_arena(arena, size, align, phase, nocross, minaddr,
998                                         maxaddr, flags);
999                 if (ret)
1000                         return ret;
1001                 /* We checked earlier than no two of these overflow, so I think we don't
1002                  * need to worry about multiple overflows. */
1003                 req_size = size + align + phase;
1004                 /* Note that this check isn't the same as the one we make when finding a
1005                  * sufficient segment.  Here we check overflow on the requested size.
1006                  * Later, we check aligned bt_start + phase.  The concern is that this
1007                  * check succeeds, but the other fails.  (Say size = PGSIZE, phase =
1008                  * -PGSIZE -1.  req_size is very large.
1009                  *
1010                  * In this case, we're still fine - if our source is able to satisfy the
1011                  * request, our bt_start and bt_size will be able to express that size
1012                  * without wrapping. */
1013                 if (req_size < size)
1014                         panic("Arena %s, size %p + align %p + phase %p overflow",
1015                               arena->name, size, align, phase);
1016                 if (!get_more_resources(arena, req_size, flags))
1017                         return NULL;
1018                 /* Our source may have given us a segment that is on the BESTFIT list,
1019                  * same as with arena_alloc. */
1020                 flags &= ~ARENA_ALLOC_STYLES;
1021                 flags |= ARENA_BESTFIT;
1022                 /* TODO: could put a check in here to make sure we don't loop forever,
1023                  * in case we trip some other bug. */
1024         }
1025 }
1026
1027 /* Helper: if possible, merges the right BT to the left.  Returns TRUE if we
1028  * merged. */
1029 static bool __merge_right_to_left(struct arena *arena, struct btag *left,
1030                                   struct btag *right)
1031 {
1032         /* These checks will also make sure we never merge SPAN boundary tags. */
1033         if (left->status != BTAG_FREE)
1034                 return FALSE;
1035         if (right->status != BTAG_FREE)
1036                 return FALSE;
1037         if (left->start + left->size == right->start) {
1038                 /* Need to yank left off its list before changing its size. */
1039                 __untrack_free_seg(arena, left);
1040                 __untrack_free_seg(arena, right);
1041                 left->size += right->size;
1042                 __track_free_seg(arena, left);
1043                 rb_erase(&right->all_link, &arena->all_segs);
1044                 __free_btag(arena, right);
1045                 return TRUE;
1046         }
1047         return FALSE;
1048 }
1049
1050 /* Merges @bt's segments with its adjacent neighbors.  If we end up having an
1051  * entire span free, we'll stop tracking it in this arena and return it for our
1052  * caller to free. */
1053 static void __coalesce_free_seg(struct arena *arena, struct btag *bt,
1054                                 void **to_free_addr, size_t *to_free_sz)
1055 {
1056         struct rb_node *rb_p, *rb_n;
1057         struct btag *bt_p, *bt_n;
1058
1059         rb_n = rb_next(&bt->all_link);
1060         if (rb_n) {
1061                 bt_n = container_of(rb_n, struct btag, all_link);
1062                 __merge_right_to_left(arena, bt, bt_n);
1063         }
1064         rb_p = rb_prev(&bt->all_link);
1065         if (rb_p) {
1066                 bt_p = container_of(rb_p, struct btag, all_link);
1067                 if (__merge_right_to_left(arena, bt_p, bt))
1068                         bt = bt_p;
1069         }
1070         /* Check for a span */
1071         rb_p = rb_prev(&bt->all_link);
1072         if (rb_p) {
1073                 bt_p = container_of(rb_p, struct btag, all_link);
1074                 if ((bt_p->status == BTAG_SPAN) &&
1075                     (bt_p->start == bt->start) &&
1076                     (bt_p->size == bt->size)) {
1077
1078                         *to_free_addr = (void*)bt_p->start;
1079                         *to_free_sz = bt_p->size;
1080                         /* Note the span was not on a free list */
1081                         __untrack_free_seg(arena, bt);
1082                         rb_erase(&bt_p->all_link, &arena->all_segs);
1083                         __free_btag(arena, bt_p);
1084                         rb_erase(&bt->all_link, &arena->all_segs);
1085                         __free_btag(arena, bt);
1086                 }
1087         }
1088 }
1089
1090 static void free_from_arena(struct arena *arena, void *addr, size_t size)
1091 {
1092         struct btag *bt;
1093         void *to_free_addr = 0;
1094         size_t to_free_sz = 0;
1095
1096         spin_lock_irqsave(&arena->lock);
1097         bt = __untrack_alloc_seg(arena, (uintptr_t)addr);
1098         if (!bt)
1099                 panic("Free of unallocated addr %p from arena %s", addr, arena->name);
1100         if (bt->size != size)
1101                 panic("Free of %p with wrong size %p (%p) from arena %s", addr, size,
1102                       bt->size, arena->name);
1103         arena->amt_alloc_segs -= size;
1104         __track_free_seg(arena, bt);
1105         __coalesce_free_seg(arena, bt, &to_free_addr, &to_free_sz);
1106         arena->amt_total_segs -= to_free_sz;
1107         spin_unlock_irqsave(&arena->lock);
1108         if (to_free_addr)
1109                 arena->ffunc(arena->source, to_free_addr, to_free_sz);
1110 }
1111
1112 void arena_free(struct arena *arena, void *addr, size_t size)
1113 {
1114         size = ROUNDUP(size, arena->quantum);
1115         if (size <= arena->qcache_max)
1116                 return kmem_cache_free(size_to_qcache(arena, size), addr);
1117         free_from_arena(arena, addr, size);
1118 }
1119
1120 void arena_xfree(struct arena *arena, void *addr, size_t size)
1121 {
1122         size = ROUNDUP(size, arena->quantum);
1123         free_from_arena(arena, addr, size);
1124 }
1125
1126 /* Low-level arena builder.  Pass in a page address, and this will build an
1127  * arena in that memory.
1128  *
1129  * This will be used for each NUMA domain's base arena, kpages_arena, and
1130  * kmalloc_arena, since the normal arena_create() won't work yet (no kmalloc).
1131  */
1132 struct arena *arena_builder(void *pgaddr, char *name, size_t quantum,
1133                             void *(*afunc)(struct arena *, size_t, int),
1134                             void (*ffunc)(struct arena *, void *, size_t),
1135                             struct arena *source, size_t qcache_max)
1136 {
1137         struct arena *a = (struct arena*)pgaddr;
1138         struct btag *two_tags = (struct btag*)(pgaddr + sizeof(struct arena));
1139
1140         static_assert(sizeof(struct arena) + 2 * sizeof(struct btag) <= PGSIZE);
1141
1142         arena_init(a, name, quantum, afunc, ffunc, source, qcache_max);
1143         if (!source)
1144                 a->is_base = TRUE;
1145         BSD_LIST_INSERT_HEAD(&a->unused_btags, &two_tags[0], misc_link);
1146         BSD_LIST_INSERT_HEAD(&a->unused_btags, &two_tags[1], misc_link);
1147         return a;
1148 }
1149
1150 /* Sanity checker for an arena's structures.  Hold the lock. */
1151 static void __arena_asserter(struct arena *arena)
1152 {
1153         struct btag *bt_i;
1154         struct rb_node *rb_i;
1155         size_t amt_free = 0, amt_alloc = 0, nr_allocs = 0;
1156
1157         for (int i = 0; i < ARENA_NR_FREE_LISTS; i++) {
1158                 BSD_LIST_FOREACH(bt_i, &arena->free_segs[i], misc_link) {
1159                         assert(bt_i->status == BTAG_FREE);
1160                         assert(bt_i->size >= (1ULL << i));
1161                         assert(bt_i->size < (1ULL << (i + 1)));
1162                 }
1163         }
1164         for (int i = 0; i < arena->hh.nr_hash_lists; i++) {
1165                 BSD_LIST_FOREACH(bt_i, &arena->alloc_hash[i], misc_link)
1166                         assert(bt_i->status == BTAG_ALLOC);
1167         }
1168         for (rb_i = rb_first(&arena->all_segs); rb_i; rb_i = rb_next(rb_i)) {
1169                 bt_i = container_of(rb_i, struct btag, all_link);
1170                 if (bt_i->status == BTAG_FREE)
1171                         amt_free += bt_i->size;
1172                 if (bt_i->status == BTAG_ALLOC) {
1173                         amt_alloc += bt_i->size;
1174                         nr_allocs++;
1175                 }
1176         }
1177         assert(arena->amt_total_segs == amt_free + amt_alloc);
1178         assert(arena->amt_alloc_segs == amt_alloc);
1179         assert(arena->hh.nr_items == nr_allocs);
1180 }
1181
1182 size_t arena_amt_free(struct arena *arena)
1183 {
1184         return arena->amt_total_segs - arena->amt_alloc_segs;
1185 }
1186
1187 size_t arena_amt_total(struct arena *arena)
1188 {
1189         return arena->amt_total_segs;
1190 }
1191
1192 void *base_alloc(struct arena *guess, size_t size, int flags)
1193 {
1194         return arena_alloc(find_my_base(guess), size, flags);
1195 }
1196
1197 void *base_zalloc(struct arena *guess, size_t size, int flags)
1198 {
1199         void *ret = base_alloc(guess, size, flags);
1200
1201         if (!ret)
1202                 return NULL;
1203         memset(ret, 0, size);
1204         return ret;
1205 }
1206
1207 void base_free(struct arena *guess, void *addr, size_t size)
1208 {
1209         return arena_free(find_my_base(guess), addr, size);
1210 }
1211
1212 void print_arena_stats(struct arena *arena, bool verbose)
1213 {
1214         struct btag *bt_i;
1215         struct rb_node *rb_i;
1216
1217         size_t nr_allocs = 0;
1218         size_t nr_imports = 0;
1219         size_t amt_alloc = 0;
1220         size_t amt_free = 0;
1221         size_t amt_imported = 0;
1222         size_t empty_hash_chain = 0;
1223         size_t longest_hash_chain = 0;
1224
1225         printk("Arena: %s (%p)\n--------------\n", arena->name, arena);
1226         printk("\tquantum: %d, qcache_max: %d\n", arena->quantum,
1227                arena->qcache_max);
1228         printk("\tsource: %s\n", arena->source ? arena->source->name : "none");
1229
1230         spin_lock_irqsave(&arena->lock);
1231         for (int i = 0; i < ARENA_NR_FREE_LISTS; i++) {
1232                 int j = 0;
1233
1234                 if (!BSD_LIST_EMPTY(&arena->free_segs[i])) {
1235                         printk("\tList of [2^%d - 2^%d):\n", i, i + 1);
1236                         BSD_LIST_FOREACH(bt_i, &arena->free_segs[i], misc_link) {
1237                                 if (verbose)
1238                                         printk("\t\t%d: start %p, size %p\n", j, bt_i->start,
1239                                                bt_i->size);
1240                                 j++;
1241                         }
1242                         printk("\t\tNr free segs: %d\n", j);
1243                 }
1244         }
1245         for (int i = 0; i < arena->hh.nr_hash_lists; i++) {
1246                 int j = 0;
1247
1248                 if (BSD_LIST_EMPTY(&arena->alloc_hash[i]))
1249                         empty_hash_chain++;
1250                 BSD_LIST_FOREACH(bt_i, &arena->alloc_hash[i], misc_link)
1251                         j++;
1252                 longest_hash_chain = MAX(longest_hash_chain, j);
1253         }
1254         printk("\tSegments:\n\t--------------\n");
1255         for (rb_i = rb_first(&arena->all_segs); rb_i; rb_i = rb_next(rb_i)) {
1256                 bt_i = container_of(rb_i, struct btag, all_link);
1257                 if (bt_i->status == BTAG_SPAN) {
1258                         if (verbose)
1259                                 printk("\tSpan: start %p + %p\n", bt_i->start, bt_i->size);
1260                         nr_imports++;
1261                         amt_imported += bt_i->size;
1262                 }
1263                 if (bt_i->status == BTAG_FREE) {
1264                         if (verbose)
1265                                 printk("\t\tFree: start %p + %p\n", bt_i->start, bt_i->size);
1266                         amt_free += bt_i->size;
1267                 }
1268                 if (bt_i->status == BTAG_ALLOC) {
1269                         if (verbose)
1270                                 printk("\t\tAloc: start %p + %p\n", bt_i->start, bt_i->size);
1271                         nr_allocs++;
1272                         amt_alloc += bt_i->size;
1273                 }
1274         }
1275         printk("\tStats:\n\t-----------------\n");
1276         printk("\t\tAmt free: %llu (%p)\n", amt_free, amt_free);
1277         printk("\t\tAmt alloc: %llu (%p), nr allocs %d\n", amt_alloc, amt_alloc,
1278                nr_allocs);
1279         printk("\t\tAmt total segs: %llu, amt alloc segs %llu\n",
1280                arena->amt_total_segs, arena->amt_alloc_segs);
1281         printk("\t\tAmt imported: %llu (%p), nr imports %d\n", amt_imported,
1282                amt_imported, nr_imports);
1283         printk("\t\tNr hash %d, empty hash: %d, longest hash %d\n",
1284                arena->hh.nr_hash_lists, empty_hash_chain, longest_hash_chain);
1285         __arena_asserter(arena);
1286         spin_unlock_irqsave(&arena->lock);
1287 }