aboutsummaryrefslogtreecommitdiffstats
path: root/common/almalloc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/almalloc.cpp')
-rw-r--r--common/almalloc.cpp67
1 files changed, 67 insertions, 0 deletions
diff --git a/common/almalloc.cpp b/common/almalloc.cpp
new file mode 100644
index 00000000..842fb400
--- /dev/null
+++ b/common/almalloc.cpp
@@ -0,0 +1,67 @@
+
+#include "config.h"
+
+#include "almalloc.h"
+
+#include <cassert>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+
+#define ALIGNED_ALLOC_AVAILABLE (__STDC_VERSION__ >= 201112L || __cplusplus >= 201703L)
+
+void *al_malloc(size_t alignment, size_t size)
+{
+ assert((alignment & (alignment-1)) == 0);
+ alignment = std::max(alignment, alignof(std::max_align_t));
+
+#if ALIGNED_ALLOC_AVAILABLE
+ size = (size+(alignment-1))&~(alignment-1);
+ return aligned_alloc(alignment, size);
+#elif defined(HAVE_POSIX_MEMALIGN)
+ void *ret;
+ if(posix_memalign(&ret, alignment, size) == 0)
+ return ret;
+ return nullptr;
+#elif defined(HAVE__ALIGNED_MALLOC)
+ return _aligned_malloc(size, alignment);
+#else
+ auto *ret = static_cast<char*>(malloc(size+alignment));
+ if(ret != nullptr)
+ {
+ *(ret++) = 0x00;
+ while((reinterpret_cast<uintptr_t>(ret)&(alignment-1)) != 0)
+ *(ret++) = 0x55;
+ }
+ return ret;
+#endif
+}
+
+void *al_calloc(size_t alignment, size_t size)
+{
+ void *ret = al_malloc(alignment, size);
+ if(ret) memset(ret, 0, size);
+ return ret;
+}
+
+void al_free(void *ptr) noexcept
+{
+#if ALIGNED_ALLOC_AVAILABLE || defined(HAVE_POSIX_MEMALIGN)
+ free(ptr);
+#elif defined(HAVE__ALIGNED_MALLOC)
+ _aligned_free(ptr);
+#else
+ if(ptr != nullptr)
+ {
+ auto *finder = static_cast<char*>(ptr);
+ do {
+ --finder;
+ } while(*finder == 0x55);
+ free(finder);
+ }
+#endif
+}