Originally the use of a weak symbol was to provide a fallback for
non-inline supporting compilers. However all compilers (we care about)
support inline keyword (which was not known at the original time of the
work). Furthermore GCC have already worked through the solution and make
it easy to implement.
The use of __GNUC_STDC_INLINE__ pattern in this way manages the fallback
and emits a hard symbol this can be tested with:
CFLAGS="-g" ./configure; make; nm */lib*.o | grep freeMagic1
CFLAGS="-O3" ./configure; make; nm */lib*.o | grep freeMagic1
A hard 'T' symbol is emitted (to provide fallback) with all builds, but
in the -O3 all usage is inlined. So an individual file can decide to
inline or not at the occasion (compile time options) allows.
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.
Tcl_Alloc() and Tcl_Free() because Tcl_Alloc() uses (unsigned int)
for the argument type and therefore limits memory allocations to
what can fit in 32 bits. Using the system malloc(size_t) should not
cause any issues.
not useful so long as Tcl_Alloc() has (unsigned int) for an argument.
The more important investigation is probably to determine if there is
a way to keep csa2_list from growing to absurdly large sizes on
connectivity checks.