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