#include #include #include #define ALIGN_BY 32 #define ALIGN_BY_M1 (ALIGN_BY - 1) #define ALIGN(_in) (((_in) + ALIGN_BY_M1) & (~ALIGN_BY_M1)) #define LLOG_LEVEL 1 #define LLOGLN(_log_level, _params) \ do { \ if (_log_level < LLOG_LEVEL) \ { \ printf _params ; \ printf ("\n") ; \ } \ } while (0) struct mem_item { unsigned int addr; int bytes; struct mem_item* next; struct mem_item* prev; }; struct mem_info { unsigned int addr; int bytes; int flags; struct mem_item* free_head; struct mem_item* free_tail; struct mem_item* used_head; struct mem_item* used_tail; int total_bytes; }; /*****************************************************************************/ static int libmem_free_mem_item(struct mem_info* self, struct mem_item* mi) { if (self == 0 || mi == 0) { return 0; } if (mi->prev != 0) { mi->prev->next = mi->next; } if (mi->next != 0) { mi->next->prev = mi->prev; } if (mi == self->free_head) { self->free_head = mi->next; } if (mi == self->free_tail) { self->free_tail = mi->prev; } if (mi == self->used_head) { self->used_head = mi->next; } if (mi == self->used_tail) { self->used_tail = mi->prev; } free(mi); return 0; } /*****************************************************************************/ void* libmem_init(unsigned int addr, int bytes) { struct mem_info* self; struct mem_item* mi; self = (struct mem_info*)malloc(sizeof(struct mem_info)); memset(self, 0, sizeof(struct mem_info)); self->addr = addr; self->bytes = bytes; //self->flags = 1; mi = (struct mem_item*)malloc(sizeof(struct mem_item)); memset(mi, 0, sizeof(struct mem_item)); mi->addr = addr; mi->bytes = bytes; self->free_head = mi; self->free_tail = mi; return self; } /*****************************************************************************/ void libmem_deinit(void* aself) { struct mem_info* self; self = (struct mem_info*)aself; if (self == 0) { return; } while (self->free_head != 0) { libmem_free_mem_item(self, self->free_head); } while (self->used_head != 0) { libmem_free_mem_item(self, self->used_head); } free(self); } /****************************************************************************/ static int libmem_add_used_item(struct mem_info* self, unsigned int addr, int bytes) { struct mem_item* mi; struct mem_item* new_mi; int added; if (self == 0 || addr == 0) { return 1; } if (self->used_head == 0) { /* add first item */ new_mi = (struct mem_item*)malloc(sizeof(struct mem_item)); memset(new_mi, 0, sizeof(struct mem_item)); new_mi->addr = addr; new_mi->bytes = bytes; self->used_head = new_mi; self->used_tail = new_mi; return 0; } added = 0; mi = self->used_head; while (mi != 0) { if (mi->addr > addr) { /* add before */ new_mi = (struct mem_item*)malloc(sizeof(struct mem_item)); memset(new_mi, 0, sizeof(struct mem_item)); new_mi->addr = addr; new_mi->bytes = bytes; new_mi->prev = mi->prev; new_mi->next = mi; if (mi->prev != 0) { mi->prev->next = new_mi; } mi->prev = new_mi; if (self->used_head == mi) { self->used_head = new_mi; } added = 1; break; } mi = mi->next; } if (!added) { /* add last */ new_mi = (struct mem_item*)malloc(sizeof(struct mem_item)); memset(new_mi, 0, sizeof(struct mem_item)); new_mi->addr = addr; new_mi->bytes = bytes; self->used_tail->next = new_mi; new_mi->prev = self->used_tail; self->used_tail = new_mi; } return 0; } /****************************************************************************/ static int libmem_add_free_item(struct mem_info* self, unsigned int addr, int bytes) { struct mem_item* mi; struct mem_item* new_mi; int added; if (self == 0 || addr == 0) { return 1; } if (self->free_head == 0) { /* add first item */ new_mi = (struct mem_item*)malloc(sizeof(struct mem_item)); memset(new_mi, 0, sizeof(struct mem_item)); new_mi->addr = addr; new_mi->bytes = bytes; self->free_head = new_mi; self->free_tail = new_mi; return 0; } added = 0; mi = self->free_head; while (mi != 0) { if (mi->addr > addr) { if (mi->prev != 0) { if (mi->prev->addr + mi->prev->bytes == addr) { /* don't need to add, just make prev bigger */ mi->prev->bytes += bytes; if (mi->prev->addr + mi->prev->bytes == mi->addr) { /* here we can remove one */ mi->prev->bytes += mi->bytes; libmem_free_mem_item(self, mi); } return 0; } } if (addr + bytes == mi->addr) { /* don't need to add here either */ mi->addr = addr; mi->bytes += bytes; return 0; } /* add before */ new_mi = (struct mem_item*)malloc(sizeof(struct mem_item)); memset(new_mi, 0, sizeof(struct mem_item)); new_mi->addr = addr; new_mi->bytes = bytes; new_mi->prev = mi->prev; new_mi->next = mi; if (mi->prev != 0) { mi->prev->next = new_mi; } mi->prev = new_mi; if (self->free_head == mi) { self->free_head = new_mi; } added = 1; break; } mi = mi->next; } if (!added) { /* add last */ new_mi = (struct mem_item*)malloc(sizeof(struct mem_item)); memset(new_mi, 0, sizeof(struct mem_item)); new_mi->addr = addr; new_mi->bytes = bytes; self->free_tail->next = new_mi; new_mi->prev = self->free_tail; self->free_tail = new_mi; } return 0; } /*****************************************************************************/ static int libmem_print(struct mem_info* self) { struct mem_item* mi; LLOGLN(0, ("libmem_print:")); LLOGLN(0, (" used_head %p", self->used_head)); LLOGLN(0, (" used_tail %p", self->used_tail)); mi = self->used_head; if (mi != 0) { LLOGLN(0, (" used list")); while (mi != 0) { LLOGLN(0, (" ptr %p prev %p next %p addr 0x%8.8x bytes %d", mi, mi->prev, mi->next, mi->addr, mi->bytes)); mi = mi->next; } } LLOGLN(0, (" free_head %p", self->free_head)); LLOGLN(0, (" free_tail %p", self->free_tail)); mi = self->free_head; if (mi != 0) { LLOGLN(0, (" free list")); while (mi != 0) { LLOGLN(0, (" ptr %p prev %p next %p addr 0x%8.8x bytes %d", mi, mi->prev, mi->next, mi->addr, mi->bytes)); mi = mi->next; } } return 0; } /*****************************************************************************/ unsigned int libmem_alloc(void* obj, int bytes) { struct mem_info* self; struct mem_item* mi; unsigned int addr; if (bytes < 1) { return 0; } bytes = ALIGN(bytes); self = (struct mem_info*)obj; addr = 0; mi = self->free_head; while (mi != 0) { if (bytes <= mi->bytes) { addr = mi->addr; mi->bytes -= bytes; mi->addr += bytes; if (mi->bytes < 1) { libmem_free_mem_item(self, mi); } break; } mi = mi->next; } if (addr != 0) { self->total_bytes += bytes; libmem_add_used_item(self, addr, bytes); if (self->flags & 1) { libmem_print(self); } } else { LLOGLN(0, ("libmem_alloc: error")); } return addr; } /*****************************************************************************/ int libmem_free(void* obj, unsigned int addr) { struct mem_info* self; struct mem_item* mi; if (addr == 0) { return 0; } self = (struct mem_info*)obj; mi = self->used_tail; while (mi != 0) { if (mi->addr == addr) { self->total_bytes -= mi->bytes; libmem_add_free_item(self, mi->addr, mi->bytes); libmem_free_mem_item(self, mi); if (self->flags & 1) { libmem_print(self); } return 0; } mi = mi->prev; } LLOGLN(0, ("libmem_free: error")); return 1; } /*****************************************************************************/ int libmem_set_flags(void* obj, int flags) { struct mem_info* self; self = (struct mem_info*)obj; self->flags |= flags; return 0; } /*****************************************************************************/ int libmem_clear_flags(void* obj, int flags) { struct mem_info* self; self = (struct mem_info*)obj; self->flags &= ~flags; return 0; } /*****************************************************************************/ int libmem_get_alloced_bytes(void* obj) { struct mem_info* self; self = (struct mem_info*)obj; return self->total_bytes; }