diff options
| author | Joseph Myers <josmyers@redhat.com> | 2025-10-17 16:56:59 +0000 |
|---|---|---|
| committer | Joseph Myers <josmyers@redhat.com> | 2025-10-17 16:56:59 +0000 |
| commit | ea18d5a4c2583726060326b8a348de0845c22aa1 (patch) | |
| tree | d38f265bdd03061704a6f8294c4a315c8c72d780 /stdlib | |
| parent | 850d93f514ebc3c8b62603e70586edd38a18f46b (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/Makefile | 4 | ||||
| -rw-r--r-- | stdlib/Versions | 3 | ||||
| -rw-r--r-- | stdlib/memalignment.c | 27 | ||||
| -rw-r--r-- | stdlib/stdlib.h | 3 | ||||
| -rw-r--r-- | stdlib/tst-memalignment.c | 43 |
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> |
