diff --git a/tests/memtest/Makefile b/tests/memtest/Makefile new file mode 100644 index 00000000..c0310ece --- /dev/null +++ b/tests/memtest/Makefile @@ -0,0 +1,13 @@ + +OBJS = libmem.o memtest.o + +#CFLAGS = -O2 -Wall +CFLAGS = -g + +all: memtest + +memtest: $(OBJS) + $(CC) -o memtest $(OBJS) + +clean: + rm -f $(OBJS) librdp.a diff --git a/tests/memtest/libmem.c b/tests/memtest/libmem.c new file mode 100644 index 00000000..8038f108 --- /dev/null +++ b/tests/memtest/libmem.c @@ -0,0 +1,423 @@ + +#include +#include +#include + +#define ALIGN_BY 1024 +#define ALIGN_BY_M1 (ALIGN_BY - 1) +#define ALIGN(_in) (((_in) + ALIGN_BY_M1) & (~ALIGN_BY_M1)) + +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; +}; + +/*****************************************************************************/ +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) + { + /* 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_pack_free(struct mem_info* self) +{ + struct mem_item* mi; + int cont; + + cont = 1; + while (cont) + { + cont = 0; + mi = self->free_head; + while (mi != 0) + { + /* combine */ + if (mi->next != 0) + { + if (mi->addr + mi->bytes == mi->next->addr) + { + mi->bytes += mi->next->bytes; + cont = 1; + libmem_free_mem_item(self, mi->next); + } + } + /* remove empties */ + if (mi->bytes == 0) + { + cont = 1; + libmem_free_mem_item(self, mi); + mi = self->free_head; + continue; + } + mi = mi->next; + } + } + return 0; +} + +/*****************************************************************************/ +static int +libmem_print(struct mem_info* self) +{ + struct mem_item* mi; + + printf("libmem_print:\n"); + printf(" used_head %p\n", self->used_head); + printf(" used_tail %p\n", self->used_tail); + mi = self->used_head; + if (mi != 0) + { + printf(" used list\n"); + while (mi != 0) + { + printf(" ptr %p prev %p next %p addr 0x%8.8x bytes %d\n", + mi, mi->prev, mi->next, mi->addr, mi->bytes); + mi = mi->next; + } + } + printf(" free_head %p\n", self->free_head); + printf(" free_tail %p\n", self->free_tail); + mi = self->free_head; + if (mi != 0) + { + printf(" free list\n"); + while (mi != 0) + { + printf(" ptr %p prev %p next %p addr 0x%8.8x bytes %d\n", + 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; + if (bytes > 16 * 1024) + { + /* big blocks */ + mi = self->free_tail; + while (mi != 0) + { + if (bytes <= mi->bytes) + { + addr = mi->addr; + mi->bytes -= bytes; + mi->addr += bytes; + break; + } + mi = mi->prev; + } + } + else + { + /* small blocks */ + mi = self->free_head; + while (mi != 0) + { + if (bytes <= mi->bytes) + { + addr = mi->addr; + mi->bytes -= bytes; + mi->addr += bytes; + break; + } + mi = mi->next; + } + } + if (addr != 0) + { + libmem_add_used_item(self, addr, bytes); + libmem_pack_free(self); + if (self->flags & 1) + { + libmem_print(self); + } + } + else + { + printf("libmem_alloc: error\n"); + } + 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_head; + while (mi != 0) + { + if (mi->addr == addr) + { + libmem_add_free_item(self, mi->addr, mi->bytes); + libmem_free_mem_item(self, mi); + libmem_pack_free(self); + if (self->flags & 1) + { + libmem_print(self); + } + return 0; + } + mi = mi->next; + } + printf("libmem_free: error\n"); + return 1; +} + +/*****************************************************************************/ +int +libmem_set_flags(void* obj, int flags) +{ + struct mem_info* self; + + self = (struct mem_info*)obj; + self->flags |= flags; +} + +/*****************************************************************************/ +int +libmem_clear_flags(void* obj, int flags) +{ + struct mem_info* self; + + self = (struct mem_info*)obj; + self->flags &= ~flags; +} diff --git a/tests/memtest/libmem.h b/tests/memtest/libmem.h new file mode 100644 index 00000000..4bc4b1ec --- /dev/null +++ b/tests/memtest/libmem.h @@ -0,0 +1,18 @@ + +#ifndef _LIBMEM_C +#define _LIBMEM_C + +void* +libmem_init(unsigned int addr, int bytes); +void +libmem_deinit(void* aself); +unsigned int +libmem_alloc(void* obj, int bytes); +int +libmem_free(void* obj, unsigned int addr); +int +libmem_set_flags(void* obj, int flags); +int +libmem_clear_flags(void* obj, int flags); + +#endif diff --git a/tests/memtest/memtest.c b/tests/memtest/memtest.c new file mode 100644 index 00000000..e7a26045 --- /dev/null +++ b/tests/memtest/memtest.c @@ -0,0 +1,60 @@ + +#include +#include +#include + +#include "libmem.h" + +int main(int argc, char** argv) +{ + void* obj; + unsigned int addr1; + unsigned int addr2; + unsigned int addr3; + unsigned int addr4; + unsigned int addr5; + int index; + int rd; + + srand(time(0)); + obj = libmem_init(0x80000000, 64 * 1024 * 1024); + for (index = 0; index < 256; index++) + { + rd = rand() & 0xffff; + printf("1 rd %d\n", rd); + addr1 = libmem_alloc(obj, rd); + rd = rand() & 0xffff; + printf("2 rd %d\n", rd); + addr2 = libmem_alloc(obj, rd); + rd = rand() & 0xffff; + printf("3 rd %d\n", rd); + addr3 = libmem_alloc(obj, rd); + rd = rand() & 0xffff; + printf("4 rd %d\n", rd); + addr4 = libmem_alloc(obj, rd); + addr5 = libmem_alloc(obj, rd); + libmem_free(obj, addr1); + printf("5\n"); + addr1 = libmem_alloc(obj, 64); + printf("6\n"); + libmem_free(obj, addr3); + printf("7\n"); + addr3 = libmem_alloc(obj, 64 * 1024); + libmem_free(obj, addr5); + addr5 = libmem_alloc(obj, 64 * 1024); + printf("8\n"); + libmem_free(obj, addr1); + printf("9\n"); + libmem_free(obj, addr2); + printf("10\n"); + libmem_free(obj, addr3); + libmem_free(obj, addr4); + if (index == 255) + { + libmem_set_flags(obj, 1); + } + libmem_free(obj, addr5); + } + libmem_deinit(obj); + return 0; +}