mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-08-28 17:15:13 +02:00
SUPPORT_DIRECT_MALLOC and SUPPORT_REMOVE_MALLOC_LEGACY
This supports three build modes: No additional -D options, default legacy mode -DSUPPORT_DIRECT_MALLOC, magic will use direct calls to libc malloc/free and will leave in place the symbols now renamed as mallocMagicLegacy() freeMagicLegacy() and callocMagicLegacy(). -DSUPPORT_DIRECT_MALLOC -DSUPPORT_REMOVE_MALLOC_LEGACY as above but will remove the three legacy functions from the binary to provide assurance they can not be used. The system malloc is thread-safe the legacy magic malloc has a global deferred free pointer and the mmap() allocate has a free-list that is not thread-safe making use of free not thread-safe. This could of course be improved with the use of atomic_compare_and_exchange operations but for what gain ? Then there is the additional function call overhead (of the indirection) and a few tests/branches inserted into a commonly used code paths around memory allocation, it hides the call site of the malloc/free usage from the compiler which maybe have special optimization cases. The existing malloc/free makes static code analysis around memory allocation more problematic, also use of runtime analysers will operate better with a fail-fast to bad memory usage.
This commit is contained in:
committed by
R. Timothy Edwards
parent
97134848ab
commit
ef419258ab
+90
-3
@@ -22,8 +22,95 @@
|
||||
#ifndef _MAGIC__UTILS__MALLOC_H
|
||||
#define _MAGIC__UTILS__MALLOC_H
|
||||
|
||||
extern void *mallocMagic(size_t);
|
||||
extern void *callocMagic(size_t);
|
||||
extern void freeMagic(void *);
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
/* build time configuration check */
|
||||
#if (!defined(SUPPORT_DIRECT_MALLOC) && defined(SUPPORT_REMOVE_MALLOC_LEGACY))
|
||||
#error "ERROR: Unspported build configuration SUPPORT_REMOVE_MALLOC_LEGACY is defined but SUPPORT_DIRECT_MALLOC is undefined"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SUPPORT_DIRECT_MALLOC
|
||||
|
||||
#define mallocMagic malloc
|
||||
#define callocMagic calloc
|
||||
#define freeMagic free
|
||||
|
||||
#else
|
||||
|
||||
extern void *mallocMagicLegacy(size_t);
|
||||
#define mallocMagic(size) mallocMagicLegacy(size)
|
||||
|
||||
/* renamed like this, so there is no performance loss if the byte count
|
||||
* can be computed at compile time.
|
||||
*/
|
||||
extern void *callocMagicLegacy(size_t);
|
||||
#define callocMagic(nmemb, size) callocMagicLegacy((nmemb) * (size))
|
||||
|
||||
extern void freeMagicLegacy(void *);
|
||||
#define freeMagic(ptr) freeMagicLegacy(ptr)
|
||||
|
||||
#endif /* SUPPORT_DIRECT_MALLOC */
|
||||
|
||||
|
||||
typedef void* free_magic1_t;
|
||||
|
||||
/* TODO this should be moved to autoconf/build/toolchain detection, this does exist
|
||||
* in autoconf and in another changeset, so I come back and fixup/remove this later.
|
||||
*/
|
||||
#if (defined(__STDC__) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))
|
||||
/* C99 or later */
|
||||
#ifndef __inline__
|
||||
/* you'd have thought on linux this was enabled already, TODO check bplane module inlines */
|
||||
#define __inline__ inline
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (!defined(_MAGIC__UTILS__MALLOC_H__NOINLINE) && defined(__inline__))
|
||||
|
||||
/* TODO this (__extern_inline__) should be moved to autoconf/build/toolchain detection */
|
||||
#define __extern_inline__ inline
|
||||
|
||||
/*
|
||||
* NOTICE: inline form, keep in sync with malloc.c copied
|
||||
*/
|
||||
__extern_inline__ free_magic1_t freeMagic1_init() {
|
||||
return NULL;
|
||||
}
|
||||
__extern_inline__ void freeMagic1(free_magic1_t* m1, void* ptr) {
|
||||
if(*m1) /* this if() is here to help inliner remove the call to free() when it can */
|
||||
{
|
||||
#if (defined(SUPPORT_DIRECT_MALLOC) || defined(SUPPORT_REMOVE_MALLOC_LEGACY))
|
||||
free(*m1); /* no need for NULL check with free() */
|
||||
#else
|
||||
freeMagicLegacy(*m1);
|
||||
#endif
|
||||
}
|
||||
*m1 = ptr;
|
||||
}
|
||||
__extern_inline__ void freeMagic1_end(free_magic1_t* m1) {
|
||||
if(*m1) /* this if() is here to help inliner remove the call to free() when it can */
|
||||
{
|
||||
#if (defined(SUPPORT_DIRECT_MALLOC) || defined(SUPPORT_REMOVE_MALLOC_LEGACY))
|
||||
free(*m1); /* no need for NULL check with free() */
|
||||
#else
|
||||
freeMagicLegacy(*m1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define freeMagic1_init() freeMagic1_init_func()
|
||||
#define freeMagic1(m1, ptr) freeMagic1_func((m1), (ptr))
|
||||
#define freeMagic1_end(m1) freeMagic1_end_func((m1))
|
||||
|
||||
#endif /* !_MAGIC__UTILS__MALLOC_H__NOINLINE && __inline__ */
|
||||
|
||||
/* we'll emit a function call interface just in case a platform won't inline and we can redirect */
|
||||
extern free_magic1_t freeMagic1_init_func(void);
|
||||
extern void freeMagic1_func(free_magic1_t* m1, void* ptr);
|
||||
extern void freeMagic1_end_func(free_magic1_t* m1);
|
||||
|
||||
#endif /* _MAGIC__UTILS__MALLOC_H */
|
||||
|
||||
Reference in New Issue
Block a user