clang issues:
svc_unix.c:318:18: error: field 'cmsg' with variable sized type 'struct cmsghdr' not at the end of a struct or class is a GNU extension [-Werror,-Wgnu-variable-sized-type-not-at-end]
318 | struct cmsghdr cmsg;
| ^
The __msgread explicitly expects that 'struct ucred' is after the 'cmsg',
so suppress the warning.
Reviewed-by: Sam James <sam@gentoo.org>
clang does not allow to redefine attributes after function declaration.
Although it work for external usage, its breaks the build for internal
symbol that glibc provides as optimization (for instance bsearch
with stdlib-bsearch.h or __cmsg_nxthdr).
Disable such optimization for clang while building glibc.
Reviewed-by: Sam James <sam@gentoo.org>
Linux handles virtual memory in Virtual Memory Areas (VMAs). The
madvise(MADV_HUGEPAGE) call works on a VMA granularity, which sets the
VM_HUGEPAGE flag on the VMA. This flag is invariant of the mprotect()
syscall which is used in growing the secondary heaps. Therefore, we
need to call madvise() only when we are sure that VM_HUGEPAGE was not
previously set, which is only in the case when h->size < mp_.thp_pagesize.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
The __syscall_cancel_arch function has an epilogue that does not match
the prologue. The stack is not used and the return address still lies in
r15 when reaching the epilogue. Fix the epilogue by simply returning
from the function.
Signed-off-by: Luc Michel <luc.michel@amd.com>
Tested-by: gopi@sankhya.com
Reviewed-by: Neal Frager <neal.frager@amd.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
clang does not support the __builtin_*_overflow_p builtins, on gcc
the macros will call __builtin_*_overflow_p.
Reviewed-by: Collin Funk <collin.funk1@gmail.com>
clang 20 adds both __INT64_C and __UINT64_C as builtins, but different
than gcc it does not undef them in its stdint wrapper.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
GCC enables it by default, clang in the other hand sets -fno-trapping-math.
This is required to fix some math and stdlib tests that explicit raises
floating point exceptions:
math/test-double-canonicalize.out
testing double (without inline functions)
Failure: canonicalize (max_value): Exception "Overflow" set
Failure: canonicalize (max_value): Exception "Inexact" set
Failure: canonicalize (-max_value): Exception "Overflow" set
Failure: canonicalize (-max_value): Exception "Inexact" set
Failure: canonicalize_downward (max_value): Exception "Overflow" set
Failure: canonicalize_downward (max_value): Exception "Inexact" set
Failure: canonicalize_downward (-max_value): Exception "Overflow" set
Failure: canonicalize_downward (-max_value): Exception "Inexact" set
Failure: canonicalize_towardzero (max_value): Exception "Overflow" set
Failure: canonicalize_towardzero (max_value): Exception "Inexact" set
Failure: canonicalize_towardzero (-max_value): Exception "Overflow" set
Failure: canonicalize_towardzero (-max_value): Exception "Inexact" set
Failure: canonicalize_upward (max_value): Exception "Overflow" set
Failure: canonicalize_upward (max_value): Exception "Inexact" set
Failure: canonicalize_upward (-max_value): Exception "Overflow" set
Failure: canonicalize_upward (-max_value): Exception "Inexact" set
test-float-catanh.out
testing float (without inline functions)
Failure: Real part of: catanh (-0x1.000002p+0 - 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh (-0x1.000002p+0 - 0x8p-152 i): Exception "Underflow" set
Failure: Real part of: catanh (-0x1.000002p+0 + 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh (-0x1.000002p+0 + 0x8p-152 i): Exception "Underflow" set
Failure: Real part of: catanh (-0xf.fffffp-4 - 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh (-0xf.fffffp-4 + 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh (0x1.000002p+0 - 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh (0x1.000002p+0 - 0x8p-152 i): Exception "Underflow" set
Failure: Real part of: catanh (0x1.000002p+0 + 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh (0x1.000002p+0 + 0x8p-152 i): Exception "Underflow" set
Failure: Real part of: catanh (0xf.fffffp-4 - 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh (0xf.fffffp-4 + 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_downward (-0x1.000002p+0 - 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_downward (-0x1.000002p+0 - 0x8p-152 i): Exception "Underflow" set
Failure: Real part of: catanh_downward (-0x1.000002p+0 + 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_downward (-0x1.000002p+0 + 0x8p-152 i): Exception "Underflow" set
Failure: Real part of: catanh_downward (-0xf.fffffp-4 - 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_downward (-0xf.fffffp-4 + 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_downward (0x1.000002p+0 - 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_downward (0x1.000002p+0 - 0x8p-152 i): Exception "Underflow" set
Failure: Real part of: catanh_downward (0x1.000002p+0 + 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_downward (0x1.000002p+0 + 0x8p-152 i): Exception "Underflow" set
Failure: Real part of: catanh_downward (0xf.fffffp-4 - 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_downward (0xf.fffffp-4 + 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_towardzero (-0x1.000002p+0 - 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_towardzero (-0x1.000002p+0 - 0x8p-152 i): Exception "Underflow" set
Failure: Real part of: catanh_towardzero (-0x1.000002p+0 + 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_towardzero (-0x1.000002p+0 + 0x8p-152 i): Exception "Underflow" set
Failure: Real part of: catanh_towardzero (-0xf.fffffp-4 - 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_towardzero (-0xf.fffffp-4 + 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_towardzero (0x1.000002p+0 - 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_towardzero (0x1.000002p+0 - 0x8p-152 i): Exception "Underflow" set
Failure: Real part of: catanh_towardzero (0x1.000002p+0 + 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_towardzero (0x1.000002p+0 + 0x8p-152 i): Exception "Underflow" set
Failure: Real part of: catanh_towardzero (0xf.fffffp-4 - 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_towardzero (0xf.fffffp-4 + 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_upward (-0x1.000002p+0 - 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_upward (-0x1.000002p+0 - 0x8p-152 i): Exception "Underflow" set
Failure: Real part of: catanh_upward (-0x1.000002p+0 + 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_upward (-0x1.000002p+0 + 0x8p-152 i): Exception "Underflow" set
Failure: Real part of: catanh_upward (-0xf.fffffp-4 - 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_upward (-0xf.fffffp-4 + 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_upward (0x1.000002p+0 - 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_upward (0x1.000002p+0 - 0x8p-152 i): Exception "Underflow" set
Failure: Real part of: catanh_upward (0x1.000002p+0 + 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_upward (0x1.000002p+0 + 0x8p-152 i): Exception "Underflow" set
Failure: Real part of: catanh_upward (0xf.fffffp-4 - 0x4p-128 i): Exception "Underflow" set
Failure: Real part of: catanh_upward (0xf.fffffp-4 + 0x4p-128 i): Exception "Underflow" set
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
The configure check always fail with clang:
conftest.c:5:58: error: expected string literal as argument of 'alias' attribute
5 | extern __typeof (__foo) foo __attribute__ ((weak, alias (__foo)));
| ^
conftest.c:6:58: error: expected string literal as argument of 'alias' attribute
6 | extern __typeof (__foo) bar __attribute__ ((weak, alias (foo)));
| ^
Reviewed-by: Sam James <sam@gentoo.org>
clang does not work by using whitespace for defining the -z option:
$ make test t=misc/tst-gcs-disabled
[...]
clang: error: no such file or directory: 'gcs=always'
Use the usual comma separate way.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
The constant should be used with c_cc, which for all supported ABIs
is defined as unsigned char. By using it as literar char constant,
clang triggers an error when compared with signal literal on ABIs that
define 'char' as unsigned.
On aarch64, clang shows:
../sysdeps/posix/fpathconf.c:118:21: error: right side of operator
converted from negative value to unsigned: -1 to 18446744073709551615
[-Werror]
#if _POSIX_VDISABLE == -1
~~~~~~~~~~~~~~~ ^ ~~
Reviewed-by: Collin Funk <collin.funk1@gmail.com>
clang issues:
key_call.c:459:20: error: equality comparison with extraneous parentheses [-Werror,-Wparentheses-equality]
459 | if ((kcp->client == (CLIENT *) NULL))
Instead of suppress the warning, just use the more usual comparison style.
Reviewed-by: Sam James <sam@gentoo.org>
A late change in C23, the resolution to CD2 comment GB-108, specified
that <inttypes.h> macros such as PRId8 expand to formats such that,
when an argument is passed in the promoted type that isn't
representable in the original type such as int8_t corresponding to the
format, it gets converted to that type before printing. (Previously,
the proper handling of such arguments was unclear; the case of direct
use of formats such as %hhd was clarified earlier in C23 development,
and had been fixed in glibc in 2006.) Implement the change to use
formats such as "hhd" for the affected macros, with associated tests.
Tested for x86_64 and x86.
Remove target implementations of roundeven(f)/lrint(f)/lround(f) and
use the math-use-builtins mechanism instead.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Cleanup _int_memalign. Simplify the logic. Add a seperate check
for mmap. Only release the tail chunk if it is at least MINSIZE.
Use the new mmap abstractions.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
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.
And remove some unused entries of the fallback table.
Checked on x86_64-linux-gnu and aarch64-linux-gnu.
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
The fma is required only for x == -0x1.da285cp-5 in FE_TONEAREST
to provide correctly rounded results.
Checked on x86_64-linux-gnu and i686-linux-gnu.
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
The fma is required only for x == +/-0x1.6371e8p-4f in FE_TOWARDZERO
to provide correctly rounded results.
Checked on x86_64-linux-gnu and aarch64-linux-gnu.
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
The fma is not required to provide correctly rounded and it helps
on !__FP_FAST_FMA ISAs.
Checked on x86_64-linux-gnu and i686-linux-gnu.
Reviewed-by: Paul Zimmermann <Paul.Zimmermann@inria.fr>
The fma is required only for inputs less than 0x1.0fd288p-127. Also
only add the extra check for !__FP_FAST_FMA targets.
Checked on x86_64-linux-gnu and aarch64-linux-gnu.
Reviewed-by: Paul Zimmermann <Paul.Zimmermann@inria.fr>
The fma is not strickly required to provide correctly rounded and
it helps on !__FP_FAST_FMA ABIs.
Checked on x86_64-linux-gnu and i686-linux-gnu.
Reviewed-by: Paul Zimmermann <Paul.Zimmermann@inria.fr>
This commit adds tests for the following use cases relevant to handing of
the SME state:
- fork() and vfork()
- clone() and clone3()
- signal handler
While most cases are trivial, the case of clone3() is more complicated since
the clone3() symbol is not public in Glibc.
To avoid having to check all possible ways clone3() may be called via other
public functions (e.g. vfork() or pthread_create()), we put together a test
that links directly with clone3.o. All the existing functions that have calls
to clone3() may not actually use it, in which case the outcome of such tests
would be unexpected. Having a direct call to the clone3() symbol in the test
allows to check precisely what we need to test: that the __arm_za_disable()
function is indeed called and has the desired effect.
Linking to clone3.o also requires linking to __arm_za_disable.o that in
turn requires the _dl_hwcap2 hidden symbol which to provide in the test
and initialise it before using.
Co-authored-by: Adhemerval Zanella Netto <adhemerval.zanella@linaro.org>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
This change adds a call to the __arm_za_disable() function immediately
before the SVC instruction inside clone() and clone3() wrappers. It also
adds a macro for inline clone() used in fork() and adds the same call to
the vfork implementation. This sets the ZA state of SME to "off" on return
from these functions (for both the child and the parent).
The __arm_za_disable() function is described in [1] (8.1.3). Note that
the internal Glibc name for this function is __libc_arm_za_disable().
When this change was originally proposed [2,3], it generated a long
discussion where several questions and concerns were raised. Here we
will address these concerns and explain why this change is useful and,
in fact, necessary.
In a nutshell, a C library that conforms to the AAPCS64 spec [1] (pertinent
to this change, mainly, the chapters 6.2 and 6.6), should have a call to the
__arm_za_disable() function in clone() and clone3() wrappers. The following
explains in detail why this is the case.
When we consider using the __arm_za_disable() function inside the clone()
and clone3() libc wrappers, we talk about the C library subroutines clone()
and clone3() rather than the syscalls with similar names. In the current
version of Glibc, clone() is public and clone3() is private, but it being
private is not pertinent to this discussion.
We will begin with stating that this change is NOT a bug fix for something
in the kernel. The requirement to call __arm_za_disable() does NOT come from
the kernel. It also is NOT needed to satisfy a contract between the kernel
and userspace. This is why it is not for the kernel documentation to describe
this requirement. This requirement is instead needed to satisfy a pure userspace
scheme outlined in [1] and to make sure that software that uses Glibc (or any
other C library that has correct handling of SME states (see below)) conforms
to [1] without having to unnecessarily become SME-aware thus losing portability.
To recap (see [1] (6.2)), SME extension defines SME state which is part of
processor state. Part of this SME state is ZA state that is necessary to
manage ZA storage register in the context of the ZA lazy saving scheme [1]
(6.6). This scheme exists because it would be challenging to handle ZA
storage of SME in either callee-saved or caller-saved manner.
There are 3 kinds of ZA state that are defined in terms of the PSTATE.ZA
bit and the TPIDR2_EL0 register (see [1] (6.6.3)):
- "off": PSTATE.ZA == 0
- "active": PSTATE.ZA == 1 TPIDR2_EL0 == null
- "dormant": PSTATE.ZA == 1 TPIDR2_EL0 != null
As [1] (6.7.2) outlines, every subroutine has exactly one SME-interface
depending on the permitted ZA-states on entry and on normal return from
a call to this subroutine. Callers of a subroutine must know and respect
the ZA-interface of the subroutines they are using. Using a subroutine
in a way that is not permitted by its ZA-interface is undefined behaviour.
In particular, clone() and clone3() (the C library functions) have the
ZA-private interface. This means that the permitted ZA-states on entry
are "off" and "dormant" and that the permitted states on return are "off"
or "dormant" (but if and only if it was "dormant" on entry).
This means that both functions in question should correctly handle both
"off" and "dormant" ZA-states on entry. The conforming states on return
are "off" and "dormant" (if inbound state was already "dormant").
This change ensures that the ZA-state on return is always "off". Note,
that, in the context of clone() and clone3(), "on return" means a point
when execution resumes at certain address after transferring from clone()
or clone3(). For the caller (we may refer to it as "parent") this is the
return address in the link register where the RET instruction jumps. For
the "child", this is the target branch address.
So, the "off" state on return is permitted and conformant. Why can't we
retain the "dormant" state? In theory, we can, but we shouldn't, here is
why.
Every subroutine with a private-ZA interface, including clone() and clone3(),
must comply with the lazy saving scheme [1] (6.7.2). This puts additional
responsibility on a subroutine if ZA-state on return is "dormant" because
this state has special meaning. The "caller" (that is the place in code
where execution is transferred to, so this include both "parent" and "child")
may check the ZA-state and use it as per the spec of the "dormant" state that
is outlined in [1] (6.6.6 and 6.6.7).
Conforming to this would require more code inside of clone() and clone3()
which hardly is desirable.
For the return to "parent" this could be achieved in theory, but given that
neither clone() nor clone3() are supposed to be used in the middle of an
SME operation, if wouldn't be useful. For the "return" to "child" this
would be particularly difficult to achieve given the complexity of these
functions and their interfaces. Most importantly, it would be illegal
and somewhat meaningless to allow a "child" to start execution in the
"dormant" ZA-state because the very essence of the "dormant" state implies
that there is a place to return and that there is some outer context that
we are allowed to interact with.
To sum up, calling __arm_za_disable() to ensure the "off" ZA-state when the
execution resumes after a call to clone() or clone3() is correct and also
the most simple way to conform to [1].
Can there be situations when we can avoid calling __arm_za_disable()?
Calling __arm_za_disable() implies certain (sufficiently small) overhead,
so one might rightly ponder avoiding making a call to this function when
we can afford not to. The most trivial cases like this (e.g. when the
calling thread doesn't have access to SME or to the TPIDR2_EL0 register)
are already handled by this function (see [1] (8.1.3 and 8.1.2)). Reasoning
about other possible use cases would require making code inside clone() and
clone3() more complicated and it would defeat the point of trying to make
an optimisation of not calling __arm_za_disable().
Why can't the kernel do this instead?
The handling of SME state by the kernel is described in [4]. In short,
kernel must not impose a specific ZA-interface onto a userspace function.
Interaction with the kernel happens (among other thing) via system calls.
In Glibc many of the system calls (notably, including SYS_clone and
SYS_clone3) are used via wrappers, and the kernel has no control of them
and, moreover, it cannot dictate how these wrappers should behave because
it is simply outside of the kernel's remit.
However, in certain cases, the kernel may ensure that a "child" doesn't
start in an incorrect state. This is what is done by the recent change
included in 6.16 kernel [5]. This is not enough to ensure that code that
uses clone() and clone3() function conforms to [1] when it runs on a
system that provides SME, hence this change.
[1]: https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
[2]: https://inbox.sourceware.org/libc-alpha/20250522114828.2291047-1-yury.khrustalev@arm.com
[3]: https://inbox.sourceware.org/libc-alpha/20250609121407.3316070-1-yury.khrustalev@arm.com
[4]: https://www.kernel.org/doc/html/v6.16/arch/arm64/sme.html
[5]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cde5c32db55740659fca6d56c09b88800d88fd29
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
A common sequence of instructions is used in several places
in assembly files, so define it in one place as an assembly
macro.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
* posix/glob.c (__glob): Strip trailing slashes before the recursive
call, so it is not called for every slash in the pattern.
* posix/tst-glob-bz30635.c: Add two test cases that would previously
segmentation fault. The first test has many trailing slashes and the
second has many slashes following a wildcard character.
* posix/Makefile (tests): Add the new test.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
strerror, strsignal, and their variants should return unique strings for
each known (and, depending on the function, unknown) error/signal. Add
tests to verify this for strerror, strerror_r (GNU and XSI compliant
variants), and strerror_l (for the C locale), strerrordesc_np,
strsignal, sigabbrev_np, and sigdescr_np.
Co-authored-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Use __seg_gs named address space qualifiers in PTR_MANGLE() and
PTR_DEMANGLE() macros to access the pointer_guard field in the TCB.
This change allows the compiler to eliminate redundant reads of
the variable, reducing the number of reads from 105 to 94 and
decreasing the text size of the library by 280 bytes.
While at it, fix a few trivial whitespace issues as well
Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Use __seg_fs named address space qualifiers in PTR_MANGLE() and
PTR_DEMANGLE() macros to access the pointer_guard field in the TCB.
This change allows the compiler to eliminate redundant reads of
the variable, reducing the number of reads from 98 to 89 and
decreasing the text size of the library by 512 bytes.
While at it, fix a few trivial whitespace issues as well.
Signed-off-by: Uros Bizjak <ubizjak@gmail.com>
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
This patch adds two tests that verify correct behavior of getaddrinfo
when DNS resolution fails with a temporary error. Both tests ensure
that getaddrinfo returns EAI_AGAIN in cases where no valid address can
be resolved due to network or resolver failure.
* tst-getaddrinfo-eai-again.c
Runs inside the glibc test-container without any DNS server
configured. The test performs queries using AF_INET, AF_INET6,
and AF_UNSPEC and verifies that getaddrinfo returns EAI_AGAIN
when resolution fails.
* tst-getaddrinfo-eai-again-timeout.c
Runs outside of the container but uses the resolv_test framework
to simulate network failures. The test covers two failure modes:
- No response from the server (resolv_response_drop)
- Zero-length reply from the server
In both cases, getaddrinfo is expected to return EAI_AGAIN.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
POSIX requires that the buffer used by getdelim/getline add a
terminating NUL whenever an EOF is read.
* libio/iogetdelim.c (__getdelim): Add a NUL byte when the first
__underflow is called.
* libio/tst-getdelim.c (do_test): Add a test case for the bug.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
When debugging library loading issues with `LD_DEBUG`, it can be
frustrating to see logs for files in a directory are searched, but the
target library is skipped over without any indication of why. Add
reporting to all paths which reject a library as `ENOENT`.
Originally created for minimum-OS version detection, but that has since
been removed in b46d250656 (Remove kernel version check, 2022-02-21).
The remaining codepaths are still useful.
Signed-off-by: Ben Boeckel <ben.boeckel@kitware.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
The gcc implements fmod as a built-in for x86, so disable it to
benchmark the C implementation.
Also, make fmod and fmodf use the workload directive to measure
the reciprocal throughput.