|  | #include <arena.h> | 
|  | #include <slab.h> | 
|  | #include <ktest.h> | 
|  | #include <dma.h> | 
|  | #include <pmap.h> | 
|  | #include <umem.h> | 
|  |  | 
|  | KTEST_SUITE("ARENA") | 
|  |  | 
|  | static bool test_nextfit(void) | 
|  | { | 
|  | struct arena *a; | 
|  | void *o1, *o2, *o3; | 
|  |  | 
|  | a = arena_create(__func__, (void*)1, 30, 1, NULL, NULL, NULL, 0, | 
|  | MEM_WAIT); | 
|  | o1 = arena_alloc(a, 1, MEM_WAIT | ARENA_NEXTFIT); | 
|  | o2 = arena_alloc(a, 1, MEM_WAIT | ARENA_NEXTFIT); | 
|  | /* If we didn't NEXTFIT, the allocator would likely give us '1' back */ | 
|  | arena_free(a, o1, 1); | 
|  | o3 = arena_alloc(a, 1, MEM_WAIT | ARENA_NEXTFIT); | 
|  | KT_ASSERT(o3 == o2 + 1); | 
|  | arena_free(a, o2, 1); | 
|  | arena_free(a, o3, 1); | 
|  | arena_destroy(a); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static bool test_bestfit(void) | 
|  | { | 
|  | struct arena *a; | 
|  | void *o1; | 
|  |  | 
|  | a = arena_create(__func__, NULL, 0, 1, NULL, NULL, NULL, 0, MEM_WAIT); | 
|  | /* Each span will be an independent chunk in the allocator.  Their base | 
|  | * values don't matter; they just identify the spans. | 
|  | * | 
|  | * BESTFIT for 65 should be 67.  INSTANTFIT should be 128.  The (128-1) | 
|  | * objects around 67 are to make sure we check all objects on the 2^6 | 
|  | * list. */ | 
|  | arena_add(a, (void*)1000, 64, MEM_WAIT); | 
|  | arena_add(a, (void*)3000, 128 - 1, MEM_WAIT); | 
|  | arena_add(a, (void*)2000, 67, MEM_WAIT); | 
|  | arena_add(a, (void*)4000, 128 - 1, MEM_WAIT); | 
|  | arena_add(a, (void*)5000, 128, MEM_WAIT); | 
|  | o1 = arena_alloc(a, 65, MEM_WAIT | ARENA_BESTFIT); | 
|  | KT_ASSERT(o1 == (void*)2000); | 
|  | arena_free(a, o1, 65); | 
|  | arena_destroy(a); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static bool test_instantfit(void) | 
|  | { | 
|  | struct arena *a; | 
|  | void *o1; | 
|  |  | 
|  | a = arena_create(__func__, NULL, 0, 1, NULL, NULL, NULL, 0, MEM_WAIT); | 
|  | arena_add(a, (void*)1000, 64, MEM_WAIT); | 
|  | arena_add(a, (void*)2000, 67, MEM_WAIT); | 
|  | arena_add(a, (void*)3000, 64, MEM_WAIT); | 
|  | arena_add(a, (void*)4000, 128, MEM_WAIT); | 
|  | o1 = arena_alloc(a, 65, MEM_WAIT | ARENA_INSTANTFIT); | 
|  | KT_ASSERT(o1 == (void*)4000); | 
|  | arena_free(a, o1, 65); | 
|  | arena_destroy(a); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static bool test_quantum_align(void) | 
|  | { | 
|  | struct arena *a; | 
|  | void *o1, *o2; | 
|  |  | 
|  | a = arena_create(__func__, NULL, 0, 32, NULL, NULL, NULL, 0, MEM_WAIT); | 
|  | /* this should give us one object only: */ | 
|  | arena_add(a, (void*)(4096 + 1), 64, MEM_WAIT); | 
|  | /* 1 gets rounded up to quantum, so we're really asking for 32 */ | 
|  | o1 = arena_alloc(a, 1, MEM_WAIT); | 
|  | KT_ASSERT(o1 == ROUNDUP((void*)(4096 + 1), a->quantum)); | 
|  | /* Should be nothing quantum-sized left */ | 
|  | o2 = arena_alloc(a, 1, MEM_ATOMIC); | 
|  | KT_ASSERT(o2 == NULL); | 
|  | arena_free(a, o1, 1); | 
|  | arena_destroy(a); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static bool test_odd_quantum(void) | 
|  | { | 
|  | struct arena *a; | 
|  | void *o1, *o2; | 
|  |  | 
|  | a = arena_create(__func__, NULL, 0, 7, NULL, NULL, NULL, 0, MEM_WAIT); | 
|  | arena_add(a, (void*)7, 49, MEM_WAIT); | 
|  | o1 = arena_alloc(a, 7, MEM_WAIT); | 
|  | KT_ASSERT(o1 == (void*)7); | 
|  | o2 = arena_alloc(a, 7, MEM_WAIT); | 
|  | KT_ASSERT(o2 == (void*)14); | 
|  | arena_free(a, o1, 7); | 
|  | arena_free(a, o2, 7); | 
|  |  | 
|  | /* In older arena code, this would fragment such that it could hand out | 
|  | * non-quantum-aligned objects. */ | 
|  | o1 = arena_xalloc(a, 7, 4, 0, 0, NULL, NULL, MEM_WAIT); | 
|  | o2 = arena_alloc(a, 7, MEM_WAIT); | 
|  | KT_ASSERT(!((uintptr_t)o2 % 7)); | 
|  | arena_xfree(a, o1, 7); | 
|  | arena_free(a, o2, 7); | 
|  | arena_destroy(a); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* The nocross-fallback hops over the first nocross boundary in a segment try, | 
|  | * in the hopes that the rest of the segment can satisfy the constraints. */ | 
|  | static bool test_nocross_fallback(void) | 
|  | { | 
|  | struct arena *a; | 
|  | void *o1; | 
|  |  | 
|  | a = arena_create(__func__, NULL, 0, 3, NULL, NULL, NULL, 0, MEM_WAIT); | 
|  | arena_add(a, (void*)3, 20, MEM_WAIT); | 
|  | o1 = arena_xalloc(a, 3, 1, 0, 4, NULL, NULL, MEM_WAIT); | 
|  | /* 6 would be wrong.  We hopped over 4, but then didn't check that | 
|  | * segment either (crosses 8). */ | 
|  | KT_ASSERT(o1 == (void*)9); | 
|  | arena_xfree(a, o1, 3); | 
|  | arena_destroy(a); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static bool test_xalloc_from_freelist(void) | 
|  | { | 
|  | struct arena *a; | 
|  | void *o1; | 
|  |  | 
|  | a = arena_create(__func__, NULL, 0, 1, NULL, NULL, NULL, 0, MEM_WAIT); | 
|  | /* one object on the order 3 list: size [8, 15].  it also starts at 15, | 
|  | * which will satisfy align=8 phase=7. */ | 
|  | arena_add(a, (void*)15, 15, MEM_WAIT); | 
|  | /* adding phase + ALIGN(align) would have us look on the order 4 list, | 
|  | * which is what older code did. */ | 
|  | o1 = arena_xalloc(a, 15, 8, 7, 0, NULL, NULL, | 
|  | MEM_ATOMIC | ARENA_BESTFIT); | 
|  | KT_ASSERT(o1 == (void*)15); | 
|  | arena_xfree(a, o1, 15); | 
|  | arena_destroy(a); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Right now, instantfit failures do *not* fall back to bestfit.  If we ever do | 
|  | * that, we can turn on this test.  {,x}alloc with a source will fallback to | 
|  | * bestfit *after* it went to the source. */ | 
|  | static bool test_alloc_instantfit_fallback(void) | 
|  | { | 
|  | struct arena *a; | 
|  | void *o1; | 
|  |  | 
|  | a = arena_create(__func__, NULL, 0, 1, NULL, NULL, NULL, 0, MEM_WAIT); | 
|  | /* one object on the order 3 list: size [8, 15], at 1. */ | 
|  | arena_add(a, (void*)1, 15, MEM_WAIT); | 
|  | o1 = arena_alloc(a, 15, MEM_ATOMIC); | 
|  | KT_ASSERT(o1 == (void*)1); | 
|  | arena_free(a, o1, 15); | 
|  | o1 = arena_xalloc(a, 15, 1, 0, 0, NULL, NULL, MEM_ATOMIC); | 
|  | KT_ASSERT(o1 == (void*)1); | 
|  | arena_xfree(a, o1, 15); | 
|  | arena_destroy(a); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static bool test_qcache(void) | 
|  | { | 
|  | struct arena *a; | 
|  | void *o1, *o2, *o3, *o4; | 
|  |  | 
|  | /* 3 qcaches */ | 
|  | a = arena_create(__func__, NULL, 0, 1, NULL, NULL, NULL, 3, MEM_WAIT); | 
|  | arena_add(a, (void*)1, 10000, MEM_WAIT); | 
|  | /* Alloc from each qc, plus the arena. */ | 
|  | o1 = arena_alloc(a, 1, MEM_WAIT); | 
|  | o2 = arena_alloc(a, 2, MEM_WAIT); | 
|  | o3 = arena_alloc(a, 3, MEM_WAIT); | 
|  | o4 = arena_alloc(a, 4, MEM_WAIT); | 
|  |  | 
|  | arena_free(a, o1, 1); | 
|  | arena_free(a, o2, 2); | 
|  | arena_free(a, o3, 3); | 
|  | arena_free(a, o4, 4); | 
|  | arena_destroy(a); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static bool test_qc_odd_quantum(void) | 
|  | { | 
|  | struct arena *a; | 
|  | void *o[4]; | 
|  |  | 
|  | /* 3 qcaches, non-power-of-two quantum.  This checks the slab guarantee | 
|  | * that if slab objects (qcaches) are a multiple of source->quantum, | 
|  | * then all allocations are multiples of quantum. */ | 
|  | a = arena_create(__func__, NULL, 0, 7, NULL, NULL, NULL, 21, MEM_WAIT); | 
|  | arena_add(a, (void*)7, 10000, MEM_WAIT); | 
|  | /* Alloc from each qc, plus the arena, ensure quantum alignment. */ | 
|  | for (int i = 1; i < 4; i++) { | 
|  | size_t amt = 7 * i; | 
|  |  | 
|  | /* Get a few before checking them all */ | 
|  | for (int j = 0; j < ARRAY_SIZE(o); j++) | 
|  | o[j] = arena_alloc(a, amt, MEM_WAIT); | 
|  | for (int j = 0; j < ARRAY_SIZE(o); j++) | 
|  | KT_ASSERT(!((uintptr_t)o[j] % 7)); | 
|  | for (int j = 0; j < ARRAY_SIZE(o); j++) | 
|  | arena_free(a, o[j], amt); | 
|  | } | 
|  | arena_destroy(a); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* slab code had an issue with align > PGSIZE.  QCs are quantum aligned, so | 
|  | * quantum > PGSIZE with a QC caused trouble. */ | 
|  | static bool test_qc_large_quantum(void) | 
|  | { | 
|  | struct arena *a; | 
|  | void *o1; | 
|  |  | 
|  | a = arena_create(__func__, NULL, 0, 8192, NULL, NULL, NULL, 8192, | 
|  | MEM_WAIT); | 
|  | arena_add(a, (void*)8192, 8192 * 4, MEM_WAIT); | 
|  | o1 = arena_alloc(a, 8192, MEM_WAIT); | 
|  | arena_free(a, o1, 8192); | 
|  | arena_destroy(a); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Just examples of stuff you can do. */ | 
|  | static void *tiaf(struct arena *a, size_t amt, int flags) | 
|  | { | 
|  | void *obj = arena_alloc(a, amt, flags); | 
|  |  | 
|  | return (void*)((uintptr_t)obj << 15); | 
|  | } | 
|  |  | 
|  | static void tiff(struct arena *a, void *obj, size_t amt) | 
|  | { | 
|  | arena_free(a, (void*)((uintptr_t)obj >> 15), amt); | 
|  | } | 
|  |  | 
|  | static bool test_import(void) | 
|  | { | 
|  | struct arena *a, *s; | 
|  | void *o1, *o2; | 
|  |  | 
|  | s = arena_create("test_import-source", NULL, 0, 4096, NULL, NULL, NULL, | 
|  | 0, MEM_WAIT); | 
|  | arena_add(s, (void*)4096, 4096 * 4, MEM_WAIT); | 
|  | a = arena_create("test_import-actual", NULL, 0, 1, tiaf, tiff, s, 2, | 
|  | MEM_WAIT); | 
|  |  | 
|  | o1 = arena_alloc(a, 1, MEM_WAIT); | 
|  | o2 = arena_alloc(a, 2, MEM_WAIT); | 
|  | /* Make sure our handlers run.  The source gives 'a' addresses around | 
|  | * 4096, which the import funcs translate to above 1 << 15. */ | 
|  | KT_ASSERT((uintptr_t)o1 >= (1 << 15)); | 
|  | KT_ASSERT((uintptr_t)o2 >= (1 << 15)); | 
|  |  | 
|  | arena_free(a, o1, 1); | 
|  | arena_free(a, o2, 2); | 
|  | arena_destroy(a); | 
|  | arena_destroy(s); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static bool test_import_slab(void) | 
|  | { | 
|  | struct arena *s; | 
|  | struct kmem_cache *kc; | 
|  | void *o[3]; | 
|  |  | 
|  | s = arena_create(__func__, NULL, 0, 7, NULL, NULL, NULL, | 
|  | 0, MEM_WAIT); | 
|  | /* We need to have a sizable amount here, since the KCs will pull a lot | 
|  | * of resources when growing.  7000 isn't enough. */ | 
|  | arena_add(s, (void*)7, 70000, MEM_WAIT); | 
|  |  | 
|  | /* Quantum-preserving guarantee */ | 
|  | kc = kmem_cache_create("test_import_slab-QP", 14, 1, KMC_NOTOUCH, s, | 
|  | NULL, NULL, NULL); | 
|  | for (int i = 0; i < ARRAY_SIZE(o); i++) | 
|  | o[i] = kmem_cache_alloc(kc, MEM_WAIT); | 
|  | for (int i = 0; i < ARRAY_SIZE(o); i++) | 
|  | KT_ASSERT(!((uintptr_t)o[i] % 7)); | 
|  | for (int i = 0; i < ARRAY_SIZE(o); i++) | 
|  | kmem_cache_free(kc, o[i]); | 
|  | kmem_cache_destroy(kc); | 
|  |  | 
|  |  | 
|  | /* Listen to slab's alignment guarantee */ | 
|  | kc = kmem_cache_create("test_import_slab-AG", 1, 16, KMC_NOTOUCH, NULL, | 
|  | NULL, NULL, NULL); | 
|  | for (int i = 0; i < ARRAY_SIZE(o); i++) | 
|  | o[i] = kmem_cache_alloc(kc, MEM_WAIT); | 
|  | for (int i = 0; i < ARRAY_SIZE(o); i++) | 
|  | KT_ASSERT(ALIGNED(o[i], 16)); | 
|  | for (int i = 0; i < ARRAY_SIZE(o); i++) | 
|  | kmem_cache_free(kc, o[i]); | 
|  | kmem_cache_destroy(kc); | 
|  |  | 
|  |  | 
|  | arena_destroy(s); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Arena import code wasn't grabbing enough, such that when we aligned the | 
|  | * source object to a's np2sb (which happened to be a power of 2), we had | 
|  | * nothing left to actually put in the arena. | 
|  | * | 
|  | * Additionally, arena's weren't freeing the segment back to their sources. */ | 
|  | static bool test_import_alignment(void) | 
|  | { | 
|  | struct arena *s, *a; | 
|  | void *o1; | 
|  |  | 
|  | s = arena_create("test_import_alignment-s", NULL, 0, 1, | 
|  | NULL, NULL, NULL, 0, MEM_WAIT); | 
|  | arena_add(s, (void*)1, 1000, MEM_WAIT); | 
|  | a = arena_create("test_import_alignment-a", NULL, 0, 16, | 
|  | arena_alloc, arena_free, s, | 
|  | 0, MEM_WAIT); | 
|  | o1 = arena_alloc(a, 16, MEM_WAIT); | 
|  | KT_ASSERT(o1); | 
|  | arena_free(a, o1, 16); | 
|  | arena_destroy(a); | 
|  | arena_destroy(s); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static bool test_xalloc(void) | 
|  | { | 
|  | struct arena *a; | 
|  | void *o1, *o2, *o3, *o4; | 
|  |  | 
|  | a = arena_create(__func__, NULL, 0, 3, NULL, NULL, NULL, 0, MEM_WAIT); | 
|  | arena_add(a, (void*)3, 4096, MEM_WAIT); | 
|  |  | 
|  | /* align 16, phase 6 */ | 
|  | o1 = arena_xalloc(a, 3, 16, 6, 0, NULL, NULL, MEM_WAIT); | 
|  | KT_ASSERT(ALIGNED((uintptr_t)o1 - 6, 16)); | 
|  | KT_ASSERT(!((uintptr_t)o1 % 3)); | 
|  |  | 
|  | /* nocross 16 */ | 
|  | o2 = arena_xalloc(a, 15, 1, 0, 16, NULL, NULL, MEM_WAIT); | 
|  | KT_ASSERT(!((uintptr_t)o2 % 3)); | 
|  | KT_ASSERT(ROUNDUP(o2 + 1, 16) >= o2 + 15); | 
|  |  | 
|  | /* min 81, max 252.  should be available. */ | 
|  | o3 = arena_xalloc(a, 3, 1, 0, 0, (void*)81, (void*)252, MEM_WAIT); | 
|  | KT_ASSERT(!((uintptr_t)o3 % 3)); | 
|  | KT_ASSERT(81 <= (uintptr_t)o3 && (uintptr_t)o3 < 252); | 
|  |  | 
|  | /* older xalloc code could hand out non-free segments! */ | 
|  | o4 = arena_xalloc(a, 3, 1, 0, 0, (void*)81, (void*)252, MEM_WAIT); | 
|  | KT_ASSERT(!((uintptr_t)o4 % 3)); | 
|  | KT_ASSERT(81 <= (uintptr_t)o4 && (uintptr_t)o4 < 252); | 
|  | KT_ASSERT(o4 != o3); | 
|  |  | 
|  | arena_xfree(a, o1, 3); | 
|  | arena_xfree(a, o2, 15); | 
|  | arena_xfree(a, o3, 3); | 
|  | arena_xfree(a, o4, 3); | 
|  | arena_destroy(a); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static bool test_xalloc_minmax(void) | 
|  | { | 
|  | struct arena *a; | 
|  | void *o1, *o2; | 
|  |  | 
|  | a = arena_create(__func__, NULL, 0, 1, NULL, NULL, NULL, 0, MEM_WAIT); | 
|  | arena_add(a, (void*)1, 100, MEM_WAIT); | 
|  | o1 = arena_xalloc(a, 20, 1, 0, 0, (void*)10, (void*)30, MEM_ATOMIC); | 
|  | KT_ASSERT((uintptr_t)o1 == 10); | 
|  | o2 = arena_xalloc(a, 20, 1, 0, 0, (void*)30, (void*)50, MEM_ATOMIC); | 
|  | KT_ASSERT((uintptr_t)o2 == 30); | 
|  | arena_xfree(a, o1, 20); | 
|  | arena_xfree(a, o2, 20); | 
|  | arena_destroy(a); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /* Note we don't use qcaches - they throw off the measurements, since all qcache | 
|  | * objects (free or not) are counted as allocated from the arena's perspective. | 
|  | */ | 
|  | static bool test_accounting(void) | 
|  | { | 
|  | struct arena *a; | 
|  | void *o1, *o2; | 
|  |  | 
|  | a = arena_create(__func__, NULL, 0, 1, NULL, NULL, NULL, 0, MEM_WAIT); | 
|  | arena_add(a, (void*)1, 100, MEM_WAIT); | 
|  | KT_ASSERT(arena_amt_free(a) == 100); | 
|  | KT_ASSERT(arena_amt_total(a) == 100); | 
|  |  | 
|  | /* Ensuring some fragmentation */ | 
|  | o1 = arena_xalloc(a, 15, 1, 0, 0, (void*)10, (void*)40, MEM_WAIT); | 
|  | o2 = arena_xalloc(a, 15, 1, 0, 0, (void*)50, (void*)90, MEM_WAIT); | 
|  |  | 
|  | KT_ASSERT(arena_amt_free(a) == 70); | 
|  | KT_ASSERT(arena_amt_total(a) == 100); | 
|  |  | 
|  | arena_free(a, o1, 15); | 
|  | arena_free(a, o2, 15); | 
|  | arena_destroy(a); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static void *tssaf(struct arena *a, size_t amt, int flags) | 
|  | { | 
|  | static uintptr_t store = PGSIZE; | 
|  | void *ret; | 
|  |  | 
|  | ret = (void*)store; | 
|  | store += ROUNDUP(amt, a->quantum); | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | static void tssff(struct arena *a, void *obj, size_t amt) | 
|  | { | 
|  | } | 
|  |  | 
|  | static bool test_self_source(void) | 
|  | { | 
|  | struct arena *s, *a; | 
|  | void *o1, *o2; | 
|  |  | 
|  | s = arena_create(__func__, NULL, 0, PGSIZE, tssaf, tssff, | 
|  | ARENA_SELF_SOURCE, 0, MEM_WAIT); | 
|  | o1 = arena_alloc(s, 1, MEM_WAIT); | 
|  | o2 = arena_alloc(s, 1, MEM_WAIT); | 
|  | KT_ASSERT(o1 != o2); | 
|  | arena_free(s, o1, 1); | 
|  | arena_free(s, o2, 1); | 
|  |  | 
|  | a = arena_create("test_self_source-import", NULL, 0, 1, | 
|  | arena_alloc, arena_free, s, 0, MEM_WAIT); | 
|  | o1 = arena_alloc(a, 1, MEM_WAIT); | 
|  | o2 = arena_alloc(a, 1, MEM_WAIT); | 
|  | KT_ASSERT(o1 != o2); | 
|  | arena_free(a, o1, 1); | 
|  | arena_free(a, o2, 1); | 
|  |  | 
|  | arena_destroy(a); | 
|  | arena_destroy(s); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static bool test_dma_pool(void) | 
|  | { | 
|  | struct dma_pool *dp; | 
|  | #define NR_LOOPS 10 | 
|  | void *va[NR_LOOPS]; | 
|  | dma_addr_t da[NR_LOOPS]; | 
|  |  | 
|  | dp = dma_pool_create(__func__, NULL, 33, 16, 64); | 
|  | for (int i = 0; i < NR_LOOPS; i++) { | 
|  | va[i] = dma_pool_alloc(dp, MEM_WAIT, &da[i]); | 
|  | KT_ASSERT(ALIGNED(va[i], 16)); | 
|  | KT_ASSERT(ROUNDUP(va[i] + 1, 64) >= va[i] + 33); | 
|  | KT_ASSERT(PADDR(va[i]) == da[i]); | 
|  | } | 
|  | for (int i = 0; i < NR_LOOPS; i++) | 
|  | dma_pool_free(dp, va[i], da[i]); | 
|  | dma_pool_destroy(dp); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static bool test_user_dma(void) | 
|  | { | 
|  | struct dma_arena *da; | 
|  | void *o1, *o2; | 
|  | dma_addr_t d1, d2; | 
|  |  | 
|  | setup_dma_arena(current); | 
|  | da = current->user_pages; | 
|  | o1 = dma_arena_alloc(da, PGSIZE * 4, &d1, MEM_WAIT); | 
|  | o2 = dma_arena_alloc(da, PGSIZE, &d2, MEM_WAIT); | 
|  |  | 
|  | KT_ASSERT(is_user_rwaddr((void*)d1, PGSIZE * 4)); | 
|  | KT_ASSERT(is_user_rwaddr((void*)d2, PGSIZE)); | 
|  | KT_ASSERT(o1 == (void*)d1); | 
|  | KT_ASSERT(o2 == (void*)d2); | 
|  |  | 
|  | dma_arena_free(da, o1, d1, PGSIZE * 4); | 
|  | dma_arena_free(da, o2, d2, PGSIZE); | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static struct ktest ktests[] = { | 
|  | KTEST_REG(nextfit,		CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(bestfit,		CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(instantfit,		CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(quantum_align,	CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(odd_quantum,		CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(nocross_fallback,	CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(xalloc_from_freelist,	CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(qcache,		CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(qc_odd_quantum,	CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(qc_large_quantum,	CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(import,		CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(import_slab,		CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(import_alignment,	CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(xalloc,		CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(xalloc_minmax,	CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(accounting,		CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(self_source,		CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(dma_pool,		CONFIG_KTEST_ARENA), | 
|  | KTEST_REG(user_dma,		CONFIG_KTEST_ARENA), | 
|  | }; | 
|  |  | 
|  | static int num_ktests = sizeof(ktests) / sizeof(struct ktest); | 
|  |  | 
|  | static void __init register_arena_ktests(void) | 
|  | { | 
|  | REGISTER_KTESTS(ktests, num_ktests); | 
|  | } | 
|  | init_func_1(register_arena_ktests); |