summaryrefslogtreecommitdiff
path: root/stdlib
diff options
context:
space:
mode:
authorJoseph Myers <josmyers@redhat.com>2025-10-17 16:56:59 +0000
committerJoseph Myers <josmyers@redhat.com>2025-10-17 16:56:59 +0000
commitea18d5a4c2583726060326b8a348de0845c22aa1 (patch)
treed38f265bdd03061704a6f8294c4a315c8c72d780 /stdlib
parent850d93f514ebc3c8b62603e70586edd38a18f46b (diff)
Implement C23 memalignment
Add the C23 memalignment function (query the alignment of a pointer) to glibc. Given how simple this operation is, it would make sense for compilers to inline calls to this function, but I'm treating that as a compiler matter (compilers should add it as a built-in function) rather than adding an inline version to glibc headers (although such an inline version would be reasonable as well). I've filed https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122117 for this feature in GCC. Tested for x86_64 and x86.
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/Makefile4
-rw-r--r--stdlib/Versions3
-rw-r--r--stdlib/memalignment.c27
-rw-r--r--stdlib/stdlib.h3
-rw-r--r--stdlib/tst-memalignment.c43
5 files changed, 80 insertions, 0 deletions
diff --git a/stdlib/Makefile b/stdlib/Makefile
index d2c594885a..8d9a98602c 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -97,6 +97,7 @@ routines := \
mblen \
mbstowcs \
mbtowc \
+ memalignment \
mrand48 \
mrand48_r \
nrand48 \
@@ -299,6 +300,7 @@ tests := \
tst-makecontext-align \
tst-makecontext2 \
tst-makecontext3 \
+ tst-memalignment \
tst-on_exit \
tst-qsort \
tst-qsort2 \
@@ -441,6 +443,8 @@ CFLAGS-tst-stdc_bit_width.c += -fno-builtin
CFLAGS-tst-stdc_bit_floor.c += -fno-builtin
CFLAGS-tst-stdc_bit_ceil.c += -fno-builtin
+CFLAGS-tst-memalignment.c += -fno-builtin
+
ifeq ($(have-cxx-thread_local),yes)
CFLAGS-tst-quick_exit.o = -std=c++11
LDLIBS-tst-quick_exit = -lstdc++
diff --git a/stdlib/Versions b/stdlib/Versions
index 6d024000f8..da7019a7ed 100644
--- a/stdlib/Versions
+++ b/stdlib/Versions
@@ -229,6 +229,9 @@ libc {
ulabs;
ullabs;
}
+ GLIBC_2.43 {
+ memalignment;
+ }
GLIBC_PRIVATE {
# functions which have an additional interface since they are
# are cancelable.
diff --git a/stdlib/memalignment.c b/stdlib/memalignment.c
new file mode 100644
index 0000000000..fb3eef96fe
--- /dev/null
+++ b/stdlib/memalignment.c
@@ -0,0 +1,27 @@
+/* Return the alignment of a pointer.
+ Copyright (C) 2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+
+/* Return the alignment of P. */
+size_t
+memalignment (const void *p)
+{
+ size_t i = (size_t) p;
+ return i & -i;
+}
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index 1d6a83a22c..8d4d194a46 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -1164,6 +1164,9 @@ extern int ttyslot (void) __THROW;
/* Call function __FUNC exactly once, even if invoked from several threads.
All calls must be made with the same __FLAGS object. */
extern void call_once (once_flag *__flag, void (*__func)(void));
+
+/* Return the alignment of P. */
+extern size_t memalignment (const void *__p);
#endif
#include <bits/stdlib-float.h>
diff --git a/stdlib/tst-memalignment.c b/stdlib/tst-memalignment.c
new file mode 100644
index 0000000000..518b83cc6b
--- /dev/null
+++ b/stdlib/tst-memalignment.c
@@ -0,0 +1,43 @@
+/* Test memalignment.
+ Copyright (C) 2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <array_length.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+ void *null = NULL;
+ TEST_COMPARE (memalignment (NULL), 0);
+ TEST_COMPARE (memalignment (null), 0);
+ char ca[256];
+ array_foreach (p, ca)
+ TEST_VERIFY (memalignment (p) >= 1);
+ TEST_VERIFY (memalignment (&ca[0]) == 1 || memalignment (&ca[1]) == 1);
+ TEST_VERIFY (memalignment (&ca[0]) == 2 || memalignment (&ca[1]) == 2
+ || memalignment (&ca[2]) == 2 || memalignment (&ca[3]) == 2);
+ long long int lla[256];
+ array_foreach (p, lla)
+ TEST_VERIFY (memalignment (p) >= _Alignof (long long int));
+ TEST_VERIFY (memalignment (&lla[0]) <= sizeof (long long int)
+ || memalignment (&lla[1]) <= sizeof (long long int));
+ return 0;
+}
+
+#include <support/test-driver.c>