pool.c (2242B)
1 #include <kernel.h> 2 #include <mmu.h> 3 #include <alloc.h> 4 #include <spinlock.h> 5 #include <pool.h> 6 7 enum item_state { 8 ITEM_UNUSED, 9 ITEM_USED, 10 }; 11 12 struct item { 13 item_id id; 14 void *mem; 15 size_t siz; 16 enum item_state state; 17 }; 18 19 struct pool { 20 struct item *item; 21 size_t siz; 22 spinlock_t lock; 23 }; 24 25 static int ndebug = 0; 26 27 struct pool * 28 init_pool(void) 29 { 30 struct pool *pool; 31 32 pool = kmalloc(sizeof(struct pool)); 33 if (!pool) 34 return NULL; 35 pool->item = NULL; 36 pool->siz = 0; 37 spinlock_init(&pool->lock); 38 return pool; 39 } 40 41 void 42 free_pool(struct pool *pool) 43 { 44 struct item *item; 45 size_t i; 46 47 for (i = 0; i < pool->siz; i++) { 48 item = &pool->item[i]; 49 kfree(item->mem); 50 } 51 kfree(pool->item); 52 kfree(pool); 53 } 54 55 /* Allocate an item in the pool of size `n' with `id'. 56 * If there is an unused item of sufficient size with the same 57 * `id' then it will be re-used. */ 58 void * 59 alloc_item(struct pool *pool, size_t n, item_id id) 60 { 61 struct item *tmp; 62 struct item *item; 63 size_t i; 64 65 spinlock_lock(&pool->lock); 66 for (i = 0; i < pool->siz; i++) { 67 item = &pool->item[i]; 68 if (item->id == id) { 69 if (ndebug > 0) 70 kprintf("Found possible unused item: %d\n", item->id); 71 if (item->state == ITEM_UNUSED && item->siz >= n) { 72 if (ndebug > 0) 73 kprintf("Found unused item: %d of size %zu bytes\n", 74 item->id, item->siz); 75 item->state = ITEM_USED; 76 spinlock_unlock(&pool->lock); 77 return item->mem; 78 } 79 } 80 } 81 82 if (ndebug > 0) 83 kprintf("Allocating new item: %d of size %zu bytes\n", 84 id, n); 85 86 tmp = krealloc(pool->item, sizeof(struct item) * (pool->siz + 1)); 87 if (!tmp) 88 panic("out of memory"); 89 pool->item = tmp; 90 item = &pool->item[pool->siz]; 91 item->id = id; 92 item->mem = kmalloc(n); 93 if (!item->mem) 94 panic("out of memory"); 95 item->siz = n; 96 item->state = ITEM_USED; 97 pool->siz++; 98 spinlock_unlock(&pool->lock); 99 return item->mem; 100 } 101 102 /* Free all items with `id'. This does not actually 103 * free the underlying memory, it just marks those items 104 * as unused. */ 105 void 106 free_items(struct pool *pool, item_id id) 107 { 108 struct item *item; 109 size_t i; 110 111 spinlock_lock(&pool->lock); 112 for (i = 0; i < pool->siz; i++) { 113 item = &pool->item[i]; 114 if (item->id == id) 115 item->state = ITEM_UNUSED; 116 } 117 spinlock_unlock(&pool->lock); 118 }