MEM: support overaligned types in MEM_cnew_array
This is similar to the recent change for `MEM_cnew`: 60a3d85b88.
A new function called `MEM_calloc_arrayN_aligned` is added that is used by both `cnew` functions now.
Pull Request: https://projects.blender.org/blender/blender/pulls/120632
This commit is contained in:
@@ -134,6 +134,16 @@ extern void *(*MEM_mallocN_aligned)(size_t len,
|
||||
const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(3);
|
||||
|
||||
/**
|
||||
* Allocate an aligned block of memory that is initialized with zeros.
|
||||
*/
|
||||
extern void *(*MEM_calloc_arrayN_aligned)(
|
||||
size_t len,
|
||||
size_t size,
|
||||
size_t alignment,
|
||||
const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1, 2)
|
||||
ATTR_NONNULL(4);
|
||||
|
||||
/**
|
||||
* Print a list of the names and sizes of all allocated memory
|
||||
* blocks. as a python dict for easy investigation.
|
||||
@@ -311,14 +321,7 @@ template<typename T> inline void MEM_delete(const T *ptr)
|
||||
template<typename T> inline T *MEM_cnew(const char *allocation_name)
|
||||
{
|
||||
static_assert(std::is_trivial_v<T>, "For non-trivial types, MEM_new should be used.");
|
||||
if (alignof(T) <= MEM_MIN_CPP_ALIGNMENT) {
|
||||
return static_cast<T *>(MEM_callocN(sizeof(T), allocation_name));
|
||||
}
|
||||
void *ptr = MEM_mallocN_aligned(sizeof(T), alignof(T), allocation_name);
|
||||
if (ptr) {
|
||||
memset(ptr, 0, sizeof(T));
|
||||
}
|
||||
return static_cast<T *>(ptr);
|
||||
return static_cast<T *>(MEM_calloc_arrayN_aligned(1, sizeof(T), alignof(T), allocation_name));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,7 +330,8 @@ template<typename T> inline T *MEM_cnew(const char *allocation_name)
|
||||
template<typename T> inline T *MEM_cnew_array(const size_t length, const char *allocation_name)
|
||||
{
|
||||
static_assert(std::is_trivial_v<T>, "For non-trivial types, MEM_new should be used.");
|
||||
return static_cast<T *>(MEM_calloc_arrayN(length, sizeof(T), allocation_name));
|
||||
return static_cast<T *>(
|
||||
MEM_calloc_arrayN_aligned(length, sizeof(T), alignof(T), allocation_name));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,6 +38,10 @@ void *(*MEM_malloc_arrayN)(size_t len, size_t size, const char *str) = MEM_lockf
|
||||
void *(*MEM_mallocN_aligned)(size_t len,
|
||||
size_t alignment,
|
||||
const char *str) = MEM_lockfree_mallocN_aligned;
|
||||
void *(*MEM_calloc_arrayN_aligned)(size_t len,
|
||||
size_t size,
|
||||
size_t alignment,
|
||||
const char *str) = MEM_lockfree_calloc_arrayN_aligned;
|
||||
void (*MEM_printmemlist_pydict)(void) = MEM_lockfree_printmemlist_pydict;
|
||||
void (*MEM_printmemlist)(void) = MEM_lockfree_printmemlist;
|
||||
void (*MEM_callbackmemlist)(void (*func)(void *)) = MEM_lockfree_callbackmemlist;
|
||||
@@ -120,6 +124,7 @@ void MEM_use_lockfree_allocator(void)
|
||||
MEM_mallocN = MEM_lockfree_mallocN;
|
||||
MEM_malloc_arrayN = MEM_lockfree_malloc_arrayN;
|
||||
MEM_mallocN_aligned = MEM_lockfree_mallocN_aligned;
|
||||
MEM_calloc_arrayN_aligned = MEM_lockfree_calloc_arrayN_aligned;
|
||||
MEM_printmemlist_pydict = MEM_lockfree_printmemlist_pydict;
|
||||
MEM_printmemlist = MEM_lockfree_printmemlist;
|
||||
MEM_callbackmemlist = MEM_lockfree_callbackmemlist;
|
||||
@@ -154,6 +159,7 @@ void MEM_use_guarded_allocator(void)
|
||||
MEM_mallocN = MEM_guarded_mallocN;
|
||||
MEM_malloc_arrayN = MEM_guarded_malloc_arrayN;
|
||||
MEM_mallocN_aligned = MEM_guarded_mallocN_aligned;
|
||||
MEM_calloc_arrayN_aligned = MEM_guarded_calloc_arrayN_aligned;
|
||||
MEM_printmemlist_pydict = MEM_guarded_printmemlist_pydict;
|
||||
MEM_printmemlist = MEM_guarded_printmemlist;
|
||||
MEM_callbackmemlist = MEM_guarded_callbackmemlist;
|
||||
|
||||
@@ -619,6 +619,36 @@ void *MEM_guarded_calloc_arrayN(size_t len, size_t size, const char *str)
|
||||
return MEM_guarded_callocN(total_size, str);
|
||||
}
|
||||
|
||||
void *MEM_guarded_calloc_arrayN_aligned(const size_t len,
|
||||
const size_t size,
|
||||
const size_t alignment,
|
||||
const char *str)
|
||||
{
|
||||
size_t bytes_num;
|
||||
if (UNLIKELY(!MEM_size_safe_multiply(len, size, &bytes_num))) {
|
||||
print_error(
|
||||
"Calloc array aborted due to integer overflow: "
|
||||
"len=" SIZET_FORMAT "x" SIZET_FORMAT " in %s, total " SIZET_FORMAT "\n",
|
||||
SIZET_ARG(len),
|
||||
SIZET_ARG(size),
|
||||
str,
|
||||
mem_in_use);
|
||||
abort();
|
||||
return nullptr;
|
||||
}
|
||||
if (alignment <= MEM_MIN_CPP_ALIGNMENT) {
|
||||
return MEM_callocN(bytes_num, str);
|
||||
}
|
||||
/* There is no lower level #calloc with an alignment parameter, so we have to fallback to using
|
||||
* #memset unfortunately. */
|
||||
void *ptr = MEM_mallocN_aligned(bytes_num, alignment, str);
|
||||
if (!ptr) {
|
||||
return nullptr;
|
||||
}
|
||||
memset(ptr, 0, bytes_num);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Memory statistics print */
|
||||
typedef struct MemPrintBlock {
|
||||
const char *name;
|
||||
|
||||
@@ -155,6 +155,11 @@ void *MEM_lockfree_mallocN_aligned(size_t len,
|
||||
size_t alignment,
|
||||
const char *str) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(3);
|
||||
void *MEM_lockfree_calloc_arrayN_aligned(size_t len,
|
||||
size_t size,
|
||||
size_t alignment,
|
||||
const char *str) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1, 2) ATTR_NONNULL(4);
|
||||
void MEM_lockfree_printmemlist_pydict(void);
|
||||
void MEM_lockfree_printmemlist(void);
|
||||
void MEM_lockfree_callbackmemlist(void (*func)(void *));
|
||||
@@ -202,6 +207,8 @@ void *MEM_guarded_mallocN_aligned(size_t len,
|
||||
size_t alignment,
|
||||
const char *str) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(3);
|
||||
void *MEM_guarded_calloc_arrayN_aligned(size_t len, size_t size, size_t alignment, const char *str)
|
||||
ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1, 2) ATTR_NONNULL(4);
|
||||
void MEM_guarded_printmemlist_pydict(void);
|
||||
void MEM_guarded_printmemlist(void);
|
||||
void MEM_guarded_callbackmemlist(void (*func)(void *));
|
||||
|
||||
@@ -371,6 +371,36 @@ void *MEM_lockfree_mallocN_aligned(size_t len, size_t alignment, const char *str
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void *MEM_lockfree_calloc_arrayN_aligned(const size_t len,
|
||||
const size_t size,
|
||||
const size_t alignment,
|
||||
const char *str)
|
||||
{
|
||||
size_t bytes_num;
|
||||
if (UNLIKELY(!MEM_size_safe_multiply(len, size, &bytes_num))) {
|
||||
print_error(
|
||||
"Calloc array aborted due to integer overflow: "
|
||||
"len=" SIZET_FORMAT "x" SIZET_FORMAT " in %s, total " SIZET_FORMAT "\n",
|
||||
SIZET_ARG(len),
|
||||
SIZET_ARG(size),
|
||||
str,
|
||||
memory_usage_current());
|
||||
abort();
|
||||
return nullptr;
|
||||
}
|
||||
if (alignment <= MEM_MIN_CPP_ALIGNMENT) {
|
||||
return MEM_callocN(bytes_num, str);
|
||||
}
|
||||
/* There is no lower level #calloc with an alignment parameter, so we have to fallback to using
|
||||
* #memset unfortunately. */
|
||||
void *ptr = MEM_mallocN_aligned(bytes_num, alignment, str);
|
||||
if (!ptr) {
|
||||
return nullptr;
|
||||
}
|
||||
memset(ptr, 0, bytes_num);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void MEM_lockfree_printmemlist_pydict() {}
|
||||
|
||||
void MEM_lockfree_printmemlist() {}
|
||||
|
||||
Reference in New Issue
Block a user