summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2023-10-23 12:47:39 -0400
committerJonathan Bradley <jcb@pikum.xyz>2023-10-23 12:47:39 -0400
commitf400971f58a1c5e43d96e5bdce82d608ad88af3a (patch)
treeba5db54f1d9fe8d527da54663bf7e7aa54c586cb
parent4a61cc1e5ace3e59050d18493806c05487458cfd (diff)
memory manager now handles alignment
-rw-r--r--src/asset-manager.cpp6
-rw-r--r--src/memory.cpp32
-rw-r--r--src/memory.hpp18
3 files changed, 36 insertions, 20 deletions
diff --git a/src/asset-manager.cpp b/src/asset-manager.cpp
index d463cff..5ff25f3 100644
--- a/src/asset-manager.cpp
+++ b/src/asset-manager.cpp
@@ -31,11 +31,11 @@ AssetHandle AM_Register_Inner(const void *src, void *dst, int64_t size, const ch
return AssetHandle{assetHandle_T};
}
-AssetHandle AM_Register(const void *data, int64_t size, const char *key) {
+AssetHandle AM_Register(const void *data, int64_t size, std::size_t alignment, const char *key) {
assert(data != nullptr && "Attempt to register invalid asset data");
assert(data != CAFE_BABE(void) && "Attempt to register invalid asset data");
assert(size != 0 && "Attempt to register asset data of size 0");
- void *target = Pke_New(size);
+ void *target = Pke_New(size, alignment);
return AM_Register_Inner(data, target, size, key);
}
@@ -45,7 +45,7 @@ AssetHandle AM_Register(const char *path) {
throw "failed to open file";
}
auto fileSize = (int64_t)file.tellg();
- void *target = Pke_New(fileSize);
+ void *target = Pke_New(fileSize, alignof(uint64_t));
int64_t pathLen = strlen(path);
auto assetHandle = AM_Register_Inner(nullptr, target, 0, path + (pathLen > 16 ? pathLen - 16 : 0));
diff --git a/src/memory.cpp b/src/memory.cpp
index 793c4d0..538ffd8 100644
--- a/src/memory.cpp
+++ b/src/memory.cpp
@@ -1,6 +1,9 @@
#include "memory.hpp"
+const std::size_t MINIMUM_ALIGNMENT = 1;
+const std::size_t MAXIMUM_ALIGNMENT = 64;
+
struct MemBlock {
char *data;
std::size_t size;
@@ -52,12 +55,16 @@ void DestroyBucket(MemBucket *bkt) {
bkt->transient = false;
}
-void *Pke_New(std::size_t sz, MemBucket *bkt) {
+void *Pke_New(std::size_t sz, std::size_t alignment, MemBucket *bkt) {
MemBlock *blocks = reinterpret_cast<MemBlock *>(bkt->blocks);
+ std::size_t calculatedAlignment = alignment < MINIMUM_ALIGNMENT ? MINIMUM_ALIGNMENT : alignment;
int64_t availBlockIndex = -1;
void *data = nullptr;
for (int64_t i = 0; i <= bkt->lastEmptyBlockIndex; ++i) {
auto blk = blocks[i];
+ std::size_t misalignment = reinterpret_cast<std::size_t>(blk.data) % calculatedAlignment;
+ if (misalignment != 0)
+ continue;
if (blk.size > sz) {
availBlockIndex = i;
break;
@@ -77,24 +84,31 @@ void *Pke_New(std::size_t sz, MemBucket *bkt) {
}
} else {
assert(bkt->head + sz <= bkt->size && "memory bucket specified, but full");
- data = bkt->ptr + bkt->head;
- bkt->head += sz;
+ std::size_t misalignment = reinterpret_cast<std::size_t>(bkt->ptr + bkt->head) % calculatedAlignment;
+ std::size_t padding = calculatedAlignment - misalignment;
+ if (misalignment != 0) {
+ bkt->lastEmptyBlockIndex += 1;
+ blocks[bkt->lastEmptyBlockIndex].data = bkt->ptr + bkt->head;
+ blocks[bkt->lastEmptyBlockIndex].size = padding;
+ }
+ data = bkt->ptr + bkt->head + padding;
+ bkt->head += sz + padding;
}
bkt->allocs++;
return data;
}
-void *Pke_New(std::size_t sz) {
+void *Pke_New(std::size_t sz, std::size_t alignment) {
MemBucket *bkt = nullptr;
for (long i = 0; i < bucketHead; ++i) {
- if (buckets[i].transient == false && buckets[i].size - buckets[i].head > sz) {
+ if (buckets[i].transient == false && buckets[i].size - buckets[i].head > sz + MAXIMUM_ALIGNMENT) {
bkt = &buckets[i];
}
}
if (bkt == nullptr) {
bkt = &buckets[InitNewBucket(DEFAULT_BUCKET_SIZE)];
}
- return Pke_New(sz, bkt);
+ return Pke_New(sz, alignment, bkt);
}
void Pke_Delete(const void *ptr, std::size_t sz, MemBucket *bkt) {
@@ -170,9 +184,11 @@ void Pke_MemoryFlush() {
}
}
-uint64_t Buckets_NewHandle(std::size_t bucketBytes, uint64_t bucketItemCount, uint64_t &bucketIncrementer, uint64_t &bucketCounter, uint64_t &itemCounter, void*& buckets) {
+uint64_t Buckets_NewHandle(std::size_t bucketBytes, std::size_t alignment, uint64_t bucketItemCount, uint64_t &bucketIncrementer, uint64_t &bucketCounter, uint64_t &itemCounter, void*& buckets) {
uint64_t newHandle{itemCounter | bucketCounter};
+ std::size_t calculatedAlignment = alignment < MINIMUM_ALIGNMENT ? MINIMUM_ALIGNMENT : alignment;
+
itemCounter += uint64_t{1ULL << 32};
if (itemCounter > uint64_t{(bucketItemCount - 1) << 32}) {
itemCounter = 0ULL;
@@ -180,7 +196,7 @@ uint64_t Buckets_NewHandle(std::size_t bucketBytes, uint64_t bucketItemCount, ui
}
if (bucketCounter > bucketIncrementer) {
int64_t newIncrement = bucketIncrementer * 1.5;
- char * newBuckets = reinterpret_cast<char *>(Pke_New(bucketBytes * newIncrement));
+ char * newBuckets = reinterpret_cast<char *>(Pke_New(bucketBytes * newIncrement, calculatedAlignment));
std::memcpy(newBuckets, buckets, bucketBytes * bucketIncrementer);
Pke_Delete(buckets, bucketBytes * bucketIncrementer);
buckets = newBuckets;
diff --git a/src/memory.hpp b/src/memory.hpp
index b93890a..b76a72b 100644
--- a/src/memory.hpp
+++ b/src/memory.hpp
@@ -24,8 +24,8 @@ struct BucketContainer {
T *buckets = nullptr;
};
-void *Pke_New(std::size_t sz);
-void *Pke_New(std::size_t sz, MemBucket *bkt);
+void *Pke_New(std::size_t sz, std::size_t alignment);
+void *Pke_New(std::size_t sz, std::size_t alignment, MemBucket *bkt);
void Pke_Delete(const void *ptr, std::size_t sz);
void Pke_Delete(const void *ptr, std::size_t sz, MemBucket *bkt);
void Pke_DebugPrint();
@@ -38,9 +38,9 @@ template <typename T>
inline T *Pke_New(MemBucket *bucket = nullptr) {
void *ptr = nullptr;
if (bucket) {
- ptr = Pke_New(sizeof(T), bucket);
+ ptr = Pke_New(sizeof(T), alignof(T), bucket);
} else {
- ptr = Pke_New(sizeof(T));
+ ptr = Pke_New(sizeof(T), alignof(T));
}
if IS_CONSTRUCTIBLE(T) {
return new (ptr) T{};
@@ -51,9 +51,9 @@ template <typename T>
inline T *Pke_New(long count, MemBucket *bucket = nullptr) {
char *ptr = nullptr;
if (bucket) {
- ptr = static_cast<char *>(Pke_New(sizeof(T) * count, bucket));
+ ptr = static_cast<char *>(Pke_New(sizeof(T) * count, alignof(T), bucket));
} else {
- ptr = static_cast<char *>(Pke_New(sizeof(T) * count));
+ ptr = static_cast<char *>(Pke_New(sizeof(T) * count, alignof(T)));
}
if IS_CONSTRUCTIBLE(T) {
for (long i = 0; i < count; ++i) {
@@ -94,18 +94,18 @@ void Buckets_Init(BucketContainer<T, CT> &bktContainer) {
bktContainer.buckets = Pke_New<T>(bktContainer.incrementer);
}
-uint64_t Buckets_NewHandle(std::size_t bucketBytes, uint64_t bucketItemCount, uint64_t &bucketIncrementer, uint64_t &bucketCounter, uint64_t &itemCounter, void*& buckets);
+uint64_t Buckets_NewHandle(std::size_t bucketBytes, std::size_t alignment, uint64_t bucketItemCount, uint64_t &bucketIncrementer, uint64_t &bucketCounter, uint64_t &itemCounter, void*& buckets);
template <typename T> inline uint64_t Buckets_NewHandle(uint64_t bucketItemCount, uint64_t &bucketIncrementer, uint64_t &bucketCounter, uint64_t &itemCounter, T*& buckets) {
void *ptr = reinterpret_cast<void *>(buckets);
- uint64_t handle = Buckets_NewHandle(sizeof(T), bucketItemCount, bucketIncrementer, bucketCounter, itemCounter, ptr);
+ uint64_t handle = Buckets_NewHandle(sizeof(T), alignof(T), bucketItemCount, bucketIncrementer, bucketCounter, itemCounter, ptr);
buckets = reinterpret_cast<T *>(ptr);
return handle;
}
template <typename T, typename CT>
inline CT Buckets_NewHandle(uint64_t maxBucketItemCount, BucketContainer<T, CT> &bktContainer) {
- return Buckets_NewHandle(maxBucketItemCount, bktContainer.incrementer, bktContainer.bucketCounter, bktContainer.itemCounter, bktContainer.buckets);
+ return Buckets_NewHandle<T>(maxBucketItemCount, bktContainer.incrementer, bktContainer.bucketCounter, bktContainer.itemCounter, bktContainer.buckets);
}
static inline constexpr uint64_t Buckets_GetBucketIndex(uint64_t handle) {