mirror of
https://github.com/zeldaret/oot.git
synced 2025-07-06 16:04:35 +00:00
TwoHeadArena and TwoHeadGfxArena docs (#1349)
* TwoHeadArena and TwoHeadGfxArena docs, ALIGNOF macro * AllocStart -> AllocHead , AllocEnd -> AllocTail * Format * Suggested changes * Fix * Further suggested changes
This commit is contained in:
parent
c165ed015c
commit
6d5287ff12
13 changed files with 302 additions and 170 deletions
|
@ -1,140 +1,135 @@
|
|||
/**
|
||||
* @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 "global.h"
|
||||
|
||||
void THGA_Ct(TwoHeadGfxArena* thga, Gfx* start, u32 size) {
|
||||
THA_Ct((TwoHeadArena*)thga, start, size);
|
||||
}
|
||||
|
||||
void THGA_Dt(TwoHeadGfxArena* thga) {
|
||||
THA_Dt((TwoHeadArena*)thga);
|
||||
}
|
||||
|
||||
u32 THGA_IsCrash(TwoHeadGfxArena* thga) {
|
||||
return THA_IsCrash((TwoHeadArena*)thga);
|
||||
}
|
||||
|
||||
void THGA_Init(TwoHeadGfxArena* thga) {
|
||||
THA_Init((TwoHeadArena*)thga);
|
||||
}
|
||||
|
||||
s32 THGA_GetSize(TwoHeadGfxArena* thga) {
|
||||
return THA_GetSize((TwoHeadArena*)thga);
|
||||
}
|
||||
|
||||
Gfx* THGA_GetHead(TwoHeadGfxArena* thga) {
|
||||
return THA_GetHead((TwoHeadArena*)thga);
|
||||
}
|
||||
|
||||
void THGA_SetHead(TwoHeadGfxArena* thga, Gfx* start) {
|
||||
THA_SetHead((TwoHeadArena*)thga, start);
|
||||
}
|
||||
|
||||
Gfx* THGA_GetTail(TwoHeadGfxArena* thga) {
|
||||
return THA_GetTail((TwoHeadArena*)thga);
|
||||
}
|
||||
|
||||
Gfx* THGA_AllocStartArray8(TwoHeadGfxArena* thga, u32 count) {
|
||||
return THA_AllocStart((TwoHeadArena*)thga, count * 8);
|
||||
}
|
||||
|
||||
Gfx* THGA_AllocStart8(TwoHeadGfxArena* thga) {
|
||||
return THGA_AllocStartArray8(thga, 1);
|
||||
}
|
||||
|
||||
Gfx* THGA_AllocStart8Wrapper(TwoHeadGfxArena* thga) {
|
||||
return THGA_AllocStart8(thga);
|
||||
}
|
||||
|
||||
Gfx* THGA_AllocEnd(TwoHeadGfxArena* thga, u32 size) {
|
||||
return THA_AllocEnd((TwoHeadArena*)thga, size);
|
||||
}
|
||||
|
||||
Gfx* THGA_AllocEndArray64(TwoHeadGfxArena* thga, u32 count) {
|
||||
return THGA_AllocEnd(thga, count * 0x40);
|
||||
}
|
||||
|
||||
Gfx* THGA_AllocEnd64(TwoHeadGfxArena* thga) {
|
||||
return THGA_AllocEnd(thga, 0x40);
|
||||
}
|
||||
|
||||
Gfx* THGA_AllocEndArray16(TwoHeadGfxArena* thga, u32 count) {
|
||||
return THGA_AllocEnd(thga, count * 0x10);
|
||||
}
|
||||
|
||||
Gfx* THGA_AllocEnd16(TwoHeadGfxArena* thga) {
|
||||
return THGA_AllocEnd(thga, 0x10);
|
||||
}
|
||||
|
||||
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, u32 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 = (void*)((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, u32 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 == 8) {
|
||||
mask = ~7;
|
||||
// Align 8 for multiples of 8
|
||||
mask = ALIGN_MASK(8);
|
||||
} else if (size == 4 || size == 12) {
|
||||
mask = ~3;
|
||||
// Align 4 for multiples of 4
|
||||
mask = ALIGN_MASK(4);
|
||||
} else if (size == 2 || size == 6 || size == 10 || size == 12 || size == 14) {
|
||||
mask = ~1;
|
||||
// Align 2 for multiples of 2
|
||||
mask = ALIGN_MASK(2);
|
||||
} else if (size >= 0x10) {
|
||||
// Align 0x10 for allocations greater than 0x10
|
||||
mask = ALIGN_MASK(0x10);
|
||||
} else {
|
||||
mask = (size >= 0x10) ? ~0xF : 0;
|
||||
//! @bug if size is less than 16 and odd the computation below will give NULL. The mask for this case would be
|
||||
//! more sensible as ~0, for no extra alignment
|
||||
mask = 0;
|
||||
}
|
||||
|
||||
tha->tail = (void*)((((u32)tha->tail & mask) - size) & mask);
|
||||
tha->tail = (void*)((((uintptr_t)tha->tail & mask) - size) & mask);
|
||||
return tha->tail;
|
||||
}
|
||||
|
||||
void* THA_AllocEndAlign16(TwoHeadArena* tha, u32 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 = (void*)((((u32)tha->tail & mask) - size) & (u32)(u64)mask);
|
||||
tha->tail = (void*)((((uintptr_t)tha->tail & mask) - size) & (uintptr_t)(u64)mask);
|
||||
return tha->tail;
|
||||
}
|
||||
|
||||
void* THA_AllocEndAlign(TwoHeadArena* tha, u32 size, u32 mask) {
|
||||
tha->tail = (void*)((((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 = (void*)((u32)tha->bufp + tha->size);
|
||||
/**
|
||||
* Resets the head and tail positions of the Two Head Arena, all prior allocations are effectively considered free
|
||||
* as any new allocations will begin to overwrite them.
|
||||
*/
|
||||
void THA_Reset(TwoHeadArena* tha) {
|
||||
tha->head = tha->start;
|
||||
tha->tail = (u8*)tha->start + tha->size;
|
||||
}
|
||||
|
||||
void THA_Ct(TwoHeadArena* tha, void* ptr, u32 size) {
|
||||
tha->bufp = ptr;
|
||||
/**
|
||||
* Creates a new Two Head Arena at `start` with available size `size`
|
||||
*/
|
||||
void THA_Init(TwoHeadArena* tha, void* start, size_t size) {
|
||||
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));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue