summaryrefslogtreecommitdiff
path: root/Build/source/libs/pplib/pplib-src/src/util/utilmemheap.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/pplib/pplib-src/src/util/utilmemheap.c')
-rw-r--r--Build/source/libs/pplib/pplib-src/src/util/utilmemheap.c1078
1 files changed, 1078 insertions, 0 deletions
diff --git a/Build/source/libs/pplib/pplib-src/src/util/utilmemheap.c b/Build/source/libs/pplib/pplib-src/src/util/utilmemheap.c
new file mode 100644
index 00000000000..cce28e0ed07
--- /dev/null
+++ b/Build/source/libs/pplib/pplib-src/src/util/utilmemheap.c
@@ -0,0 +1,1078 @@
+
+#include "utilmemheap.h"
+#include "utilmemallc.h"
+
+#define pyre_alloc8(heap, space) ((pyre8 *)((heap->flags & HEAP_ZERO) ? util_calloc(1, sizeof(pyre8) + space * sizeof(uint8_t)) : util_malloc(sizeof(pyre8) + space * sizeof(uint8_t))))
+#define pyre_alloc16(heap, space) ((pyre16 *)((heap->flags & HEAP_ZERO) ? util_calloc(1, sizeof(pyre16) + space * sizeof(uint8_t)) : util_malloc(sizeof(pyre16) + space * sizeof(uint8_t))))
+#define pyre_alloc32(heap, space) ((pyre32 *)((heap->flags & HEAP_ZERO) ? util_calloc(1, sizeof(pyre32) + space * sizeof(uint8_t)) : util_malloc(sizeof(pyre32) + space * sizeof(uint8_t))))
+#define pyre_alloc64(heap, space) ((pyre64 *)((heap->flags & HEAP_ZERO) ? util_calloc(1, sizeof(pyre64) + space * sizeof(uint8_t)) : util_malloc(sizeof(pyre64) + space * sizeof(uint8_t))))
+
+#define pyre_free(pyre) util_free(pyre)
+
+/* block reset */
+
+#define reset_heap_head8(heap, pyre, used) \
+ ((used = block_used8(pyre)), (pyre->data -= used), ((heap->flags & HEAP_ZERO) ? (memset(pyre->data, 0, used), 0) : 0), (pyre->left += (uint8_t)used))
+#define reset_heap_head16(heap, pyre, used) \
+ ((used = block_used16(pyre)), (pyre->data -= used), ((heap->flags & HEAP_ZERO) ? (memset(pyre->data, 0, used), 0) : 0), (pyre->left += (uint16_t)used))
+#define reset_heap_head32(heap, pyre, used) \
+ ((used = block_used32(pyre)), (pyre->data -= used), ((heap->flags & HEAP_ZERO) ? (memset(pyre->data, 0, used), 0) : 0), (pyre->left += (uint32_t)used))
+#define reset_heap_head64(heap, pyre, used) \
+ ((used = block_used64(pyre)), (pyre->data -= used), ((heap->flags & HEAP_ZERO) ? (memset(pyre->data, 0, used), 0) : 0), (pyre->left += (uint64_t)used))
+
+/* init heap */
+
+heap8 * heap8_init (heap8 *heap, uint8_t space, uint8_t large, uint8_t flags)
+{
+ align_space8(space);
+ if (large > space) large = space;
+ heap->head = NULL;
+ heap->space = space;
+ heap->large = large;
+ heap->flags = flags;
+ return heap;
+}
+
+heap16 * heap16_init (heap16 *heap, uint16_t space, uint16_t large, uint8_t flags)
+{
+ align_space16(space);
+ if (large > space) large = space;
+ heap->head = NULL;
+ heap->space = space;
+ heap->large = large;
+ heap->flags = flags;
+ return heap;
+}
+
+heap32 * heap32_init (heap32 *heap, uint32_t space, uint32_t large, uint8_t flags)
+{
+ align_space32(space);
+ if (large > space) large = space;
+ heap->head = NULL;
+ heap->space = space;
+ heap->large = large;
+ heap->flags = flags;
+ return heap;
+}
+
+heap64 * heap64_init (heap64 *heap, uint64_t space, uint64_t large, uint8_t flags)
+{
+ align_space64(space);
+ if (large > space) large = space;
+ heap->head = NULL;
+ heap->space = space;
+ heap->large = large;
+ heap->flags = flags;
+ return heap;
+}
+
+/* free heap */
+
+void heap8_free (heap8 *heap)
+{
+ pyre8 *pyre, *prev;
+ pyre = heap->head;
+ heap->head = NULL;
+ while (pyre != NULL)
+ {
+ prev = pyre->prev;
+ pyre_free(pyre);
+ pyre = prev;
+ }
+}
+
+void heap16_free (heap16 *heap)
+{
+ pyre16 *pyre, *prev;
+ pyre = heap->head;
+ heap->head = NULL;
+ while (pyre != NULL)
+ {
+ prev = pyre->prev;
+ pyre_free(pyre);
+ pyre = prev;
+ }
+}
+
+void heap32_free (heap32 *heap)
+{
+ pyre32 *pyre, *prev;
+ pyre = heap->head;
+ heap->head = NULL;
+ while (pyre != NULL)
+ {
+ prev = pyre->prev;
+ pyre_free(pyre);
+ pyre = prev;
+ }
+}
+
+void heap64_free (heap64 *heap)
+{
+ pyre64 *pyre, *prev;
+ pyre = heap->head;
+ heap->head = NULL;
+ while (pyre != NULL)
+ {
+ prev = pyre->prev;
+ pyre_free(pyre);
+ pyre = prev;
+ }
+}
+
+/* clear heap */
+
+void heap8_clear (heap8 *heap)
+{
+ pyre8 *pyre, *prev;
+ size_t used;
+ if ((pyre = heap->head) == NULL)
+ return;
+ prev = pyre->prev;
+ pyre->prev = NULL;
+ reset_heap_head8(heap, pyre, used);
+ for (; prev != NULL; prev = pyre)
+ {
+ pyre = prev->prev;
+ pyre_free(prev);
+ }
+}
+
+void heap16_clear (heap16 *heap)
+{
+ pyre16 *pyre, *prev;
+ size_t used;
+ if ((pyre = heap->head) == NULL)
+ return;
+ prev = pyre->prev;
+ pyre->prev = NULL;
+ reset_heap_head16(heap, pyre, used);
+ for (; prev != NULL; prev = pyre)
+ {
+ pyre = prev->prev;
+ pyre_free(prev);
+ }
+}
+
+void heap32_clear (heap32 *heap)
+{
+ pyre32 *pyre, *prev;
+ size_t used;
+ if ((pyre = heap->head) == NULL)
+ return;
+ prev = pyre->prev;
+ pyre->prev = NULL;
+ reset_heap_head32(heap, pyre, used);
+ for (; prev != NULL; prev = pyre)
+ {
+ pyre = prev->prev;
+ pyre_free(prev);
+ }
+}
+
+void heap64_clear (heap64 *heap)
+{
+ pyre64 *pyre, *prev;
+ size_t used;
+ if ((pyre = heap->head) == NULL)
+ return;
+ prev = pyre->prev;
+ pyre->prev = NULL;
+ reset_heap_head64(heap, pyre, used);
+ for (; prev != NULL; prev = pyre)
+ {
+ pyre = prev->prev;
+ pyre_free(prev);
+ }
+}
+
+/* heap head */
+
+void heap8_head (heap8 *heap)
+{
+ pyre8 *pyre;
+ heap->head = pyre = pyre_alloc8(heap, heap->space);
+ pyre->prev = NULL;
+ pyre->data = block_edge8(pyre);
+ pyre->left = block_left8(pyre, heap->space);
+ pyre->chunks = 0;
+}
+
+void heap16_head (heap16 *heap)
+{
+ pyre16 *pyre;
+ heap->head = pyre = pyre_alloc16(heap, heap->space);
+ pyre->prev = NULL;
+ pyre->data = block_edge16(pyre);
+ pyre->left = block_left16(pyre, heap->space);
+ pyre->chunks = 0;
+}
+
+void heap32_head (heap32 *heap)
+{
+ pyre32 *pyre;
+ heap->head = pyre = pyre_alloc32(heap, heap->space);
+ pyre->prev = NULL;
+ pyre->data = block_edge32(pyre);
+ pyre->left = block_left32(pyre, heap->space);
+ pyre->chunks = 0;
+}
+
+void heap64_head (heap64 *heap)
+{
+ pyre64 *pyre;
+ heap->head = pyre = pyre_alloc64(heap, heap->space);
+ pyre->prev = NULL;
+ pyre->data = block_edge64(pyre);
+ pyre->left = block_left64(pyre, heap->space);
+ pyre->chunks = 0;
+}
+
+/* next heap head */
+
+static pyre8 * heap8_new (heap8 *heap)
+{
+ pyre8 *pyre;
+ pyre = pyre_alloc8(heap, heap->space);
+ pyre->prev = heap->head;
+ heap->head = pyre;
+ pyre->data = block_edge8(pyre);
+ pyre->left = block_left8(pyre, heap->space);
+ pyre->chunks = 0;
+ return pyre;
+}
+
+static pyre16 * heap16_new (heap16 *heap)
+{
+ pyre16 *pyre;
+ pyre = pyre_alloc16(heap, heap->space);
+ pyre->prev = heap->head;
+ heap->head = pyre;
+ pyre->data = block_edge16(pyre);
+ pyre->left = block_left16(pyre, heap->space);
+ pyre->chunks = 0;
+ return pyre;
+}
+
+static pyre32 * heap32_new (heap32 *heap)
+{
+ pyre32 *pyre;
+ pyre = pyre_alloc32(heap, heap->space);
+ pyre->prev = heap->head;
+ heap->head = pyre;
+ pyre->data = block_edge32(pyre);
+ pyre->left = block_left32(pyre, heap->space);
+ pyre->chunks = 0;
+ return pyre;
+}
+
+static pyre64 * heap64_new (heap64 *heap)
+{
+ pyre64 *pyre;
+ pyre = pyre_alloc64(heap, heap->space);
+ pyre->prev = heap->head;
+ heap->head = pyre;
+ pyre->data = block_edge64(pyre);
+ pyre->left = block_left64(pyre, heap->space);
+ pyre->chunks = 0;
+ return pyre;
+}
+
+/* next heap sole */
+
+static pyre8 * heap8_sole (heap8 *heap, size_t size)
+{
+ pyre8 *pyre, *head, *prev;
+ pyre = pyre_alloc8(heap, size);
+ head = heap->head;
+ prev = head->prev;
+ pyre->prev = prev;
+ head->prev = pyre;
+ pyre->data = block_edge8(pyre);
+ pyre->left = 0; // (uint8_t)size makes no sense, even with buffer api it will finally become 0
+ return pyre;
+}
+
+static pyre16 * heap16_sole (heap16 *heap, size_t size)
+{
+ pyre16 *pyre, *head, *prev;
+ pyre = pyre_alloc16(heap, size);
+ head = heap->head;
+ prev = head->prev;
+ pyre->prev = prev;
+ head->prev = pyre;
+ pyre->data = block_edge16(pyre);
+ pyre->left = 0;
+ return pyre;
+}
+
+static pyre32 * heap32_sole (heap32 *heap, size_t size)
+{
+ pyre32 *pyre, *head, *prev;
+ pyre = pyre_alloc32(heap, size);
+ head = heap->head;
+ prev = head->prev;
+ pyre->prev = prev;
+ head->prev = pyre;
+ pyre->data = block_edge32(pyre);
+ pyre->left = 0;
+ return pyre;
+}
+
+static pyre64 * heap64_sole (heap64 *heap, size_t size)
+{
+ pyre64 *pyre, *head, *prev;
+ pyre = pyre_alloc64(heap, size);
+ head = heap->head;
+ prev = head->prev;
+ pyre->prev = prev;
+ head->prev = pyre;
+ pyre->data = block_edge64(pyre);
+ pyre->left = 0;
+ return pyre;
+}
+
+/* take from heap */
+
+#define pyre_next8(d, pyre, size) (d = pyre->data, pyre->data += size, pyre->left -= (uint8_t)size, ++pyre->chunks)
+#define pyre_next16(d, pyre, size) (d = pyre->data, pyre->data += size, pyre->left -= (uint16_t)size, ++pyre->chunks)
+#define pyre_next32(d, pyre, size) (d = pyre->data, pyre->data += size, pyre->left -= (uint32_t)size, ++pyre->chunks)
+#define pyre_next64(d, pyre, size) (d = pyre->data, pyre->data += size, pyre->left -= (uint64_t)size, ++pyre->chunks)
+
+// for sole blocks, block->left is permanently 0, we can't store size_t there
+#define pyre_last8(d, pyre, size) (d = pyre->data, pyre->data += size, pyre->chunks = 1)
+#define pyre_last16(d, pyre, size) (d = pyre->data, pyre->data += size, pyre->chunks = 1)
+#define pyre_last32(d, pyre, size) (d = pyre->data, pyre->data += size, pyre->chunks = 1)
+#define pyre_last64(d, pyre, size) (d = pyre->data, pyre->data += size, pyre->chunks = 1)
+
+void * _heap8_take (heap8 *heap, size_t size)
+{
+ pyre8 *pyre;
+ void *data;
+ pyre = heap->head;
+ align_size8(size);
+ if (size <= pyre->left)
+ {
+ pyre_next8(data, pyre, size);
+ }
+ else if (take_new_block8(heap, pyre8, pyre, size))
+ {
+ pyre = heap8_new(heap);
+ pyre_next8(data, pyre, size);
+ }
+ else
+ {
+ pyre = heap8_sole(heap, size);
+ pyre_last8(data, pyre, size);
+ }
+ return data;
+}
+
+void * _heap16_take (heap16 *heap, size_t size)
+{
+ pyre16 *pyre;
+ void *data;
+ pyre = heap->head;
+ align_size16(size);
+ if (size <= pyre->left)
+ {
+ pyre_next16(data, pyre, size);
+ }
+ else if (take_new_block16(heap, pyre16, pyre, size))
+ {
+ pyre = heap16_new(heap);
+ pyre_next16(data, pyre, size);
+ }
+ else
+ {
+ pyre = heap16_sole(heap, size);
+ pyre_last16(data, pyre, size);
+ }
+ return data;
+}
+
+void * _heap32_take (heap32 *heap, size_t size)
+{
+ pyre32 *pyre;
+ void *data;
+ pyre = heap->head;
+ align_size32(size);
+ if (size <= pyre->left)
+ {
+ pyre_next32(data, pyre, size);
+ }
+ else if (take_new_block32(heap, pyre32, pyre, size))
+ {
+ pyre = heap32_new(heap);
+ pyre_next32(data, pyre, size);
+ }
+ else
+ {
+ pyre = heap32_sole(heap, size);
+ pyre_last32(data, pyre, size);
+ }
+ return data;
+}
+
+void * _heap64_take (heap64 *heap, size_t size)
+{
+ pyre64 *pyre;
+ void *data;
+ pyre = heap->head;
+ align_size64(size);
+ if (size <= pyre->left)
+ {
+ pyre_next64(data, pyre, size);
+ }
+ else if (take_new_block64(heap, pyre64, pyre, size))
+ {
+ pyre = heap64_new(heap);
+ pyre_next64(data, pyre, size);
+ }
+ else
+ {
+ pyre = heap64_sole(heap, size);
+ pyre_last64(data, pyre, size);
+ }
+ return data;
+}
+
+void * _heap8_take0 (heap8 *heap, size_t size)
+{
+ return memset(_heap8_take(heap, size), 0, size);
+}
+
+void * _heap16_take0 (heap16 *heap, size_t size)
+{
+ return memset(_heap16_take(heap, size), 0, size);
+}
+
+void * _heap32_take0 (heap32 *heap, size_t size)
+{
+ return memset(_heap32_take(heap, size), 0, size);
+}
+
+void * _heap64_take0 (heap64 *heap, size_t size)
+{
+ return memset(_heap64_take(heap, size), 0, size);
+}
+
+/* pop last heap chunk */
+
+#define taken_from_head(taken, head) (byte_data(taken) == head->data)
+#define taken_from_sole(taken, head, sole) ((sole = head->prev) != NULL && byte_data(taken) == sole->data)
+
+#define taken_prev_head(taken, head, size) (byte_data(taken) == head->data - size)
+#define taken_prev_sole(taken, head, sole, size) ((sole = head->prev) != NULL && byte_data(taken) == sole->data - size)
+
+void heap8_pop (heap8 *heap, void *taken, size_t size)
+{
+ pyre8 *pyre, *head;
+ head = heap->head;
+ align_size8(size);
+ if (taken_prev_head(taken, head, size))
+ {
+
+ head->data -= size;
+ head->left += (uint8_t)size;
+ --head->chunks;
+ }
+ else if (taken_prev_sole(taken, head, pyre, size))
+ {
+ head->prev = pyre->prev;
+ pyre_free(pyre);
+ }
+ else
+ {
+ ASSERT8(0);
+ }
+}
+
+void heap16_pop (heap16 *heap, void *taken, size_t size)
+{
+ pyre16 *pyre, *head;
+ head = heap->head;
+ align_size16(size);
+ if (taken_prev_head(taken, head, size))
+ {
+
+ head->data -= size;
+ head->left += (uint16_t)size;
+ --head->chunks;
+ }
+ else if (taken_prev_sole(taken, head, pyre, size))
+ {
+ head->prev = pyre->prev;
+ pyre_free(pyre);
+ }
+ else
+ {
+ ASSERT16(0);
+ }
+}
+
+void heap32_pop (heap32 *heap, void *taken, size_t size)
+{
+ pyre32 *pyre, *head;
+ head = heap->head;
+ align_size32(size);
+ if (taken_prev_head(taken, head, size))
+ {
+
+ head->data -= size;
+ head->left += (uint32_t)size;
+ --head->chunks;
+ }
+ else if (taken_prev_sole(taken, head, pyre, size))
+ {
+ head->prev = pyre->prev;
+ pyre_free(pyre);
+ }
+ else
+ {
+ ASSERT32(0);
+ }
+}
+
+void heap64_pop (heap64 *heap, void *taken, size_t size)
+{
+ pyre64 *pyre, *head;
+ head = heap->head;
+ align_size64(size);
+ if (taken_prev_head(taken, head, size))
+ {
+
+ head->data -= size;
+ head->left += (uint64_t)size;
+ --head->chunks;
+ }
+ else if (taken_prev_sole(taken, head, pyre, size))
+ {
+ head->prev = pyre->prev;
+ pyre_free(pyre);
+ }
+ else
+ {
+ ASSERT64(0);
+ }
+}
+
+/* heap buffer */
+
+void * _heap8_some (heap8 *heap, size_t size, size_t *pspace)
+{
+ pyre8 *pyre;
+ pyre = heap->head;
+ align_size8(size);
+ if (size <= pyre->left)
+ {
+ *pspace = pyre->left;
+ }
+ else if (take_new_block8(heap, pyre8, pyre, size))
+ {
+ pyre = heap8_new(heap);
+ *pspace = pyre->left;
+ }
+ else
+ {
+ pyre = heap8_sole(heap, size);
+ *pspace = size;
+ }
+ return void_data(pyre->data);
+}
+
+void * _heap16_some (heap16 *heap, size_t size, size_t *pspace)
+{
+ pyre16 *pyre;
+ pyre = heap->head;
+ align_size16(size);
+ if (size <= pyre->left)
+ {
+ *pspace = pyre->left;
+ }
+ else if (take_new_block16(heap, pyre16, pyre, size))
+ {
+ pyre = heap16_new(heap);
+ *pspace = pyre->left;
+ }
+ else
+ {
+ pyre = heap16_sole(heap, size);
+ *pspace = size;
+ }
+ return void_data(pyre->data);
+}
+
+void * _heap32_some (heap32 *heap, size_t size, size_t *pspace)
+{
+ pyre32 *pyre;
+ pyre = heap->head;
+ align_size32(size);
+ if (size <= pyre->left)
+ {
+ *pspace = pyre->left;
+ }
+ else if (take_new_block32(heap, pyre32, pyre, size))
+ {
+ pyre = heap32_new(heap);
+ *pspace = pyre->left;
+ }
+ else
+ {
+ pyre = heap32_sole(heap, size);
+ *pspace = size;
+ }
+ return void_data(pyre->data);
+}
+
+void * _heap64_some (heap64 *heap, size_t size, size_t *pspace)
+{
+ pyre64 *pyre;
+ pyre = heap->head;
+ align_size64(size);
+ if (size <= pyre->left)
+ {
+ *pspace = pyre->left;
+ }
+ else if (take_new_block64(heap, pyre64, pyre, size))
+ {
+ pyre = heap64_new(heap);
+ *pspace = pyre->left;
+ }
+ else
+ {
+ pyre = heap64_sole(heap, size);
+ *pspace = size;
+ }
+ return void_data(pyre->data);
+}
+
+void * heap8_more (heap8 *heap, void *taken, size_t written, size_t size, size_t *pspace)
+{
+ pyre8 *pyre, *prev;
+ pyre = heap->head;
+ align_size8(size);
+ if (taken_from_head(taken, pyre))
+ {
+ if (size <= pyre->left)
+ {
+ *pspace = pyre->left;
+ }
+ else if (take_new_block8(heap, pyre8, pyre, size))
+ {
+ pyre = heap8_new(heap);
+ memcpy(pyre->data, taken, written);
+ *pspace = pyre->left;
+ }
+ else
+ {
+ pyre = heap8_sole(heap, size);
+ memcpy(pyre->data, taken, written);
+ *pspace = size;
+ }
+ }
+ else if (taken_from_sole(taken, pyre, prev))
+ {
+ pyre = heap8_sole(heap, size);
+ memcpy(pyre->data, taken, written);
+ *pspace = size;
+ pyre->prev = prev->prev;
+ pyre_free(prev);
+ }
+ else
+ {
+ ASSERT8(0);
+ *pspace = 0;
+ return NULL;
+ }
+ return void_data(pyre->data);
+}
+
+void * heap16_more (heap16 *heap, void *taken, size_t written, size_t size, size_t *pspace)
+{
+ pyre16 *pyre, *prev;
+ pyre = heap->head;
+ align_size16(size);
+ if (taken_from_head(taken, pyre))
+ {
+ if (size <= pyre->left)
+ {
+ *pspace = pyre->left;
+ }
+ else if (take_new_block16(heap, pyre16, pyre, size))
+ {
+ pyre = heap16_new(heap);
+ memcpy(pyre->data, taken, written);
+ *pspace = pyre->left;
+ }
+ else
+ {
+ pyre = heap16_sole(heap, size);
+ memcpy(pyre->data, taken, written);
+ *pspace = size;
+ }
+ }
+ else if (taken_from_sole(taken, pyre, prev))
+ {
+ pyre = heap16_sole(heap, size);
+ memcpy(pyre->data, taken, written);
+ *pspace = size;
+ pyre->prev = prev->prev;
+ pyre_free(prev);
+ }
+ else
+ {
+ ASSERT16(0);
+ *pspace = 0;
+ return NULL;
+ }
+ return void_data(pyre->data);
+}
+
+void * heap32_more (heap32 *heap, void *taken, size_t written, size_t size, size_t *pspace)
+{
+ pyre32 *pyre, *prev;
+ pyre = heap->head;
+ align_size32(size);
+ if (taken_from_head(taken, pyre))
+ {
+ if (size <= pyre->left)
+ {
+ *pspace = pyre->left;
+ }
+ else if (take_new_block32(heap, pyre32, pyre, size))
+ {
+ pyre = heap32_new(heap);
+ memcpy(pyre->data, taken, written);
+ *pspace = pyre->left;
+ }
+ else
+ {
+ pyre = heap32_sole(heap, size);
+ memcpy(pyre->data, taken, written);
+ *pspace = size;
+ }
+ }
+ else if (taken_from_sole(taken, pyre, prev))
+ {
+ pyre = heap32_sole(heap, size);
+ memcpy(pyre->data, taken, written);
+ *pspace = size;
+ pyre->prev = prev->prev;
+ pyre_free(prev);
+ }
+ else
+ {
+ ASSERT32(0);
+ *pspace = 0;
+ return NULL;
+ }
+ return void_data(pyre->data);
+}
+
+void * heap64_more (heap64 *heap, void *taken, size_t written, size_t size, size_t *pspace)
+{
+ pyre64 *pyre, *prev;
+ pyre = heap->head;
+ align_size64(size);
+ if (taken_from_head(taken, pyre))
+ {
+ if (size <= pyre->left)
+ {
+ *pspace = pyre->left;
+ }
+ else if (take_new_block64(heap, pyre64, pyre, size))
+ {
+ pyre = heap64_new(heap);
+ memcpy(pyre->data, taken, written);
+ *pspace = pyre->left;
+ }
+ else
+ {
+ pyre = heap64_sole(heap, size);
+ memcpy(pyre->data, taken, written);
+ *pspace = size;
+ }
+ }
+ else if (taken_from_sole(taken, pyre, prev))
+ {
+ pyre = heap64_sole(heap, size);
+ memcpy(pyre->data, taken, written);
+ *pspace = size;
+ pyre->prev = prev->prev;
+ pyre_free(prev);
+ }
+ else
+ {
+ ASSERT64(0);
+ *pspace = 0;
+ return NULL;
+ }
+ return void_data(pyre->data);
+}
+
+void heap8_done (heap8 *heap, void *taken, size_t written)
+{
+ pyre8 *pyre;
+ pyre = heap->head;
+ align_size8(written);
+ if (taken_from_head(taken, pyre))
+ {
+ pyre->data += written;
+ pyre->left -= (uint8_t)written;
+ ++pyre->chunks;
+ }
+ else if (taken_from_sole(taken, pyre, pyre))
+ {
+ pyre->data += written;
+ pyre->chunks = 1;
+ }
+ else
+ {
+ ASSERT8(0);
+ }
+}
+
+void heap16_done (heap16 *heap, void *taken, size_t written)
+{
+ pyre16 *pyre;
+ pyre = heap->head;
+ align_size16(written);
+ if (taken_from_head(taken, pyre))
+ {
+ pyre->data += written;
+ pyre->left -= (uint16_t)written;
+ ++pyre->chunks;
+ }
+ else if (taken_from_sole(taken, pyre, pyre))
+ {
+ pyre->data += written;
+ pyre->chunks = 1;
+ }
+ else
+ {
+ ASSERT16(0);
+ }
+}
+
+void heap32_done (heap32 *heap, void *taken, size_t written)
+{
+ pyre32 *pyre;
+ pyre = heap->head;
+ align_size32(written);
+ if (taken_from_head(taken, pyre))
+ {
+ pyre->data += written;
+ pyre->left -= (uint32_t)written;
+ ++pyre->chunks;
+ }
+ else if (taken_from_sole(taken, pyre, pyre))
+ {
+ pyre->data += written;
+ pyre->chunks = 1;
+ }
+ else
+ {
+ ASSERT32(0);
+ }
+}
+
+void heap64_done (heap64 *heap, void *taken, size_t written)
+{
+ pyre64 *pyre;
+ pyre = heap->head;
+ align_size64(written);
+ if (taken_from_head(taken, pyre))
+ {
+ pyre->data += written;
+ pyre->left -= (uint64_t)written;
+ ++pyre->chunks;
+ }
+ else if (taken_from_sole(taken, pyre, pyre))
+ {
+ pyre->data += written;
+ pyre->chunks = 1;
+ }
+ else
+ {
+ ASSERT64(0);
+ }
+}
+
+/* giveup */
+
+void heap8_giveup (heap8 *heap, void *taken)
+{
+ pyre8 *head, *pyre;
+ head = heap->head;
+ if (taken_from_sole(taken, head, pyre))
+ {
+ head->prev = pyre->prev;
+ pyre_free(pyre);
+ }
+}
+
+void heap16_giveup (heap16 *heap, void *taken)
+{
+ pyre16 *head, *pyre;
+ head = heap->head;
+ if (taken_from_sole(taken, head, pyre))
+ {
+ head->prev = pyre->prev;
+ pyre_free(pyre);
+ }
+}
+
+void heap32_giveup (heap32 *heap, void *taken)
+{
+ pyre32 *head, *pyre;
+ head = heap->head;
+ if (taken_from_sole(taken, head, pyre))
+ {
+ head->prev = pyre->prev;
+ pyre_free(pyre);
+ }
+}
+
+void heap64_giveup (heap64 *heap, void *taken)
+{
+ pyre64 *head, *pyre;
+ head = heap->head;
+ if (taken_from_sole(taken, head, pyre))
+ {
+ head->prev = pyre->prev;
+ pyre_free(pyre);
+ }
+}
+
+/* heap empty */
+
+int heap8_empty (heap8 *heap)
+{
+ pyre8 *pyre;
+ return head_block_empty(heap, pyre);
+}
+
+int heap16_empty (heap16 *heap)
+{
+ pyre16 *pyre;
+ return head_block_empty(heap, pyre);
+}
+
+int heap32_empty (heap32 *heap)
+{
+ pyre32 *pyre;
+ return head_block_empty(heap, pyre);
+}
+
+int heap64_empty (heap64 *heap)
+{
+ pyre64 *pyre;
+ return head_block_empty(heap, pyre);
+}
+
+/* heap stats */
+
+void heap8_stats (heap8 *heap, mem_info *info, int append)
+{
+ pyre8 *pyre;
+ size_t used, chunks = 0, blocks = 0, singles = 0;
+ if (!append)
+ memset(info, 0, sizeof(mem_info));
+ for (pyre = heap->head; pyre != NULL; pyre = pyre->prev)
+ {
+ ++blocks;
+ chunks += pyre->chunks;
+ used = block_used8(pyre);
+ info->used += used;
+ info->left += pyre->left;
+ if (pyre->chunks == 1 && pyre->left == 0)
+ {
+ ++singles;
+ info->singleused += used;
+ }
+ }
+ info->chunks += chunks;
+ info->blocks += blocks;
+ info->blockghosts += blocks * sizeof(pyre8);
+ info->singles += singles;
+ info->singleghosts += singles * sizeof(pyre8);
+}
+
+void heap16_stats (heap16 *heap, mem_info *info, int append)
+{
+ pyre16 *pyre;
+ size_t used, chunks = 0, blocks = 0, singles = 0;
+ if (!append)
+ memset(info, 0, sizeof(mem_info));
+ for (pyre = heap->head; pyre != NULL; pyre = pyre->prev)
+ {
+ ++blocks;
+ chunks += pyre->chunks;
+ used = block_used16(pyre);
+ info->used += used;
+ info->left += pyre->left;
+ if (pyre->chunks == 1 && pyre->left == 0)
+ {
+ ++singles;
+ info->singleused += used;
+ }
+ }
+ info->chunks += chunks;
+ info->blocks += blocks;
+ info->blockghosts += blocks * sizeof(pyre16);
+ info->singles += singles;
+ info->singleghosts += singles * sizeof(pyre16);
+}
+
+void heap32_stats (heap32 *heap, mem_info *info, int append)
+{
+ pyre32 *pyre;
+ size_t used, chunks = 0, blocks = 0, singles = 0;
+ if (!append)
+ memset(info, 0, sizeof(mem_info));
+ for (pyre = heap->head; pyre != NULL; pyre = pyre->prev)
+ {
+ ++blocks;
+ chunks += pyre->chunks;
+ used = block_used32(pyre);
+ info->used += used;
+ info->left += pyre->left;
+ if (pyre->chunks == 1 && pyre->left == 0)
+ {
+ ++singles;
+ info->singleused += used;
+ }
+ }
+ info->chunks += chunks;
+ info->blocks += blocks;
+ info->blockghosts += blocks * sizeof(pyre32);
+ info->singles += singles;
+ info->singleghosts += singles * sizeof(pyre32);
+}
+
+void heap64_stats (heap64 *heap, mem_info *info, int append)
+{
+ pyre64 *pyre;
+ size_t used, chunks = 0, blocks = 0, singles = 0;
+ if (!append)
+ memset(info, 0, sizeof(mem_info));
+ for (pyre = heap->head; pyre != NULL; pyre = pyre->prev)
+ {
+ ++blocks;
+ chunks += pyre->chunks;
+ used = block_used64(pyre);
+ info->used += used;
+ info->left += pyre->left;
+ if (pyre->chunks == 1 && pyre->left == 0)
+ {
+ ++singles;
+ info->singleused += used;
+ }
+ }
+ info->chunks += chunks;
+ info->blocks += blocks;
+ info->blockghosts += blocks * sizeof(pyre64);
+ info->singles += singles;
+ info->singleghosts += singles * sizeof(pyre64);
+}