1 #include <bz/memory/arena_internal.h>
3 #include <bz/memory/allocator.h>
4 #include <bz/types/identifier_internal.h>
7 #include <string.h> // memset... :rolleyes:
9 /*struct BZExpandedPointer {
10 BZMemoryArenaID arena;
13 typedef struct BZExpandedPointer BZExpandedPointer;*/
15 //const size_t kMaxUserArenas = 32;
16 #define kMaxUserArenas 32 // FIXME
17 static BZMemoryArena userArenas
[kMaxUserArenas
];
18 static size_t nextUserArena
= 0;
20 BZMemoryArenaID kBZSystemMemoryArena
= &userArenas
[0];
22 static size_t allocateSize(size_t size
) {
23 size_t alignment
= alignof(max_align_t
); // FIXME, check this alignment stuff...
24 size_t alignmentPadding
= (alignment
- (size
% alignment
)) % alignment
;
25 size_t fullSize
= size
+ alignmentPadding
;// + sizeof(BZExpandedPointer);
29 BZMemoryArenaID
bzMemoryArenaCreate(BZMemoryArenaID hostArena
, size_t size
, const char *nameFmt
, ...) {
30 bzAssert(size
== allocateSize(size
));
31 if (nextUserArena
< kMaxUserArenas
) {
32 BZMemoryArenaID arena
= bzMemoryArenaAllocate(&userArenas
[++nextUserArena
], hostArena
, size
);
33 bzInsertIdentifier(((char *)arena
->identifier
), nameFmt
);
36 bzError("Too many arenas");
41 void bzMemoryArenaReset(BZMemoryArenaID arena
) {
42 bzMemoryArenaSetup(arena
, arena
->memory
, arena
->maxSize
, arena
->zeroOut
);
45 void bzMemoryArenaResetTmp(BZMemoryArenaID arena
) {
47 memset(&arena
->memory
[arena
->maxSize
- arena
->allocationOffsetTop
], 0, arena
->allocationOffsetTop
);
49 arena
->allocationOffsetTop
= 0;
52 BZMemoryArenaID
bzMemoryArenaSetup(BZMemoryArena
*arenaOut
, void *memory
, size_t size
, bool zeroOut
) {
53 arenaOut
->maxSize
= size
;
54 arenaOut
->memory
= memory
;
55 arenaOut
->numWatermarks
= 0;
56 arenaOut
->zeroOut
= zeroOut
;
58 arenaOut
->allocationOffsetBottom
= 0;
59 arenaOut
->allocationOffsetTop
= 0;
61 if (arenaOut
->zeroOut
) {
62 // We're gonna interop with C++, so we really need to do this.
63 memset(memory
, 0, size
);
69 BZMemoryArenaID
bzMemoryArenaAllocate(BZMemoryArena
*arenaOut
, BZMemoryArenaID arenaFrom
, size_t size
) {
70 void *memory
= bzMemoryAlloc(arenaFrom
, size
);
71 return bzMemoryArenaSetup(arenaOut
, memory
, size
, true);
74 void bzMemoryArenaPushWatermark(BZMemoryArenaID arena
) {
75 if (arena
->numWatermarks
< MAX_WATERMARKS
) {
76 arena
->watermarks
[arena
->numWatermarks
++] = arena
->allocationOffsetBottom
;
78 bzError("Watermarked too many times!!");
82 void bzMemoryArenaPopWatermark(BZMemoryArenaID arena
) {
83 if (arena
->numWatermarks
> 0) {
84 size_t lastAllocation
= arena
->allocationOffsetBottom
;
85 arena
->allocationOffsetBottom
= arena
->watermarks
[--arena
->numWatermarks
];
88 // We're gonna interop with C++, so we really need to do this.
89 // Zero out anything that got used.
90 memset(&arena
->memory
[arena
->allocationOffsetBottom
], 0, lastAllocation
- arena
->allocationOffsetBottom
);
93 bzError("Watermarked too many times!!");
97 void *_bzMemoryAlloc(BZMemoryArenaID arena
, size_t size
, const char *filename
, size_t lineNumber
) {
98 bzAssertMessage(arena
!= NULL
, "No memory arena");
100 size_t fullSize
= allocateSize(size
);
103 if (arena
== kBZSystemMemoryArena
) {
104 ptr
= bzSystemAllocate(fullSize
);
105 // if (arena->zeroOut) {
106 memset(ptr
, 0, fullSize
); // Just do this one...
108 } else if (arena
->allocationOffsetBottom
+ fullSize
<= arena
->maxSize
- arena
->allocationOffsetTop
) {
109 ptr
= &arena
->memory
[arena
->allocationOffsetBottom
];
110 arena
->allocationOffsetBottom
+= fullSize
;
113 bzAssertMessage(ptr
!= NULL
, "Arena '%s' is out of memory, failed %s:%d", arena
->identifier
, filename
, lineNumber
);
118 void *_bzMemoryAllocTmp(BZMemoryArenaID arena
, size_t size
, const char *filename
, size_t lineNumber
) {
119 bzAssertMessage(arena
!= NULL
, "No memory arena");
121 size_t fullSize
= allocateSize(size
);
124 if (arena
== kBZSystemMemoryArena
) {
125 ptr
= bzSystemAllocateStack(fullSize
);
126 } else if (arena
->maxSize
- arena
->allocationOffsetTop
- fullSize
>= arena
->allocationOffsetBottom
) {
127 arena
->allocationOffsetTop
+= fullSize
;
128 ptr
= &arena
->memory
[arena
->maxSize
- arena
->allocationOffsetTop
];
131 bzAssertMessage(ptr
!= NULL
, "Arena is out of memory, failed %s:%d", filename
, lineNumber
);
134 } // FIXME, this won't work if you pass arena to other places, need more watermarking??....
137 //void bzMemoryFree(void *p) {
139 // ptr -= sizeof(BZExpandedPointer);
141 // if (*(BZMemoryArenaID *)ptr == kBZSystemMemoryArena) {
144 // bzLog("Asked to free arena memory that cannot be");