GNU time's configure script has the following:
# What memory units are reported by getrusage(2) ?
warn_getrusage_mem_units=
if test -z "$time_getrusage_mem_units" ; then
# if envvar 'time_getrusage_mem_units' isn't set,
# autodetect based on OS.
case "$host_os" in
minix*|aix*|*bsd*|linux*|gnu*)
time_getrusage_mem_units=kb ;;
macos*|darwin*) time_getrusage_mem_units=bytes ;;
solaris*) time_getrusage_mem_units=pages ;;
# As a fallback, assume KB (the most common value).
# Set the 'warn' variable to warn the user at the end
# of ./configure
*) time_getrusage_mem_units=kb
warn_getrusage_mem_units=yes
;;
esac
fi
Using the attached test program we can test what unit a platform uses.
On GNU/Linux, AIX 7.3, FreeBSD 15.0, NetBSD 10.0, and OpenBSD 7.8:
$ gcc test-getrusage-maxrss.c
$ ./a.out
Kilobytes
On macOS 26:
$ gcc test-getrusage-maxrss.c
$ ./a.out
Bytes
On Solaris 11.4:
$ gcc test-getrusage-maxrss.c
$ ./a.out
Empty
Solaris 11's man page says that it is measured in pages, but also that
it doesn't fill it. I guess maybe they meant to document the behavior on
older Solaris versions.
It might be worth Gnulib working around that, but before that is
considered I would have to talk to the GNU Octave maintainers who also
use this module. In the meantime, it is probably worth documenting with
the attached patch.
Collin
>From b3fea86dc3e0d44ef8044013d2f9d6cfd3801892 Mon Sep 17 00:00:00 2001
Message-ID: <b3fea86dc3e0d44ef8044013d2f9d6cfd3801892.1769061375.git.collin.fu...@gmail.com>
From: Collin Funk <[email protected]>
Date: Wed, 21 Jan 2026 21:43:56 -0800
Subject: [PATCH] doc: document a portability issue with macOS getrusage.
* doc/posix-functions/getrusage.texi: Document that the 'ru_maxrss'
field of 'struct rusage' is measured in bytes on macOS.
---
ChangeLog | 6 ++++++
doc/posix-functions/getrusage.texi | 4 ++++
2 files changed, 10 insertions(+)
diff --git a/ChangeLog b/ChangeLog
index 7b4a86c977..332817350a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2026-01-21 Collin Funk <[email protected]>
+
+ doc: document a portability issue with macOS getrusage.
+ * doc/posix-functions/getrusage.texi: Document that the 'ru_maxrss'
+ field of 'struct rusage' is measured in bytes on macOS.
+
2026-01-20 Bruno Haible <[email protected]>
vasnprintf: Optimize when 'long double' is the same as 'double'.
diff --git a/doc/posix-functions/getrusage.texi b/doc/posix-functions/getrusage.texi
index 8993a77fa1..18c1c47734 100644
--- a/doc/posix-functions/getrusage.texi
+++ b/doc/posix-functions/getrusage.texi
@@ -19,4 +19,8 @@ @node getrusage
@item
Many platforms don't fill in all the fields of @code{struct rusage} with
meaningful values.
+@item
+Some platforms fill the @code{ru_maxrss} field of @code{struct rusage}
+with the maximum resident set size in bytes instead of kilobytes:
+macOS 26.
@end itemize
--
2.52.0
#include <stdio.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#define PAGES 1000
int
main (void)
{
pid_t pid = fork ();
if (pid < 0)
{
fprintf (stderr, "fork: %s\n", strerror (errno));
return EXIT_FAILURE;
}
else if (0 < pid)
{
/* Parent. */
int status;
int result = waitpid (-1, &status, 0);
if (result < 0)
{
fprintf (stderr, "waitpid: %s\n", strerror (errno));
return EXIT_FAILURE;
}
if (! WIFEXITED (status) || WEXITSTATUS (status))
{
fprintf (stderr, "child exited abnormally\n");
return EXIT_FAILURE;
}
struct rusage ru;
if (getrusage (RUSAGE_CHILDREN, &ru) < 0)
{
fprintf (stderr, "getrusage: %s\n", strerror (errno));
return EXIT_FAILURE;
}
int expect = getpagesize () * PAGES;
int values[] = { ru.ru_maxrss, ru.ru_maxrss * 1024, ru.ru_maxrss *
getpagesize () };
int closest = abs (values[0] - expect);
int index = 0;
for (int i = 1; i < sizeof values / sizeof *values; ++i)
{
int diff = abs (values[i] - expect);
if (diff < closest)
{
closest = diff;
index = i;
}
}
char const *sizes[] = { "Bytes", "Kilobytes", "Pages" };
if (ru.ru_maxrss == 0)
printf ("Empty\n");
else
printf ("%s\n", sizes[index]);
return EXIT_SUCCESS;
}
else
{
/* Child. */
int bytes = getpagesize () * PAGES;
char *pages = malloc (bytes);
for (int i = 0; i < bytes; ++i)
pages[i] = i;
return EXIT_SUCCESS;
}
}