00001
00038 #include <assert.h>
00039 #include <debug.h>
00040 #include <interrupt.h>
00041 #include <mempool.h>
00042 #include <physmem.h>
00043 #include <util.h>
00044 #include <stdint.h>
00045
00051 struct mem_pool_object {
00052 struct mem_pool_object *next;
00053 };
00054
00075 void mem_pool_init(struct mem_pool *pool, void *start, size_t size,
00076 size_t objsize, unsigned int align_order)
00077 {
00078 struct mem_pool_object *obj;
00079 struct mem_pool_object *prev_obj;
00080 uintptr_t aligned_start;
00081 unsigned int offset;
00082
00083 assert(pool);
00084 assert(start);
00085 assert((uintptr_t)start + size > (uintptr_t)start);
00086
00087 aligned_start = round_up((uintptr_t)start, align_order);
00088 size -= (aligned_start - (uintptr_t)start);
00089 objsize = round_up(objsize, align_order);
00090
00091 assert(objsize >= sizeof(struct mem_pool_object));
00092 assert(size >= objsize);
00093
00094 obj = prev_obj = (void *)aligned_start;
00095 pool->freelist = obj;
00096
00097 for (offset = objsize; (offset + objsize) <= size; offset += objsize) {
00098 obj = (void *)(aligned_start + offset);
00099 prev_obj->next = obj;
00100 prev_obj = obj;
00101 }
00102 obj->next = NULL;
00103
00104 dbg_info("mempool @ %p initialized with %zu objects of size %zu\n",
00105 start, size / objsize, objsize);
00106 }
00107
00126 void mem_pool_init_physmem(struct mem_pool *mempool,
00127 struct physmem_pool *phys_pool, unsigned int nr_objects,
00128 size_t objsize, unsigned int align_order)
00129 {
00130 phys_addr_t pool_addr;
00131 size_t pool_size;
00132 size_t block_size;
00133 void *pool_vaddr;
00134
00135 assert(mempool);
00136 assert(phys_pool);
00137 assert(nr_objects > 0);
00138
00139 block_size = round_up(objsize, align_order);
00140 pool_size = nr_objects * block_size;
00141
00142 pool_addr = physmem_alloc(phys_pool, pool_size, align_order);
00143 assert(pool_addr != PHYSMEM_ALLOC_ERR);
00144
00145 pool_vaddr = physmem_map(pool_addr, pool_size,
00146 PHYS_MAP_WRBUF | PHYS_MAP_WRBACK);
00147 mem_pool_init(mempool, pool_vaddr, pool_size, objsize, align_order);
00148 }
00149
00157 void *mem_pool_alloc(struct mem_pool *pool)
00158 {
00159 struct mem_pool_object *obj;
00160 unsigned long iflags;
00161
00162 assert(pool);
00163
00164 iflags = cpu_irq_save();
00165 obj = pool->freelist;
00166 if (obj)
00167 pool->freelist = obj->next;
00168 cpu_irq_restore(iflags);
00169
00170 return obj;
00171 }
00172
00190 void mem_pool_free(struct mem_pool *pool, const void *obj)
00191 {
00192 struct mem_pool_object *free_obj;
00193 unsigned long iflags;
00194
00195 assert(pool);
00196
00197 if (!obj)
00198 return;
00199
00200 free_obj = (struct mem_pool_object *)obj;
00201
00202 iflags = cpu_irq_save();
00203 free_obj->next = pool->freelist;
00204 pool->freelist = free_obj;
00205 cpu_irq_restore(iflags);
00206 }
00207