00001
00057 #include <assert.h>
00058 #include <debug.h>
00059 #include <interrupt.h>
00060 #include <mempool.h>
00061 #include <physmem.h>
00062 #include <util.h>
00063
00064 struct mem_pool_object {
00065 struct mem_pool_object *next;
00066 };
00067
00088 void mem_pool_init(struct mem_pool *pool, void *start, size_t size,
00089 size_t objsize, unsigned int align_order)
00090 {
00091 struct mem_pool_object *obj;
00092 struct mem_pool_object *prev_obj;
00093 void *aligned_start;
00094 unsigned int offset;
00095
00096 assert(pool);
00097 assert(start);
00098 assert((unsigned long)start + size > (unsigned long)start);
00099
00100 aligned_start = (void *)round_up((unsigned long)start, align_order);
00101 size -= ((unsigned long)aligned_start - (unsigned long)start);
00102 objsize = round_up(objsize, align_order);
00103
00104 assert(objsize >= sizeof(struct mem_pool_object));
00105 assert(size >= objsize);
00106
00107 prev_obj = aligned_start;
00108 pool->freelist = prev_obj;
00109
00110 for (offset = objsize; (offset + objsize) <= size; offset += objsize) {
00111 obj = aligned_start + offset;
00112 prev_obj->next = obj;
00113 prev_obj = obj;
00114 }
00115 obj->next = NULL;
00116
00117 dbg_printf("mempool @ %p initialized with %lu objects of size %lu\n",
00118 start, size / objsize, objsize);
00119 }
00120
00139 void mem_pool_init_physmem(struct mem_pool *mempool,
00140 struct physmem_pool *phys_pool, unsigned int nr_objects,
00141 size_t objsize, unsigned int align_order)
00142 {
00143 phys_addr_t pool_addr;
00144 size_t pool_size;
00145 size_t block_size;
00146 void *pool_vaddr;
00147
00148 assert(mempool);
00149 assert(phys_pool);
00150 assert(nr_objects > 0);
00151
00152 block_size = round_up(objsize, align_order);
00153 pool_size = nr_objects * block_size;
00154
00155 pool_addr = physmem_alloc(phys_pool, pool_size, align_order);
00156 assert(pool_addr != PHYSMEM_ALLOC_ERR);
00157
00158 pool_vaddr = physmem_map(pool_addr, pool_size,
00159 PHYS_MAP_WRBUF | PHYS_MAP_WRBACK);
00160 mem_pool_init(mempool, pool_vaddr, pool_size, objsize, align_order);
00161 }
00162
00170 void *mem_pool_alloc(struct mem_pool *pool)
00171 {
00172 struct mem_pool_object *obj;
00173 unsigned long iflags;
00174
00175 assert(pool);
00176
00177 iflags = cpu_irq_save();
00178 obj = pool->freelist;
00179 if (obj)
00180 pool->freelist = obj->next;
00181 cpu_irq_restore(iflags);
00182
00183 return obj;
00184 }
00185
00202 void mem_pool_free(struct mem_pool *pool, const void *obj)
00203 {
00204 struct mem_pool_object *free_obj;
00205 unsigned long iflags;
00206
00207 assert(pool);
00208
00209 if (!obj)
00210 return;
00211
00212 free_obj = (struct mem_pool_object *)obj;
00213
00214 iflags = cpu_irq_save();
00215 free_obj->next = pool->freelist;
00216 pool->freelist = free_obj;
00217 cpu_irq_restore(iflags);
00218 }