aboutsummaryrefslogtreecommitdiff
path: root/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/Makefile44
-rw-r--r--stdlib/Versions6
-rw-r--r--stdlib/inttypes.h5
-rw-r--r--stdlib/qsort.c81
-rw-r--r--stdlib/stdlib.h6
-rw-r--r--stdlib/tst-qsort4.c4
-rw-r--r--stdlib/tst-qsort7.c80
-rw-r--r--stdlib/tst-qsortx7.c1
-rw-r--r--stdlib/tst-uabs.c45
-rw-r--r--stdlib/tst-uimaxabs.c51
-rw-r--r--stdlib/tst-ulabs.c52
-rw-r--r--stdlib/tst-ullabs.c55
-rw-r--r--stdlib/uabs.c28
-rw-r--r--stdlib/ulabs.c33
-rw-r--r--stdlib/ullabs.c33
15 files changed, 492 insertions, 32 deletions
diff --git a/stdlib/Makefile b/stdlib/Makefile
index c9c8f70..1c80e49 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -211,6 +211,9 @@ routines := \
strtoull_l \
swapcontext \
system \
+ uabs \
+ ulabs \
+ ullabs \
wcstombs \
wctomb \
xpg_basename \
@@ -300,6 +303,8 @@ tests := \
tst-qsort2 \
tst-qsort3 \
tst-qsort6 \
+ tst-qsort7 \
+ tst-qsortx7 \
tst-quick_exit \
tst-rand-sequence \
tst-rand48 \
@@ -361,6 +366,10 @@ tests := \
tst-swapcontext2 \
tst-thread-quick_exit \
tst-tininess \
+ tst-uabs \
+ tst-uimaxabs \
+ tst-ulabs \
+ tst-ullabs \
tst-unsetenv1 \
tst-width \
tst-width-stdint \
@@ -410,6 +419,11 @@ CFLAGS-tst-abs.c += -fno-builtin
CFLAGS-tst-labs.c += -fno-builtin
CFLAGS-tst-llabs.c += -fno-builtin
+CFLAGS-tst-uabs.c += -fno-builtin
+CFLAGS-tst-uimaxabs.c += -fno-builtin
+CFLAGS-tst-ulabs.c += -fno-builtin
+CFLAGS-tst-ullabs.c += -fno-builtin
+
CFLAGS-tst-stdbit-Wconversion.c += -Wconversion -Werror
CFLAGS-tst-stdc_trailing_zeros.c += -fno-builtin
CFLAGS-tst-stdc_trailing_ones.c += -fno-builtin
@@ -553,7 +567,19 @@ tests-special += $(objpfx)isomac.out
ifeq ($(run-built-tests),yes)
tests-special += $(objpfx)tst-fmtmsg.out
-endif
+ifeq ($(build-shared),yes)
+ifneq ($(PERL),no)
+generated += \
+ tst-qsort7.mtrace \
+ tst-qsortx7.mtrace \
+ # generated
+tests-special += \
+ $(objpfx)tst-qsort7-mem.out \
+ $(objpfx)tst-qsortx7-mem.out \
+ # tests-special
+endif # $(build-shared) == yes
+endif # $(PERL) == yes
+endif # $(run-built-tests) == yes
include ../Rules
@@ -647,3 +673,19 @@ $(objpfx)tst-getrandom2: $(shared-thread-library)
$(objpfx)tst-getenv-signal: $(shared-thread-library)
$(objpfx)tst-getenv-thread: $(shared-thread-library)
$(objpfx)tst-getenv-unsetenv: $(shared-thread-library)
+
+CFLAGS-tst-qsort7.c += -fno-exceptions -fno-asynchronous-unwind-tables
+LDLIBS-tst-qsort7 = $(shared-thread-library)
+tst-qsort7-ENV = MALLOC_TRACE=$(objpfx)tst-qsort7.mtrace \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
+$(objpfx)tst-qsort7-mem.out: $(objpfx)tst-qsort7.out
+ $(common-objpfx)malloc/mtrace $(objpfx)tst-qsort7.mtrace > $@; \
+ $(evaluate-test)
+
+CFLAGS-tst-qsortx7.c += -fexceptions
+LDLIBS-tst-qsortx7 = $(shared-thread-library)
+tst-qsortx7-ENV = MALLOC_TRACE=$(objpfx)tst-qsortx7.mtrace \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
+$(objpfx)tst-qsortx7-mem.out: $(objpfx)tst-qsortx7.out
+ $(common-objpfx)malloc/mtrace $(objpfx)tst-qsortx7.mtrace > $@; \
+ $(evaluate-test)
diff --git a/stdlib/Versions b/stdlib/Versions
index ea2265b..6d02400 100644
--- a/stdlib/Versions
+++ b/stdlib/Versions
@@ -223,6 +223,12 @@ libc {
stdc_bit_ceil_ul;
stdc_bit_ceil_ull;
}
+ GLIBC_2.42 {
+ uabs;
+ uimaxabs;
+ ulabs;
+ ullabs;
+ }
GLIBC_PRIVATE {
# functions which have an additional interface since they are
# are cancelable.
diff --git a/stdlib/inttypes.h b/stdlib/inttypes.h
index 95324f0..9726abf 100644
--- a/stdlib/inttypes.h
+++ b/stdlib/inttypes.h
@@ -350,6 +350,11 @@ typedef struct
/* Compute absolute value of N. */
extern intmax_t imaxabs (intmax_t __n) __THROW __attribute__ ((__const__));
+
+#if __GLIBC_USE (ISOC2Y)
+extern uintmax_t uimaxabs (intmax_t __n) __THROW __attribute__ ((__const__));
+#endif
+
/* Return the `imaxdiv_t' representation of the value of NUMER over DENOM. */
extern imaxdiv_t imaxdiv (intmax_t __numer, intmax_t __denom)
__THROW __attribute__ ((__const__));
diff --git a/stdlib/qsort.c b/stdlib/qsort.c
index 08fdb84..0b1e0e9 100644
--- a/stdlib/qsort.c
+++ b/stdlib/qsort.c
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
+#include "pthreadP.h"
/* Swap SIZE bytes between addresses A and B. These helpers are provided
along the generic one as an optimization. */
@@ -338,36 +339,10 @@ indirect_msort_with_tmp (const struct msort_param *p, void *b, size_t n,
}
}
-void
-__qsort_r (void *const pbase, size_t total_elems, size_t size,
- __compar_d_fn_t cmp, void *arg)
+static void
+qsort_r_mergesort (void *const pbase, size_t total_elems, size_t size,
+ __compar_d_fn_t cmp, void *arg, void *buf)
{
- if (total_elems <= 1)
- return;
-
- /* Align to the maximum size used by the swap optimization. */
- _Alignas (uint64_t) char tmp[QSORT_STACK_SIZE];
- size_t total_size = total_elems * size;
- char *buf;
-
- if (size > INDIRECT_SORT_SIZE_THRES)
- total_size = 2 * total_elems * sizeof (void *) + size;
-
- if (total_size <= sizeof tmp)
- buf = tmp;
- else
- {
- int save = errno;
- buf = malloc (total_size);
- __set_errno (save);
- if (buf == NULL)
- {
- /* Fallback to heapsort in case of memory failure. */
- heapsort_r (pbase, total_elems - 1, size, cmp, arg);
- return;
- }
- }
-
if (size > INDIRECT_SORT_SIZE_THRES)
{
const struct msort_param msort_param =
@@ -392,9 +367,53 @@ __qsort_r (void *const pbase, size_t total_elems, size_t size,
};
msort_with_tmp (&msort_param, pbase, total_elems);
}
+}
+
+static bool
+qsort_r_malloc (void *const pbase, size_t total_elems, size_t size,
+ __compar_d_fn_t cmp, void *arg, size_t total_size)
+{
+ int save = errno;
+ char *buf = malloc (total_size);
+ __set_errno (save);
+ if (buf == NULL)
+ return false;
- if (buf != tmp)
- free (buf);
+ /* Deallocate the auxiliary buffer if the callback function throws
+ or if the thread is cancelled. */
+ pthread_cleanup_combined_push (free, buf);
+ qsort_r_mergesort (pbase, total_elems, size, cmp, arg, buf);
+ pthread_cleanup_combined_pop (0);
+
+ free (buf);
+
+ return true;
+}
+
+void
+__qsort_r (void *const pbase, size_t total_elems, size_t size,
+ __compar_d_fn_t cmp, void *arg)
+{
+ if (total_elems <= 1)
+ return;
+
+ /* Align to the maximum size used by the swap optimization. */
+ size_t total_size = total_elems * size;
+
+ if (size > INDIRECT_SORT_SIZE_THRES)
+ total_size = 2 * total_elems * sizeof (void *) + size;
+
+ if (total_size <= QSORT_STACK_SIZE)
+ {
+ _Alignas (uint64_t) char tmp[QSORT_STACK_SIZE];
+ qsort_r_mergesort (pbase, total_elems, size, cmp, arg, tmp);
+ }
+ else
+ {
+ if (!qsort_r_malloc (pbase, total_elems, size, cmp, arg, total_size))
+ /* Fallback to heapsort in case of memory failure. */
+ heapsort_r (pbase, total_elems - 1, size, cmp, arg);
+ }
}
libc_hidden_def (__qsort_r)
weak_alias (__qsort_r, qsort_r)
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index 975f5ae..cd4503c 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -985,6 +985,12 @@ __extension__ extern long long int llabs (long long int __x)
__THROW __attribute__ ((__const__)) __wur;
#endif
+#if __GLIBC_USE (ISOC2Y)
+extern unsigned int uabs (int __x) __THROW __attribute__ ((__const__)) __wur;
+extern unsigned long int ulabs (long int __x) __THROW __attribute__ ((__const__)) __wur;
+__extension__ extern unsigned long long int ullabs (long long int __x)
+ __THROW __attribute__ ((__const__)) __wur;
+#endif
/* Return the `div_t', `ldiv_t' or `lldiv_t' representation
of the value of NUMER over DENOM. */
diff --git a/stdlib/tst-qsort4.c b/stdlib/tst-qsort4.c
index 2875d40..a36e66a 100644
--- a/stdlib/tst-qsort4.c
+++ b/stdlib/tst-qsort4.c
@@ -16,6 +16,10 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#undef pthread_cleanup_combined_push
+#define pthread_cleanup_combined_push(routine, arg)
+#undef pthread_cleanup_combined_pop
+#define pthread_cleanup_combined_pop(execute)
#include "qsort.c"
#include <stdio.h>
diff --git a/stdlib/tst-qsort7.c b/stdlib/tst-qsort7.c
new file mode 100644
index 0000000..0d62630
--- /dev/null
+++ b/stdlib/tst-qsort7.c
@@ -0,0 +1,80 @@
+/* Check exception handling from qsort (BZ 32058).
+ Copyright (C) 2024 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <mcheck.h>
+#include <stdlib.h>
+#include <support/check.h>
+#include <support/xthread.h>
+#include <unistd.h>
+
+static pthread_barrier_t b;
+
+static void
+cl (void *arg)
+{
+}
+
+static int
+compar_func (const void *a1, const void *a2)
+{
+ xpthread_barrier_wait (&b);
+
+ pthread_cleanup_push (cl, NULL);
+
+ pause ();
+
+ pthread_cleanup_pop (0);
+
+ support_record_failure ();
+
+ return 0;
+}
+
+static void *
+tf (void *tf)
+{
+ /* An array larger than QSORT_STACK_SIZE to force memory allocation. */
+ int input[1024] = { 0 };
+ qsort (input, array_length (input), sizeof input[0], compar_func);
+
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ mtrace ();
+
+ xpthread_barrier_init (&b, NULL, 2);
+
+ pthread_t thr = xpthread_create (NULL, tf, NULL);
+
+ xpthread_barrier_wait (&b);
+
+ xpthread_cancel (thr);
+
+ {
+ void *r = xpthread_join (thr);
+ TEST_VERIFY (r == PTHREAD_CANCELED);
+ }
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/stdlib/tst-qsortx7.c b/stdlib/tst-qsortx7.c
new file mode 100644
index 0000000..ab61523
--- /dev/null
+++ b/stdlib/tst-qsortx7.c
@@ -0,0 +1 @@
+#include "tst-qsort7.c"
diff --git a/stdlib/tst-uabs.c b/stdlib/tst-uabs.c
new file mode 100644
index 0000000..13c9f58
--- /dev/null
+++ b/stdlib/tst-uabs.c
@@ -0,0 +1,45 @@
+/* Basic tests for uabs.
+ 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 <limits.h>
+#include <stdlib.h>
+
+#include <support/check.h>
+
+#define LARGE_PRIME 49999
+
+static int do_test (void)
+{
+ int i;
+
+ TEST_COMPARE (uabs (INT_MAX), INT_MAX);
+ TEST_COMPARE (uabs (INT_MIN), (unsigned int)INT_MAX + 1);
+ TEST_COMPARE (uabs (-1), 1);
+ TEST_COMPARE (uabs (0), 0);
+ TEST_COMPARE (uabs (1), 1);
+
+ for (i = INT_MIN + 1; i < 0; i += LARGE_PRIME)
+ TEST_COMPARE (uabs (i), -i);
+
+ for (i = 0; i < INT_MAX - LARGE_PRIME; i += LARGE_PRIME)
+ TEST_COMPARE (uabs (i), i);
+
+ return EXIT_SUCCESS;
+}
+
+#include <support/test-driver.c>
diff --git a/stdlib/tst-uimaxabs.c b/stdlib/tst-uimaxabs.c
new file mode 100644
index 0000000..4500ec1
--- /dev/null
+++ b/stdlib/tst-uimaxabs.c
@@ -0,0 +1,51 @@
+/* Basic tests for uimaxabs.
+ 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 <inttypes.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include <support/check.h>
+
+#define LARGE_PRIME 49999
+
+static int do_test (void)
+{
+ intmax_t i;
+
+ TEST_COMPARE (uimaxabs (INTMAX_MIN), (uintmax_t)INTMAX_MAX + 1);
+ TEST_COMPARE (uimaxabs (-1), 1);
+ TEST_COMPARE (uimaxabs (0), 0);
+ TEST_COMPARE (uimaxabs (1), 1);
+
+ for (i = INTMAX_MIN + 1; i < INTMAX_MIN + INT_MAX; i += LARGE_PRIME)
+ TEST_COMPARE (uimaxabs (i), -i);
+
+ for (i = INTMAX_MAX - INT_MAX; i < INTMAX_MAX - LARGE_PRIME; i += LARGE_PRIME)
+ TEST_COMPARE (uimaxabs (i), i);
+
+ for (i = INT_MIN + 1; i < 0; i += LARGE_PRIME)
+ TEST_COMPARE (uimaxabs (i), -i);
+
+ for (i = 0; i < INT_MAX; i += LARGE_PRIME)
+ TEST_COMPARE (uimaxabs (i), i);
+
+ return EXIT_SUCCESS;
+}
+
+#include <support/test-driver.c>
diff --git a/stdlib/tst-ulabs.c b/stdlib/tst-ulabs.c
new file mode 100644
index 0000000..3b5323e
--- /dev/null
+++ b/stdlib/tst-ulabs.c
@@ -0,0 +1,52 @@
+/* Basic tests for ulabs.
+ 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 <limits.h>
+#include <stdlib.h>
+
+#include <support/check.h>
+
+#define LARGE_PRIME 49999
+
+static int do_test (void)
+{
+ long int i;
+
+ TEST_COMPARE (ulabs (LONG_MAX), LONG_MAX);
+ TEST_COMPARE (ulabs (LONG_MIN), (unsigned long int)LONG_MAX + 1);
+ TEST_COMPARE (ulabs (-1), 1);
+ TEST_COMPARE (ulabs (0), 0);
+ TEST_COMPARE (ulabs (1), 1);
+
+ for (i = LONG_MIN + 1; i < LONG_MIN + INT_MAX; i += LARGE_PRIME)
+ TEST_COMPARE (ulabs (i), -i);
+
+ for (i = LONG_MAX - INT_MAX; i < LONG_MAX - LARGE_PRIME;
+ i += LARGE_PRIME)
+ TEST_COMPARE (ulabs (i), i);
+
+ for (i = INT_MIN + 1; i < 0; i += LARGE_PRIME)
+ TEST_COMPARE (ulabs (i), -i);
+
+ for (i = 0; i <= INT_MAX - LARGE_PRIME; i += LARGE_PRIME)
+ TEST_COMPARE (ulabs (i), i);
+
+ return EXIT_SUCCESS;
+}
+
+#include <support/test-driver.c>
diff --git a/stdlib/tst-ullabs.c b/stdlib/tst-ullabs.c
new file mode 100644
index 0000000..ac34ec7
--- /dev/null
+++ b/stdlib/tst-ullabs.c
@@ -0,0 +1,55 @@
+/* Basic tests for ullabs.
+ 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 <limits.h>
+#include <stdlib.h>
+
+#include <support/check.h>
+
+#define LARGE_PRIME 49999
+
+static int do_test (void)
+{
+ long long int i;
+
+ TEST_COMPARE (ullabs (LLONG_MAX), LLONG_MAX);
+ TEST_COMPARE (ullabs (LLONG_MIN), (unsigned long long int)LLONG_MAX + 1);
+ TEST_COMPARE (ullabs (0x00000000ffffffffL), 0x00000000ffffffffL);
+ TEST_COMPARE (ullabs (0x0000000100000000L), 0x0000000100000000L);
+ TEST_COMPARE (ullabs (0x80000000ffffffffL), 0x7fffffff00000001L);
+ TEST_COMPARE (ullabs (0x8000000100000000L), 0x7fffffff00000000L);
+ TEST_COMPARE (ullabs (-1), 1);
+ TEST_COMPARE (ullabs (0), 0);
+ TEST_COMPARE (ullabs (1), 1);
+
+ for (i = LLONG_MIN + 1; i < LLONG_MIN + INT_MAX; i += LARGE_PRIME)
+ TEST_COMPARE (ullabs (i), -i);
+
+ for (i = LLONG_MAX - INT_MAX; i < LLONG_MAX - LARGE_PRIME; i += LARGE_PRIME)
+ TEST_COMPARE (ullabs (i), i);
+
+ for (i = INT_MIN + 1; i < 0; i += LARGE_PRIME)
+ TEST_COMPARE (ullabs (i), -i);
+
+ for (i = 0; i < INT_MAX; i += LARGE_PRIME)
+ TEST_COMPARE (ullabs (i), i);
+
+ return EXIT_SUCCESS;
+}
+
+#include <support/test-driver.c>
diff --git a/stdlib/uabs.c b/stdlib/uabs.c
new file mode 100644
index 0000000..72aea5f
--- /dev/null
+++ b/stdlib/uabs.c
@@ -0,0 +1,28 @@
+/* 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>
+
+#undef uabs
+
+/* Return the absolute value of I. */
+unsigned int
+uabs (int i)
+{
+ unsigned int j = i;
+ return i < 0 ? -j : i;
+}
diff --git a/stdlib/ulabs.c b/stdlib/ulabs.c
new file mode 100644
index 0000000..c2ccfb8
--- /dev/null
+++ b/stdlib/ulabs.c
@@ -0,0 +1,33 @@
+/* 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 <limits.h>
+#include <stdlib.h>
+
+#undef ulabs
+
+/* Return the absolute value of I. */
+unsigned long int
+ulabs (long int i)
+{
+ unsigned long int j = i;
+ return i < 0 ? -j : i;
+}
+
+#if ULONG_MAX != UINT_MAX
+weak_alias (ulabs, uimaxabs)
+#endif
diff --git a/stdlib/ullabs.c b/stdlib/ullabs.c
new file mode 100644
index 0000000..11268c2
--- /dev/null
+++ b/stdlib/ullabs.c
@@ -0,0 +1,33 @@
+/* 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 <limits.h>
+#include <stdlib.h>
+
+#undef ullabs
+
+/* Return the absolute value of I. */
+unsigned long long int
+ullabs (long long int i)
+{
+ unsigned long long int j = i;
+ return i < 0 ? -j : i;
+}
+
+#if ULONG_MAX == UINT_MAX
+weak_alias (ullabs, uimaxabs)
+#endif