summaryrefslogtreecommitdiff
path: root/src/code/TwoHeadArena.c
diff options
context:
space:
mode:
authorAnghelo Carvajal <angheloalf95@gmail.com>2023-03-24 14:38:04 -0300
committerGitHub <noreply@github.com>2023-03-24 14:38:04 -0300
commit147e4fcedca332070ca15dbc1db358ce2d42972c (patch)
tree30577817a17f58de61a3679cb404fa58e922b750 /src/code/TwoHeadArena.c
parentf3d2c56d1deed7194c77909ee41ed5b8ef3ef8a2 (diff)
THA docs (#1177)
* THA docs Co-authored-by: Tharo <17233964+Thar0@users.noreply.github.com> * format * namefixer * yada * remove zero pad comment * Update include/z64.h Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> * Update include/thga.h Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> * namefixer * bss * namefixer --------- Co-authored-by: Tharo <17233964+Thar0@users.noreply.github.com> Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com>
Diffstat (limited to 'src/code/TwoHeadArena.c')
-rw-r--r--src/code/TwoHeadArena.c117
1 files changed, 87 insertions, 30 deletions
diff --git a/src/code/TwoHeadArena.c b/src/code/TwoHeadArena.c
index 83d5be3d1..a476c3d74 100644
--- a/src/code/TwoHeadArena.c
+++ b/src/code/TwoHeadArena.c
@@ -1,79 +1,136 @@
-#include "global.h"
+/**
+ * @file TwoHeadArena.c
+ *
+ * This file implements a simple general purpose double-ended stack allocator.
+ *
+ * A double-ended stack allocator accepts allocations at either the "head" or "tail" of its allotted memory region.
+ * While in general this type of allocator could accept deallocations on the most recently allocated block at either
+ * end, this implementation does not support any individual deallocations; the only provided way to deallocate anything
+ * is to reset the entire arena, deallocating everything. This scheme is most applicable to allocating similar data
+ * with identical lifetime.
+ */
+
+#include "tha.h"
+#include "alignment.h"
+#include "functions.h"
void* THA_GetHead(TwoHeadArena* tha) {
return tha->head;
}
-void THA_SetHead(TwoHeadArena* tha, void* start) {
- tha->head = start;
+void THA_SetHead(TwoHeadArena* tha, void* newHead) {
+ tha->head = newHead;
}
void* THA_GetTail(TwoHeadArena* tha) {
return tha->tail;
}
-void* THA_AllocStart(TwoHeadArena* tha, size_t size) {
+/**
+ * Allocates to the head of the Two Head Arena. The allocation will not have any alignment guarantees.
+ */
+void* THA_AllocHead(TwoHeadArena* tha, size_t size) {
void* start = tha->head;
- tha->head = (u32)tha->head + size;
+ tha->head = (u8*)tha->head + size;
return start;
}
-void* THA_AllocStart1(TwoHeadArena* tha) {
- return THA_AllocStart(tha, 1);
+void* THA_AllocHeadByte(TwoHeadArena* tha) {
+ return THA_AllocHead(tha, 1);
}
-void* THA_AllocEnd(TwoHeadArena* tha, size_t size) {
- u32 mask;
+/**
+ * Allocates to the tail end of the Two Head Arena. The allocation will be aligned based on the size of the allocation.
+ * All allocations of 16 bytes or more will be aligned to 16-bytes. Otherwise, the alignment will be the largest power
+ * of 2 for which the size is a multiple, in order to accommodate the alignment requirements of any data types that can
+ * fit within the allocation.
+ */
+void* THA_AllocTail(TwoHeadArena* tha, size_t size) {
+ uintptr_t mask;
if (size >= 0x10) {
- mask = ~0xF;
+ // Align 0x10 for allocations greater than 0x10
+ mask = ALIGN_MASK(0x10);
} else if (size & 1) {
- mask = -1;
+ // No alignment for odd sizes
+ mask = ALIGN_MASK(1);
} else if (size & 2) {
- mask = ~0x1;
+ // Align 2 for multiples of 2
+ mask = ALIGN_MASK(2);
} else if (size & 4) {
- mask = ~0x3;
+ // Align 4 for multiples of 4
+ mask = ALIGN_MASK(4);
+ } else if (size & 8) {
+ // Align 8 for multiples of 8
+ mask = ALIGN_MASK(8);
} else {
- mask = (size & 8) ? ~0x7 : -1;
+ mask = ALIGN_MASK(1);
}
- tha->tail = (((u32)tha->tail & mask) - size) & mask;
+ tha->tail = (void*)((((uintptr_t)tha->tail & mask) - size) & mask);
return tha->tail;
}
-void* THA_AllocEndAlign16(TwoHeadArena* tha, size_t size) {
- u32 mask = ~0xF;
+/**
+ * Allocates to the tail end of the Two Head Arena with guaranteed 16-byte alignment.
+ */
+void* THA_AllocTailAlign16(TwoHeadArena* tha, size_t size) {
+ uintptr_t mask = ALIGN_MASK(0x10);
- tha->tail = (((u32)tha->tail & mask) - size) & mask;
+ tha->tail = (void*)((((uintptr_t)tha->tail & mask) - size) & mask);
return tha->tail;
}
-void* THA_AllocEndAlign(TwoHeadArena* tha, size_t size, u32 mask) {
- tha->tail = (((u32)tha->tail & mask) - size) & mask;
+/**
+ * Allocates to the tail end of the Two Head Arena using the provided mask to align the allocated region.
+ *
+ * @param tha Arena to allocate to
+ * @param size Size of the allocation
+ * @param mask Mask to use to align the allocated region. To align to n-bytes where n is a power of 2, use the
+ * ALIGN_MASK(n) macro
+ *
+ * @return Pointer to the start of the allocated block
+ */
+void* THA_AllocTailAlign(TwoHeadArena* tha, size_t size, uintptr_t mask) {
+ tha->tail = (void*)((((uintptr_t)tha->tail & mask) - size) & mask);
return tha->tail;
}
-s32 THA_GetSize(TwoHeadArena* tha) {
- return (u32)tha->tail - (u32)tha->head;
+/**
+ * Gets the remaining size of the Two Head Arena
+ *
+ * @return Remaining size. A negative number indicates an overflow.
+ */
+s32 THA_GetRemaining(TwoHeadArena* tha) {
+ return (s32)((u8*)tha->tail - (u8*)tha->head);
}
+/**
+ * @return true if the Two Head Arena has overflowed, false otherwise
+ */
u32 THA_IsCrash(TwoHeadArena* tha) {
- return THA_GetSize(tha) < 0;
+ return THA_GetRemaining(tha) < 0;
}
-void THA_Init(TwoHeadArena* tha) {
- tha->head = tha->bufp;
- tha->tail = (u32)tha->bufp + tha->size;
+void THA_Reset(TwoHeadArena* tha) {
+ tha->head = tha->start;
+ tha->tail = (u8*)tha->start + tha->size;
}
-void THA_Ct(TwoHeadArena* tha, void* ptr, size_t size) {
+/**
+ * Creates a new Two Head Arena at `start` with available size `size`
+ */
+void THA_Init(TwoHeadArena* tha, void* start, size_t size) {
bzero(tha, sizeof(TwoHeadArena));
- tha->bufp = ptr;
+ tha->start = start;
tha->size = size;
- THA_Init(tha);
+ THA_Reset(tha);
}
-void THA_Dt(TwoHeadArena* tha) {
+/**
+ * Destroys the Two Head Arena, no further allocations are possible
+ */
+void THA_Destroy(TwoHeadArena* tha) {
bzero(tha, sizeof(TwoHeadArena));
}