227 lines
6.8 KiB
Diff
227 lines
6.8 KiB
Diff
From 329843f682d1216d4f41aab7b5711f21ef280b71 Mon Sep 17 00:00:00 2001
|
|
From: Philip Withnall <pwithnall@endlessos.org>
|
|
Date: Wed, 25 Jan 2023 14:12:20 +0000
|
|
Subject: [PATCH] gmem: Add g_free_sized() and g_aligned_free_sized()
|
|
|
|
These wrap `free_sized()` and `free_aligned_sized()`, which are present
|
|
in C23[1]. This means that user code can start to use them without checking
|
|
for C23 support everywhere first.
|
|
|
|
It also means we can use them internally in GSlice to get a bit of
|
|
performance for the code which still uses it.
|
|
|
|
See https://en.cppreference.com/w/c/memory/free_aligned_sized and
|
|
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2699.htm.
|
|
|
|
[1]: Specifically, section 7.24.3.4 of the latest C23 draft at
|
|
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3088.pdf.
|
|
|
|
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
|
|
|
|
Conflict:NA
|
|
Reference:https://gitlab.gnome.org/GNOME/glib/-/commit/329843f682d1216d4f41aab7b5711f21ef280b71
|
|
|
|
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
|
|
index 3532d28..ac93ae6 100644
|
|
--- a/docs/reference/glib/glib-sections.txt
|
|
+++ b/docs/reference/glib/glib-sections.txt
|
|
@@ -1397,6 +1397,7 @@ g_try_realloc_n
|
|
|
|
<SUBSECTION>
|
|
g_free
|
|
+g_free_sized
|
|
g_clear_pointer
|
|
g_steal_pointer
|
|
g_mem_gc_friendly
|
|
@@ -1411,6 +1412,7 @@ g_newa0
|
|
g_aligned_alloc
|
|
g_aligned_alloc0
|
|
g_aligned_free
|
|
+g_aligned_free_sized
|
|
|
|
<SUBSECTION>
|
|
g_memmove
|
|
diff --git a/glib/gmem.c b/glib/gmem.c
|
|
index 060e91a..e94268a 100644
|
|
--- a/glib/gmem.c
|
|
+++ b/glib/gmem.c
|
|
@@ -209,6 +209,9 @@ g_realloc (gpointer mem,
|
|
*
|
|
* Frees the memory pointed to by @mem.
|
|
*
|
|
+ * If you know the allocated size of @mem, calling g_free_sized() may be faster,
|
|
+ * depending on the libc implementation in use.
|
|
+ *
|
|
* If @mem is %NULL it simply returns, so there is no need to check @mem
|
|
* against %NULL before calling this function.
|
|
*/
|
|
@@ -219,6 +222,33 @@ g_free (gpointer mem)
|
|
TRACE(GLIB_MEM_FREE((void*) mem));
|
|
}
|
|
|
|
+/**
|
|
+ * g_free_sized:
|
|
+ * @mem: (nullable): the memory to free
|
|
+ * @size: size of @mem, in bytes
|
|
+ *
|
|
+ * Frees the memory pointed to by @mem, assuming it is has the given @size.
|
|
+ *
|
|
+ * If @mem is %NULL this is a no-op (and @size is ignored).
|
|
+ *
|
|
+ * It is an error if @size doesn鈥檛 match the size passed when @mem was
|
|
+ * allocated. @size is passed to this function to allow optimizations in the
|
|
+ * allocator. If you don鈥檛 know the allocation size, use g_free() instead.
|
|
+ *
|
|
+ * Since: 2.72
|
|
+ */
|
|
+void
|
|
+g_free_sized (void *mem,
|
|
+ size_t size)
|
|
+{
|
|
+#ifdef HAVE_FREE_SIZED
|
|
+ free_sized (mem, size);
|
|
+#else
|
|
+ free (mem);
|
|
+#endif
|
|
+ TRACE (GLIB_MEM_FREE ((void*) mem));
|
|
+}
|
|
+
|
|
/**
|
|
* g_clear_pointer: (skip)
|
|
* @pp: (not nullable): a pointer to a variable, struct member etc. holding a
|
|
@@ -555,7 +585,7 @@ g_mem_profile (void)
|
|
* multiplication.
|
|
*
|
|
* Aligned memory allocations returned by this function can only be
|
|
- * freed using g_aligned_free().
|
|
+ * freed using g_aligned_free_sized() or g_aligned_free().
|
|
*
|
|
* Returns: (transfer full): the allocated memory
|
|
*
|
|
@@ -679,3 +709,33 @@ g_aligned_free (gpointer mem)
|
|
{
|
|
aligned_free (mem);
|
|
}
|
|
+
|
|
+/**
|
|
+ * g_aligned_free_sized:
|
|
+ * @mem: (nullable): the memory to free
|
|
+ * @alignment: alignment of @mem
|
|
+ * @size: size of @mem, in bytes
|
|
+ *
|
|
+ * Frees the memory pointed to by @mem, assuming it is has the given @size and
|
|
+ * @alignment.
|
|
+ *
|
|
+ * If @mem is %NULL this is a no-op (and @size is ignored).
|
|
+ *
|
|
+ * It is an error if @size doesn鈥檛 match the size, or @alignment doesn鈥檛 match
|
|
+ * the alignment, passed when @mem was allocated. @size and @alignment are
|
|
+ * passed to this function to allow optimizations in the allocator. If you
|
|
+ * don鈥檛 know either of them, use g_aligned_free() instead.
|
|
+ *
|
|
+ * Since: 2.72
|
|
+ */
|
|
+void
|
|
+g_aligned_free_sized (void *mem,
|
|
+ size_t alignment,
|
|
+ size_t size)
|
|
+{
|
|
+#ifdef HAVE_FREE_ALIGNED_SIZED
|
|
+ free_aligned_sized (mem, alignment, size);
|
|
+#else
|
|
+ aligned_free (mem);
|
|
+#endif
|
|
+}
|
|
diff --git a/glib/gmem.h b/glib/gmem.h
|
|
index d29907a..7b306b3 100644
|
|
--- a/glib/gmem.h
|
|
+++ b/glib/gmem.h
|
|
@@ -70,6 +70,9 @@ typedef struct _GMemVTable GMemVTable;
|
|
|
|
GLIB_AVAILABLE_IN_ALL
|
|
void g_free (gpointer mem);
|
|
+GLIB_AVAILABLE_IN_2_72
|
|
+void g_free_sized (gpointer mem,
|
|
+ size_t size);
|
|
|
|
GLIB_AVAILABLE_IN_2_34
|
|
void g_clear_pointer (gpointer *pp,
|
|
@@ -121,6 +124,10 @@ gpointer g_aligned_alloc0 (gsize n_blocks,
|
|
gsize alignment) G_GNUC_WARN_UNUSED_RESULT G_GNUC_ALLOC_SIZE2(1,2);
|
|
GLIB_AVAILABLE_IN_2_72
|
|
void g_aligned_free (gpointer mem);
|
|
+GLIB_AVAILABLE_IN_2_72
|
|
+void g_aligned_free_sized (gpointer mem,
|
|
+ size_t alignment,
|
|
+ size_t size);
|
|
|
|
#if defined(glib_typeof) && GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_58
|
|
#define g_clear_pointer(pp, destroy) \
|
|
diff --git a/glib/tests/utils.c b/glib/tests/utils.c
|
|
index dcdc5a6..602abe1 100644
|
|
--- a/glib/tests/utils.c
|
|
+++ b/glib/tests/utils.c
|
|
@@ -1000,6 +1000,39 @@ test_aligned_mem_zeroed (void)
|
|
g_aligned_free (p);
|
|
}
|
|
|
|
+static void
|
|
+test_aligned_mem_free_sized (void)
|
|
+{
|
|
+ gsize n_blocks = 10;
|
|
+ guint *p;
|
|
+
|
|
+ g_test_summary ("Check that g_aligned_free_sized() works");
|
|
+
|
|
+ p = g_aligned_alloc (n_blocks, sizeof (*p), 16);
|
|
+ g_assert_nonnull (p);
|
|
+
|
|
+ g_aligned_free_sized (p, sizeof (*p), n_blocks * 16);
|
|
+
|
|
+ /* NULL should be ignored */
|
|
+ g_aligned_free_sized (NULL, sizeof (*p), n_blocks * 16);
|
|
+}
|
|
+
|
|
+static void
|
|
+test_free_sized (void)
|
|
+{
|
|
+ gpointer p;
|
|
+
|
|
+ g_test_summary ("Check that g_free_sized() works");
|
|
+
|
|
+ p = g_malloc (123);
|
|
+ g_assert_nonnull (p);
|
|
+
|
|
+ g_free_sized (p, 123);
|
|
+
|
|
+ /* NULL should be ignored */
|
|
+ g_free_sized (NULL, 123);
|
|
+}
|
|
+
|
|
static void
|
|
test_nullify (void)
|
|
{
|
|
@@ -1174,6 +1207,8 @@ main (int argc,
|
|
g_test_add_func ("/utils/aligned-mem/subprocess/aligned_alloc_nmov", aligned_alloc_nmov);
|
|
g_test_add_func ("/utils/aligned-mem/alignment", test_aligned_mem_alignment);
|
|
g_test_add_func ("/utils/aligned-mem/zeroed", test_aligned_mem_zeroed);
|
|
+ g_test_add_func ("/utils/aligned-mem/free-sized", test_aligned_mem_free_sized);
|
|
+ g_test_add_func ("/utils/free-sized", test_free_sized);
|
|
g_test_add_func ("/utils/nullify", test_nullify);
|
|
g_test_add_func ("/utils/atexit", test_atexit);
|
|
g_test_add_func ("/utils/check-setuid", test_check_setuid);
|
|
diff --git a/meson.build b/meson.build
|
|
index 657e9f6..3f32ef7 100644
|
|
--- a/meson.build
|
|
+++ b/meson.build
|
|
@@ -535,6 +535,8 @@ functions = [
|
|
'fchmod',
|
|
'fchown',
|
|
'fdwalk',
|
|
+ 'free_aligned_sized',
|
|
+ 'free_sized',
|
|
'fsync',
|
|
'getauxval',
|
|
'getc_unlocked',
|
|
--
|
|
2.33.0
|