diff options
Diffstat (limited to 'tests/memtest/libmem.c')
| -rw-r--r-- | tests/memtest/libmem.c | 404 |
1 files changed, 404 insertions, 0 deletions
diff --git a/tests/memtest/libmem.c b/tests/memtest/libmem.c new file mode 100644 index 00000000..2fa0dea7 --- /dev/null +++ b/tests/memtest/libmem.c @@ -0,0 +1,404 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#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; +} |
