summaryrefslogtreecommitdiffstats
path: root/tests/memtest/libmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/memtest/libmem.c')
-rw-r--r--tests/memtest/libmem.c404
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;
+}