Objcache testing
authorJack Miller <jack@codezen.org>
Thu, 31 Mar 2016 19:59:56 +0000 (14:59 -0500)
committerJack Miller <jack@codezen.org>
Thu, 31 Mar 2016 19:59:56 +0000 (14:59 -0500)
mm/objcache.c

index a56aa05..6aa174f 100644 (file)
@@ -166,6 +166,21 @@ void objcache_free(struct objcache *objcache, void *obj)
     }
 }
 
+void objcache_destroy(struct objcache *objcache)
+{
+    u64 bitmap_longs = OVERHEAD_LONGS(objcache) - 1;
+    u64 *cur = objcache->start_page;
+    u64 *next;
+
+    while(cur) {
+        next = (u64 *) cur[bitmap_longs];
+        page_alloc_free(cur);
+        cur = next;
+    }
+
+    objcache->start_page = NULL;
+}
+
 void objcache_init(struct objcache *objcache, u32 obj_size)
 {
     if (obj_size > MIN_OBJ_SIZE)
@@ -185,8 +200,94 @@ struct test_struct {
 
 DEFINE_OBJCACHE(test_cache, struct test_struct);
 
+/* Return the count of overhead pages allocated */
+
+static int __objcache_pages(struct objcache *objcache)
+{
+    int bitmap_longs = OVERHEAD_LONGS(objcache) - 1;
+    u64 *pages = objcache->start_page;
+    int count = 0;
+
+    while(pages) {
+        pages = (void *) (pages[bitmap_longs]);
+        count++;
+    }
+
+    return count;
+}
+
 void test_objcache(void)
 {
+    /* Pretty much the only test of the objcache is that it can spit out memory
+     * chunks until we run out, and that it will free blocks that are totally
+     * empty on free.
+     */
+
+    struct objcache *a = NULL, *b = NULL;
+    int i;
+
+    if(__objcache_pages(&test_cache) != 0)
+        while(1);
+
+    /* Test struct is 32 bytes, which means 128 objects per page, one
+     * of which is taken up by our bitmap, so we should be able to do 127
+     * gets() all in the same page.
+     */
+
+    for(i = 0; i < 127; i++) {
+        b = a;
+        a = objcache_get(&test_cache);
+
+        if (b) {
+            /* make sure they're same page */
+            if (PAGE_ALIGN((u64) a) != PAGE_ALIGN((u64) b))
+                while(1);
+
+            /* make sure that previous can be freed and re allocated */
+            objcache_free(&test_cache, b);
+            if (objcache_get(&test_cache) != b)
+                while(1);
+        }
+
+        /* make sure a is after b, also NULL check */
+        if ((u64) a <= (u64) b)
+            while(1);
+
+        /* shouldn't have caused expansion */
+        if(__objcache_pages(&test_cache) != 1)
+            while(1);
+    }
+
+    /* The 128th should cause expansion */
+    a = objcache_get(&test_cache);
+
+    if(__objcache_pages(&test_cache) != 2)
+        while(1);
+
+    /* 126 more, shouldn't expand */
+    for(i = 0; i < 126; i++)
+        objcache_get(&test_cache);
+
+    if(__objcache_pages(&test_cache) != 2)
+        while(1);
+
+    a = objcache_get(&test_cache);
+
+    if(__objcache_pages(&test_cache) != 3)
+        while(1);
+
+    /* Now we have 3 pages, with only a single object on the last page */
+
+    /* A free of that single object should cause the cache to contract */
+
+    objcache_free(&test_cache, a);
+    if(__objcache_pages(&test_cache) != 2)
+        while(1);
+
+    /* Test destroy and clean up after our tests */
+    objcache_destroy(&test_cache);
 
+    if(__objcache_pages(&test_cache) != 0)
+        while(1);
 }
 #endif