#line 1 "memmgr.c" #line 1 "./memmgr.h" typedef unsigned char byte; typedef unsigned long ulong; void memmgr_init(); void* memmgr_alloc(ulong nbytes); void memmgr_free(void* ap); void memmgr_print_stats(); #line 9 "memmgr.c" typedef ulong Align; union mem_header_union { struct { union mem_header_union* next; ulong size; } s; Align align_dummy; }; typedef union mem_header_union mem_header_t; static mem_header_t base; static mem_header_t* freep = 0; static byte pool[8 * 1024] = {0}; static ulong pool_free_pos = 0; void memmgr_init() { base.s.next = 0; base.s.size = 0; freep = 0; pool_free_pos = 0; } void memmgr_print_stats() { mem_header_t* p; printf("------ Memory manager stats ------\n\n"); printf( "Pool: free_pos = %lu (%lu bytes left)\n\n", pool_free_pos,8 * 1024 - pool_free_pos); p = (mem_header_t*) pool; while (p < (mem_header_t*) (pool + pool_free_pos)) { printf( " * Addr: 0x%8lu; Size: %8lu\n", p, p->s.size); p += p->s.size; } printf("\nFree list:\n\n"); if (freep) { p = freep; while (1) { printf( " * Addr: 0x%8lu; Size: %8lu; Next: 0x%8lu\n", p, p->s.size, p->s.next); p = p->s.next; if (p == freep) break; } } else { printf("Empty\n"); } printf("\n"); } static mem_header_t* get_mem_from_pool(ulong nquantas) { ulong total_req_size; mem_header_t* h; if (nquantas < 16) nquantas = 16; total_req_size = nquantas * sizeof(mem_header_t); if (pool_free_pos + total_req_size <= 8 * 1024) { h = (mem_header_t*) (pool + pool_free_pos); h->s.size = nquantas; memmgr_free((void*) (h + 1)); pool_free_pos += total_req_size; } else { return 0; } return freep; } void* memmgr_alloc(ulong nbytes) { mem_header_t* p; mem_header_t* prevp; ulong nquantas = (nbytes + sizeof(mem_header_t) - 1) / sizeof(mem_header_t) + 1; if ((prevp = freep) == 0) { base.s.next = freep = prevp = &base; base.s.size = 0; } for (p = prevp->s.next; ; prevp = p, p = p->s.next) { if (p->s.size >= nquantas) { if (p->s.size == nquantas) { prevp->s.next = p->s.next; } else { p->s.size -= nquantas; p += p->s.size; p->s.size = nquantas; } freep = prevp; return (void*) (p + 1); } else if (p == freep) { if ((p = get_mem_from_pool(nquantas)) == 0) { return 0; } } } } void memmgr_free(void* ap) { mem_header_t* block; mem_header_t* p; block = ((mem_header_t*) ap) - 1; for (p = freep; !(block > p && block < p->s.next); p = p->s.next) { if (p >= p->s.next && (block > p || block < p->s.next)) break; } if (block + block->s.size == p->s.next) { block->s.size += p->s.next->s.size; block->s.next = p->s.next->s.next; } else { block->s.next = p->s.next; } if (p + p->s.size == block) { p->s.size += block->s.size; p->s.next = block->s.next; } else { p->s.next = block; } freep = p; }