00001
00038 #include <assert.h>
00039 #include <debug.h>
00040 #include <interrupt.h>
00041 #include <util.h>
00042 #include <physmem.h>
00043 #include <string.h>
00044 #include <mempool.h>
00045 #include <membag.h>
00046 #include <app/membag.h>
00047
00049 struct membag {
00050 size_t block_size;
00051 size_t num_blocks;
00052 struct physmem_pool *phys_pool;
00053 struct mem_pool pool;
00054
00055 void *start;
00056 void *end;
00057 #ifdef CONFIG_MEMBAG_USE_TUNING
00058 struct membag_bagstats stats;
00059 #endif
00060 };
00061
00073 #define MEMBAG(objsize, nr_objs, pool) \
00074 { .block_size = objsize, .num_blocks = nr_objs, .phys_pool = pool }
00075
00098 static struct membag membags[] = {
00099 APP_MEMBAG_INITIALIZER
00100 };
00101
00102
00115 static void membag_pool_init_physmem(struct membag *mb, unsigned int align_order)
00116 {
00117 phys_addr_t pool_addr;
00118 size_t pool_size;
00119 size_t block_size;
00120 void *pool_vaddr;
00121
00122 assert(mb);
00123 assert(mb->phys_pool);
00124 assert(mb->block_size > 0);
00125 assert(mb->num_blocks > 0);
00126
00127 block_size = round_up(mb->block_size, align_order);
00128 pool_size = mb->num_blocks * block_size;
00129
00130 pool_addr = physmem_alloc(mb->phys_pool, pool_size, align_order);
00131
00132 assert(pool_addr != PHYSMEM_ALLOC_ERR);
00133
00134 pool_vaddr = physmem_map(pool_addr, pool_size,
00135 PHYS_MAP_WRBUF | PHYS_MAP_WRBACK);
00136 mem_pool_init(&mb->pool, pool_vaddr, pool_size, mb->block_size, align_order);
00137 mb->start = pool_vaddr;
00138 mb->end = (uint8_t *)pool_vaddr + pool_size;
00139
00140 #ifdef CONFIG_MEMBAG_USE_TUNING
00141 mb->stats.num_free_blocks = mb->num_blocks;
00142 mb->stats.max_blocks_used = 0;
00143 mb->stats.min_block_size = block_size;
00144 mb->stats.max_block_size = 0;
00145 mb->stats.num_allocations = 0;
00146 #endif
00147 }
00148
00149
00163 void membag_init(const unsigned int align_order)
00164 {
00165 uint8_t i;
00166
00167
00168 for (i = 0; i < ARRAY_LEN(membags); i++) {
00169 membag_pool_init_physmem(&membags[i], align_order);
00170 }
00171 }
00172
00181 size_t membag_get_total(void)
00182 {
00183 size_t total = 0;
00184 uint16_t blocks;
00185 uint16_t size;
00186 uint8_t i;
00187
00188
00189 for (i = 0; i < ARRAY_LEN(membags); i++) {
00190 size = membags[i].block_size;
00191 blocks = membags[i].num_blocks;
00192 total += size * blocks;
00193 }
00194 return total;
00195 }
00196
00197 #ifdef CONFIG_MEMBAG_USE_TUNING
00198
00205 size_t membag_get_free(void)
00206 {
00207 size_t free = 0;
00208 uint8_t i;
00209
00210
00211 for (i = 0; i < ARRAY_LEN(membags); i++) {
00212 free += membags[i].block_size * membags[i].stats.num_free_blocks;
00213 }
00214
00215 return free;
00216 }
00217 #endif
00218
00226 size_t membag_get_smallest_free_block_size(void)
00227 {
00228 uint8_t i;
00229
00230
00231 for (i = 0; i < ARRAY_LEN(membags); i++) {
00232 if (membags[i].pool.freelist) {
00233 return membags[i].block_size;
00234 }
00235 }
00236 return 0;
00237 }
00238
00246 size_t membag_get_largest_free_block_size(void)
00247 {
00248 uint8_t i = ARRAY_LEN(membags);
00249
00250
00251 while (i > 0) {
00252 i--;
00253 if (membags[i].pool.freelist) {
00254 return membags[i].block_size;
00255 }
00256 }
00257 return 0;
00258 }
00259
00270 void *membag_alloc(size_t size)
00271 {
00272 uint8_t i;
00273 void *ptr = NULL;
00274
00275
00276 for (i = 0; i < ARRAY_LEN(membags); i++) {
00277
00278 if (membags[i].block_size < size) {
00279 continue;
00280 }
00281
00282
00283 ptr = mem_pool_alloc(&membags[i].pool);
00284
00285
00286 if (ptr == NULL) {
00287 continue;
00288 }
00289
00290 #ifdef CONFIG_MEMBAG_USE_TUNING
00291 membags[i].stats.num_free_blocks--;
00292
00293
00294 membags[i].stats.num_allocations++;
00295
00296
00297 if (membags[i].stats.num_allocations >
00298 membags[i].stats.max_blocks_used) {
00299 membags[i].stats.max_blocks_used =
00300 membags[i].stats.num_allocations;
00301 }
00302
00303 if (size < membags[i].stats.min_block_size) {
00304 membags[i].stats.min_block_size = size;
00305 }
00306
00307 if (size > membags[i].stats.max_block_size) {
00308 membags[i].stats.max_block_size = size;
00309 }
00310 #endif
00311
00312
00313 break;
00314 }
00315 return ptr;
00316 }
00317
00327 void membag_free(void *ptr)
00328 {
00329 uint8_t i;
00330
00331
00332 for (i = 0; i < ARRAY_LEN(membags); i++) {
00333 if ((ptr >= membags[i].start) && (ptr <= membags[i].end)) {
00334
00335 mem_pool_free(&membags[i].pool, ptr);
00336 #ifdef CONFIG_MEMBAG_USE_TUNING
00337 membags[i].stats.num_free_blocks++;
00338 #endif
00339 break;
00340 }
00341 }
00342 }
00343
00344 #ifdef CONFIG_MEMBAG_USE_TUNING
00345
00356 void membag_get_bag_stats(size_t bag_no, struct membag_bagstats *stats)
00357 {
00358 assert(bag_no < ARRAY_LEN(membags));
00359
00360 memcpy(stats, &membags[bag_no].stats, sizeof(struct membag_bagstats));
00361 }
00362 #endif