net: tcp: Fix up the receive window
[akaros.git] / kern / src / arena.c
index 04f3185..26a5991 100644 (file)
  *   help us get out of OOM.  So we might block when we're at low-mem, not at 0.
  *   We probably should have a sorted list of desired amounts, and unblockers
  *   poke the CV if the first waiter is likely to succeed.
- * - qcaching
- * - We'll need some linkage between sources and parent arenas, with callbacks
- *   or something when the base arena starts to run low on memory.  Once an
- *   arena (whether base or o/w) gets the "time to free up memory" call, it can
- *   call into any of its children, to include slabs and whatever else.
+ * - Reclaim: have a ktask that sleeps on a rendez.  We poke it, even from IRQ
+ *   context.  It qlocks arenas_and_slabs_lock, then does the reclaim.
  *
  * FAQ:
  * - Does allocating memory from an arena require it to take a btag?  Yes -
@@ -82,8 +79,7 @@
 #include <slab.h>
 #include <kthread.h>
 
-static struct arena_tailq all_arenas = TAILQ_HEAD_INITIALIZER(all_arenas);
-static spinlock_t all_arenas_lock = SPINLOCK_INITIALIZER;
+struct arena_tailq all_arenas = TAILQ_HEAD_INITIALIZER(all_arenas);
 qlock_t arenas_and_slabs_lock = QLOCK_INITIALIZER(arenas_and_slabs_lock);
 
 struct arena *base_arena;
@@ -129,7 +125,7 @@ static void setup_qcaches(struct arena *arena, size_t quantum,
                qc_size = (i + 1) * quantum;
                snprintf(kc_name, KMC_NAME_SZ, "%s_%d", arena->name, qc_size);
                __kmem_cache_create(&arena->qcaches[i], kc_name, qc_size, quantum,
-                                   KMC_NOTOUCH | KMC_QCACHE, arena, NULL, NULL);
+                                   KMC_NOTOUCH | KMC_QCACHE, arena, NULL, NULL, NULL);
        }
 }
 
@@ -176,9 +172,9 @@ static void arena_init(struct arena *arena, char *name, size_t quantum,
 
        if (source)
                add_importing_arena(source, arena);
-       spin_lock(&all_arenas_lock);
+       qlock(&arenas_and_slabs_lock);
        TAILQ_INSERT_TAIL(&all_arenas, arena, next);
-       spin_unlock(&all_arenas_lock);
+       qunlock(&arenas_and_slabs_lock);
 }
 
 struct arena *arena_create(char *name, void *base, size_t size, size_t quantum,
@@ -209,9 +205,9 @@ void arena_destroy(struct arena *arena)
 {
        struct btag *bt_i, *temp;
 
-       spin_lock(&all_arenas_lock);
+       qlock(&arenas_and_slabs_lock);
        TAILQ_REMOVE(&all_arenas, arena, next);
-       spin_unlock(&all_arenas_lock);
+       qunlock(&arenas_and_slabs_lock);
        if (arena->source)
                del_importing_arena(arena->source, arena);
 
@@ -1244,91 +1240,3 @@ void base_free(struct arena *guess, void *addr, size_t size)
 {
        return arena_free(find_my_base(guess), addr, size);
 }
-
-void print_arena_stats(struct arena *arena, bool verbose)
-{
-       struct btag *bt_i;
-       struct rb_node *rb_i;
-       struct arena *a_i;
-       struct kmem_cache *s_i;
-
-       size_t nr_allocs = 0;
-       size_t nr_imports = 0;
-       size_t amt_alloc = 0;
-       size_t amt_free = 0;
-       size_t amt_imported = 0;
-       size_t empty_hash_chain = 0;
-       size_t longest_hash_chain = 0;
-
-       printk("Arena: %s (%p)\n--------------\n", arena->name, arena);
-       printk("\tquantum: %d, qcache_max: %d\n", arena->quantum,
-              arena->qcache_max);
-       printk("\tsource: %s\n", arena->source ? arena->source->name : "none");
-
-       spin_lock_irqsave(&arena->lock);
-       for (int i = 0; i < ARENA_NR_FREE_LISTS; i++) {
-               int j = 0;
-
-               if (!BSD_LIST_EMPTY(&arena->free_segs[i])) {
-                       printk("\tList of [2^%d - 2^%d):\n", i, i + 1);
-                       BSD_LIST_FOREACH(bt_i, &arena->free_segs[i], misc_link) {
-                               if (verbose)
-                                       printk("\t\t%d: start %p, size %p\n", j, bt_i->start,
-                                              bt_i->size);
-                               j++;
-                       }
-                       printk("\t\tNr free segs: %d\n", j);
-               }
-       }
-       for (int i = 0; i < arena->hh.nr_hash_lists; i++) {
-               int j = 0;
-
-               if (BSD_LIST_EMPTY(&arena->alloc_hash[i]))
-                       empty_hash_chain++;
-               BSD_LIST_FOREACH(bt_i, &arena->alloc_hash[i], misc_link)
-                       j++;
-               longest_hash_chain = MAX(longest_hash_chain, j);
-       }
-       printk("\tSegments:\n\t--------------\n");
-       for (rb_i = rb_first(&arena->all_segs); rb_i; rb_i = rb_next(rb_i)) {
-               bt_i = container_of(rb_i, struct btag, all_link);
-               if (bt_i->status == BTAG_SPAN) {
-                       if (verbose)
-                               printk("\tSpan: start %p + %p\n", bt_i->start, bt_i->size);
-                       nr_imports++;
-                       amt_imported += bt_i->size;
-               }
-               if (bt_i->status == BTAG_FREE) {
-                       if (verbose)
-                               printk("\t\tFree: start %p + %p\n", bt_i->start, bt_i->size);
-                       amt_free += bt_i->size;
-               }
-               if (bt_i->status == BTAG_ALLOC) {
-                       if (verbose)
-                               printk("\t\tAloc: start %p + %p\n", bt_i->start, bt_i->size);
-                       nr_allocs++;
-                       amt_alloc += bt_i->size;
-               }
-       }
-       printk("\tStats:\n\t-----------------\n");
-       printk("\t\tAmt free: %llu (%p)\n", amt_free, amt_free);
-       printk("\t\tAmt alloc: %llu (%p), nr allocs %d\n", amt_alloc, amt_alloc,
-              nr_allocs);
-       printk("\t\tAmt total segs: %llu, amt alloc segs %llu\n",
-              arena->amt_total_segs, arena->amt_alloc_segs);
-       printk("\t\tAmt imported: %llu (%p), nr imports %d\n", amt_imported,
-              amt_imported, nr_imports);
-       printk("\t\tNr hash %d, empty hash: %d, longest hash %d\n",
-              arena->hh.nr_hash_lists, empty_hash_chain, longest_hash_chain);
-       __arena_asserter(arena);
-       spin_unlock_irqsave(&arena->lock);
-
-       qlock(&arenas_and_slabs_lock);
-       printk("\tImporting Arenas:\n\t-----------------\n");
-       TAILQ_FOREACH(a_i, &arena->__importing_arenas, import_link)
-               printk("\t\t%s\n", a_i->name);
-       printk("\tImporting Slabs:\n\t-----------------\n");
-       TAILQ_FOREACH(s_i, &arena->__importing_slabs, import_link)
-               printk("\t\t%s\n", s_i->name);
-       qunlock(&arenas_and_slabs_lock);
-}