1 #include <xtypes/xheap.h>
2 #include <xtypes/domain.h>
7 //aligned alloc bytes with header size
8 static inline uint64_t __get_alloc_bytes(struct xheap *xheap, uint64_t bytes)
10 return __align(bytes + sizeof(struct xheap_header), xheap->alignment_unit);
13 static inline struct xheap_header* __get_header(void *ptr)
15 return (struct xheap_header *) (ptr - sizeof(struct xheap_header));
18 static inline int __get_index(struct xheap *heap, uint64_t bytes)
20 bytes = __get_alloc_bytes(heap, bytes) - sizeof(struct xheap_header);
21 return (sizeof(bytes)*8 - __builtin_clzl(bytes -1));
24 uint64_t xheap_get_chunk_size(void *ptr)
26 struct xheap_header *h = __get_header(ptr);
30 /* return a pointer to a memory of size
31 * __align(bytes, xheap->alignment_unit) - sizeof(xheap_header)
33 void* xheap_allocate(struct xheap *heap, uint64_t bytes)
35 struct xheap_header *h;
36 int r = __get_index(heap, bytes);
37 void *mem = XPTR(&heap->mem), *addr = NULL;
38 xptr *free_list = (xptr *) mem;
41 xlock_acquire(&heap->lock, 1);
44 //printf("(r: %d) list[%x]: %lu\n", r, &free_list[r], list);
47 next = *(xptr *)(((unsigned long) mem) + head);
49 // printf("popped %llu out of list. list is now %llu\n", head, next);
50 addr = (void *) (((unsigned long)mem) + head);
54 bytes = __get_alloc_bytes(heap, bytes);
55 // printf("before heap->cur: %llu\n", heap->cur);
56 // printf("bytes: %llu\n", bytes);
57 if (heap->cur + bytes > heap->size)
59 addr = (void *) (((unsigned long) mem) + heap->cur + sizeof(struct xheap_header));
60 // printf("after heap->cur: %llu\n", heap->cur);
61 h = (struct xheap_header *) (((unsigned long) mem) + heap->cur);
62 h->size = bytes - sizeof(struct xheap_header);
63 XPTRSET(&h->heap, heap);
67 xlock_release(&heap->lock);
68 // printf("alloced: %lx (size: %llu) (xptr: %llu)\n", addr, __get_header(addr)->size,
73 void __add_in_free_list(struct xheap *heap, xptr* list, void *ptr)
75 void *mem = XPTR(&heap->mem);
76 xptr abs_ptr = (xptr) ((unsigned long)ptr - (unsigned long) mem);
77 xptr cur, *node = (xptr *) ptr;
79 xlock_acquire(&heap->lock, 2);
81 cur = *(volatile xptr *)list;
84 //printf("cur: %llu, next: %llu\n", cur, abs_ptr);
85 //printf("next points to %llu\n", *(xptr *) ptr);
87 xlock_release(&heap->lock);
90 void xheap_free(void *ptr)
92 struct xheap_header *h = __get_header(ptr);
93 struct xheap *heap = XPTR(&h->heap);
94 void *mem = XPTR(&heap->mem);
95 uint64_t size = xheap_get_chunk_size(ptr);
96 xptr *free_list = (xptr *) mem;
97 int r = __get_index(heap, size);
98 //printf("size: %llu, r: %d\n", size, r);
99 __add_in_free_list(heap, &free_list[r], ptr);
100 // printf("freed %lx (size: %llu)\n", ptr, __get_header(ptr)->size);
104 int xheap_init(struct xheap *heap, uint64_t size, uint32_t alignment_unit, void *mem)
106 //int r = (sizeof(size)*8 - __builtin_clzl(size));
108 void *al_mem = (void *) __align((unsigned long)mem, alignment_unit);
109 uint64_t diff = (uint64_t) ((unsigned long)al_mem - (unsigned long)mem);
110 uint64_t heap_page = 1 << alignment_unit;
115 heap->alignment_unit = alignment_unit;
116 XPTRSET(&heap->mem, mem);
118 r = __get_index(heap, size);
120 /* minimum alignment unit required */
121 if (heap_page < sizeof(struct xheap_header))
123 //if (heap_page < sizeof(xptr *) * r)
126 /* make sure unused space in heap start can hold a header*/
127 if (heap->cur < sizeof(struct xheap_header)) {
128 heap->cur += heap_page;
130 heap->cur -= sizeof(struct xheap_header);
132 /* make sure there is enough unused space in heap start to be
133 * used as an indexing array
135 while (heap->cur < sizeof(xptr *) * r)
136 heap->cur += heap_page;
138 /* clean up index array */
139 free_list = (xptr *) mem;
140 for (i = 0; i < r; i++) {
144 /* make sure there is at least one "heap_page" to allocate */
145 if (heap->cur >= size - heap_page)
147 xlock_release(&heap->lock);