From cdb2c0e02fc303fd56aa525ef63eb71136e62b2d Mon Sep 17 00:00:00 2001 From: Kevin Svetlitski Date: Fri, 14 Jul 2023 13:14:06 -0700 Subject: [PATCH] Implement C23's `free_sized` and `free_aligned_sized` [N2699 - Sized Memory Deallocation](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2699.htm) introduced two new functions which were incorporated into the C23 standard, `free_sized` and `free_aligned_sized`. Both already have analogues in Jemalloc, all we are doing here is adding the appropriate wrappers. --- configure.ac | 12 +++++- doc/jemalloc.xml.in | 42 +++++++++++++++++++ .../internal/jemalloc_internal_defs.h.in | 2 + include/jemalloc/jemalloc_protos.h.in | 3 ++ src/jemalloc.c | 17 ++++++++ 5 files changed, 75 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 687b221c..f820d14a 100644 --- a/configure.ac +++ b/configure.ac @@ -1105,7 +1105,7 @@ AC_ARG_WITH([export], fi] ) -public_syms="aligned_alloc calloc dallocx free mallctl mallctlbymib mallctlnametomib malloc malloc_conf malloc_conf_2_conf_harder malloc_message malloc_stats_print malloc_usable_size mallocx smallocx_${jemalloc_version_gid} nallocx posix_memalign rallocx realloc sallocx sdallocx xallocx" +public_syms="aligned_alloc calloc dallocx free free_sized free_aligned_sized mallctl mallctlbymib mallctlnametomib malloc malloc_conf malloc_conf_2_conf_harder malloc_message malloc_stats_print malloc_usable_size mallocx smallocx_${jemalloc_version_gid} nallocx posix_memalign rallocx realloc sallocx sdallocx xallocx" dnl Check for additional platform-specific public API functions. AC_CHECK_FUNC([memalign], [AC_DEFINE([JEMALLOC_OVERRIDE_MEMALIGN], [ ], [ ]) @@ -1129,6 +1129,16 @@ if test "x${JEMALLOC_PREFIX}" = "x" ; then AC_CHECK_FUNC([__libc_free], [AC_DEFINE([JEMALLOC_OVERRIDE___LIBC_FREE], [ ], [ ]) wrap_syms="${wrap_syms} __libc_free"]) + dnl __libc_free_sized and __libc_free_aligned_sized are here speculatively + dnl under the assumption that glibc will eventually define symbols with these + dnl names. In the event glibc chooses different names for these symbols, + dnl these will need to be amended to match. + AC_CHECK_FUNC([__libc_free_sized], + [AC_DEFINE([JEMALLOC_OVERRIDE___LIBC_FREE_SIZED], [ ], [ ]) + wrap_syms="${wrap_syms} __libc_free_sized"]) + AC_CHECK_FUNC([__libc_free_aligned_sized], + [AC_DEFINE([JEMALLOC_OVERRIDE___LIBC_FREE_ALIGNED_SIZED], [ ], [ ]) + wrap_syms="${wrap_syms} __libc_free_aligned_sized"]) AC_CHECK_FUNC([__libc_malloc], [AC_DEFINE([JEMALLOC_OVERRIDE___LIBC_MALLOC], [ ], [ ]) wrap_syms="${wrap_syms} __libc_malloc"]) diff --git a/doc/jemalloc.xml.in b/doc/jemalloc.xml.in index 98f86f95..bdebd433 100644 --- a/doc/jemalloc.xml.in +++ b/doc/jemalloc.xml.in @@ -33,6 +33,8 @@ aligned_alloc realloc free + free_sized + free_aligned_sized mallocx rallocx xallocx @@ -89,6 +91,17 @@ void free void *ptr + + void free_sized + void *ptr + size_t size + + + void free_aligned_sized + void *ptr + size_t alignment + size_t size + Non-standard API @@ -227,6 +240,17 @@ allocated memory referenced by ptr to be made available for future allocations. If ptr is NULL, no action occurs. + + The free_sized() function is an extension of + free() with a size parameter + to allow the caller to pass in the allocation size as an optimization. + + + The free_aligned_sized() function accepts a + ptr which was allocated with a requested + size and alignment, causing + the allocated memory referenced by ptr to be made + available for future allocations. Non-standard API @@ -451,6 +475,24 @@ for (i = 0; i < nbins; i++) { depended on, since such behavior is entirely implementation-dependent. + + Interactions Between the Standard and Non-standard APIs + Generally speaking it is permissible to pass pointers obtained from + the standard API to the non-standard API and vice versa (e.g. calling + free() with a pointer returned by a call to + mallocx(), calling sdallocx() + with a pointer returned by a call to calloc()). + There are however a few exceptions. In keeping with the C23 standard – + which forbids calling free_sized() on a pointer + returned by aligned_alloc(), mandating that either + free_aligned_sized() or free() + be used instead – using any combination of the standard and non-standard + APIs in an equivalent fashion (i.e. taking a pointer which was allocated + with an explicitly requested alignment and attempting to free it via an + API that accepts a size hint, without also providing the alignment hint) + is likewise forbidden. + + TUNING diff --git a/include/jemalloc/internal/jemalloc_internal_defs.h.in b/include/jemalloc/internal/jemalloc_internal_defs.h.in index cce638d3..7498bc48 100644 --- a/include/jemalloc/internal/jemalloc_internal_defs.h.in +++ b/include/jemalloc/internal/jemalloc_internal_defs.h.in @@ -14,6 +14,8 @@ */ #undef JEMALLOC_OVERRIDE___LIBC_CALLOC #undef JEMALLOC_OVERRIDE___LIBC_FREE +#undef JEMALLOC_OVERRIDE___LIBC_FREE_SIZED +#undef JEMALLOC_OVERRIDE___LIBC_FREE_ALIGNED_SIZED #undef JEMALLOC_OVERRIDE___LIBC_MALLOC #undef JEMALLOC_OVERRIDE___LIBC_MEMALIGN #undef JEMALLOC_OVERRIDE___LIBC_REALLOC diff --git a/include/jemalloc/jemalloc_protos.h.in b/include/jemalloc/jemalloc_protos.h.in index aff2d88f..170493dd 100644 --- a/include/jemalloc/jemalloc_protos.h.in +++ b/include/jemalloc/jemalloc_protos.h.in @@ -28,6 +28,9 @@ JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN JEMALLOC_CXX_THROW JEMALLOC_ALLOC_SIZE(2); JEMALLOC_EXPORT void JEMALLOC_SYS_NOTHROW @je_@free(void *ptr) JEMALLOC_CXX_THROW; +JEMALLOC_EXPORT void JEMALLOC_NOTHROW @je_@free_sized(void *ptr, size_t size); +JEMALLOC_EXPORT void JEMALLOC_NOTHROW @je_@free_aligned_sized( + void *ptr, size_t alignment, size_t size); JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN void JEMALLOC_NOTHROW *@je_@mallocx(size_t size, int flags) diff --git a/src/jemalloc.c b/src/jemalloc.c index 8de30279..3961683a 100644 --- a/src/jemalloc.c +++ b/src/jemalloc.c @@ -2990,6 +2990,16 @@ je_free(void *ptr) { LOG("core.free.exit", ""); } +JEMALLOC_EXPORT void JEMALLOC_NOTHROW +je_free_sized(void *ptr, size_t size) { + return je_sdallocx_noflags(ptr, size); +} + +JEMALLOC_EXPORT void JEMALLOC_NOTHROW +je_free_aligned_sized(void *ptr, size_t alignment, size_t size) { + return je_sdallocx(ptr, size, /* flags */ MALLOCX_ALIGN(alignment)); +} + /* * End malloc(3)-compatible functions. */ @@ -3153,6 +3163,13 @@ void *__libc_calloc(size_t n, size_t size) PREALIAS(je_calloc); # ifdef JEMALLOC_OVERRIDE___LIBC_FREE void __libc_free(void* ptr) PREALIAS(je_free); # endif +# ifdef JEMALLOC_OVERRIDE___LIBC_FREE_SIZED +void __libc_free_sized(void* ptr, size_t size) PREALIAS(je_free_sized); +# endif +# ifdef JEMALLOC_OVERRIDE___LIBC_FREE_ALIGNED_SIZED +void __libc_free_aligned_sized( + void* ptr, size_t alignment, size_t size) PREALIAS(je_free_aligned_sized); +# endif # ifdef JEMALLOC_OVERRIDE___LIBC_MALLOC void *__libc_malloc(size_t size) PREALIAS(je_malloc); # endif