aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile5
-rw-r--r--lib/libarchive/config_freebsd.h126
-rw-r--r--lib/libarchive/tests/Makefile13
-rw-r--r--lib/libc/gen/Makefile.inc5
-rw-r--r--lib/libc/gen/Symbol.map2
-rw-r--r--lib/libc/gen/dlopen.314
-rw-r--r--lib/libc/gen/memfd_create.c23
-rw-r--r--lib/libc/gen/pause.32
-rw-r--r--lib/libc/gen/posix_spawn.312
-rw-r--r--lib/libc/gen/posix_spawn.c5
-rw-r--r--lib/libc/gen/posix_spawn_file_actions_addopen.329
-rw-r--r--lib/libc/gen/sysctl.327
-rw-r--r--lib/libc/stdlib/atexit.33
-rw-r--r--lib/libc/tests/string/Makefile2
-rw-r--r--lib/libc/tests/string/strrchr_test.c156
-rw-r--r--lib/libcasper/services/cap_dns/cap_dns.c2
-rw-r--r--lib/libexpat/expat_config.h6
-rw-r--r--lib/libexpat/libbsdxml.34
-rw-r--r--lib/libgcc_s/Symbol.map1
-rw-r--r--lib/libifconfig/libifconfig.c4
-rw-r--r--lib/libifconfig/libifconfig_carp.c5
-rw-r--r--lib/libifconfig/libifconfig_sfp.c238
-rw-r--r--lib/libifconfig/libifconfig_sfp.h27
-rw-r--r--lib/libifconfig/sfp.lua120
-rw-r--r--lib/liblzma/config.h10
-rw-r--r--lib/libmixer/mixer.c8
-rw-r--r--lib/libpfctl/libpfctl.c4
-rw-r--r--lib/libpmc/libpmc_json.cc5
-rw-r--r--lib/libpmc/pmclog.329
-rw-r--r--lib/libpmc/pmclog.c4
-rw-r--r--lib/libpmc/pmclog.h6
-rw-r--r--lib/libsecureboot/h/verify_file.h5
-rw-r--r--lib/libsecureboot/tests/tvo.c6
-rw-r--r--lib/libsecureboot/vectx.c48
-rw-r--r--lib/libsecureboot/verify_file.c3
-rw-r--r--lib/libsys/_exit.29
-rw-r--r--lib/libsys/fork.22
-rw-r--r--lib/libsys/mq_open.223
-rw-r--r--lib/libsys/ntp_adjtime.26
-rw-r--r--lib/libsys/procctl.248
-rw-r--r--lib/libsys/shm_open.231
-rw-r--r--lib/libsys/stat.22
-rw-r--r--lib/libsys/x86/pkru.320
-rw-r--r--lib/libsysdecode/Makefile2
-rw-r--r--lib/libsysdecode/netlink.c94
-rw-r--r--lib/libsysdecode/sysdecode.h1
-rw-r--r--lib/libthr/libthr.325
-rw-r--r--lib/libzstd/Makefile4
-rw-r--r--lib/msun/Makefile26
-rw-r--r--lib/msun/Symbol.map23
-rw-r--r--lib/msun/aarch64/Symbol.map10
-rw-r--r--lib/msun/aarch64/fenv.c95
-rw-r--r--lib/msun/aarch64/fenv.h55
-rw-r--r--lib/msun/amd64/Makefile.inc1
-rw-r--r--lib/msun/amd64/fenv.c37
-rw-r--r--lib/msun/arm/Makefile.inc1
-rw-r--r--lib/msun/arm/fenv.c138
-rw-r--r--lib/msun/arm/fenv.h58
-rw-r--r--lib/msun/i387/Makefile.inc1
-rw-r--r--lib/msun/i387/fenv.c37
-rw-r--r--lib/msun/man/fmax.320
-rw-r--r--lib/msun/man/fmaximum.3103
-rw-r--r--lib/msun/man/fmaximum_mag.3102
-rw-r--r--lib/msun/man/fmaximum_num.3113
-rw-r--r--lib/msun/man/math.312
-rw-r--r--lib/msun/powerpc/Makefile.inc1
-rw-r--r--lib/msun/powerpc/fenv.c88
-rw-r--r--lib/msun/powerpc/fenv.h51
-rw-r--r--lib/msun/riscv/Makefile.inc1
-rw-r--r--lib/msun/riscv/fenv.c89
-rw-r--r--lib/msun/riscv/fenv.h51
-rw-r--r--lib/msun/src/math.h18
-rw-r--r--lib/msun/src/s_fmaximum.c65
-rw-r--r--lib/msun/src/s_fmaximum_mag.c73
-rw-r--r--lib/msun/src/s_fmaximum_magf.c68
-rw-r--r--lib/msun/src/s_fmaximum_magl.c62
-rw-r--r--lib/msun/src/s_fmaximum_num.c74
-rw-r--r--lib/msun/src/s_fmaximum_numf.c70
-rw-r--r--lib/msun/src/s_fmaximum_numl.c63
-rw-r--r--lib/msun/src/s_fmaximumf.c60
-rw-r--r--lib/msun/src/s_fmaximuml.c54
-rw-r--r--lib/msun/src/s_fminimum.c66
-rw-r--r--lib/msun/src/s_fminimum_mag.c74
-rw-r--r--lib/msun/src/s_fminimum_magf.c69
-rw-r--r--lib/msun/src/s_fminimum_magl.c63
-rw-r--r--lib/msun/src/s_fminimum_num.c76
-rw-r--r--lib/msun/src/s_fminimum_numf.c71
-rw-r--r--lib/msun/src/s_fminimum_numl.c65
-rw-r--r--lib/msun/src/s_fminimumf.c61
-rw-r--r--lib/msun/src/s_fminimuml.c55
-rw-r--r--lib/msun/tests/Makefile1
-rw-r--r--lib/msun/tests/fmaximum_fminimum_test.c262
-rw-r--r--lib/msun/x86/fenv.h29
93 files changed, 3469 insertions, 369 deletions
diff --git a/lib/Makefile b/lib/Makefile
index c3a95f00d4ef..1cb2d1d89e39 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -34,7 +34,6 @@ SUBDIR= ${SUBDIR_BOOTSTRAP} \
lib9p \
libalias \
libarchive \
- libauditd \
libbegemot \
libblocksruntime \
libbsddialog \
@@ -91,7 +90,6 @@ SUBDIR= ${SUBDIR_BOOTSTRAP} \
librss \
librt \
librtld_db \
- libsamplerate \
libsbuf \
libsmb \
libstdbuf \
@@ -174,6 +172,7 @@ SUBDIR+= clang
.endif
.endif
+SUBDIR.${MK_AUDIT}+= libauditd
SUBDIR.${MK_CUSE}+= libcuse
SUBDIR.${MK_TOOLCHAIN}+=libpe
SUBDIR.${MK_DIALOG}+= libdpv libfigpar
@@ -237,7 +236,7 @@ SUBDIR.${MK_RADIUS_SUPPORT}+= libradius
SUBDIR.${MK_SENDMAIL}+= libmilter libsm libsmdb libsmutil
SUBDIR.${MK_TELNET}+= libtelnet
SUBDIR.${MK_SOUND}+= libmixer
-SUBDIR.${MK_CUSE}.${MK_SOUND}+= virtual_oss
+SUBDIR.${MK_CUSE}.${MK_SOUND}+= libsamplerate virtual_oss
SUBDIR.${MK_TESTS_SUPPORT}+= atf
SUBDIR.${MK_TESTS_SUPPORT}+= liblutok
SUBDIR.${MK_TESTS}+= tests
diff --git a/lib/libarchive/config_freebsd.h b/lib/libarchive/config_freebsd.h
index 1601adddd0de..41d91cea9bd3 100644
--- a/lib/libarchive/config_freebsd.h
+++ b/lib/libarchive/config_freebsd.h
@@ -26,30 +26,11 @@
*/
#define __LIBARCHIVE_CONFIG_H_INCLUDED 1
-#include <osreldate.h>
-
-/* FreeBSD 5.0 and later has ACL and extattr support. */
-#if __FreeBSD__ > 4
-#define ARCHIVE_ACL_FREEBSD 1
-#define ARCHIVE_XATTR_FREEBSD 1
-#define HAVE_ACL_GET_PERM_NP 1
-#define HAVE_ARC4RANDOM_BUF 1
-#define HAVE_STRUCT_XVFSCONF 1
-#define HAVE_SYS_ACL_H 1
-#define HAVE_SYS_EXTATTR_H 1
-#if __FreeBSD__ > 7
-/* FreeBSD 8.0 and later has NFSv4 ACL support */
-#define ARCHIVE_ACL_FREEBSD_NFS4 1
-#define HAVE_ACL_GET_LINK_NP 1
-#define HAVE_ACL_IS_TRIVIAL_NP 1
-#define HAVE_ACL_SET_LINK_NP 1
-#endif /* __FreeBSD__ > 7 */
-#endif /* __FreeBSD__ > 4 */
-
#ifdef WITH_OPENSSL
#define HAVE_LIBCRYPTO 1
#define HAVE_OPENSSL_EVP_H 1
#define HAVE_OPENSSL_MD5_H 1
+#define HAVE_OPENSSL_OPENSSLV_H 1
#define HAVE_OPENSSL_RIPEMD_H 1
#define HAVE_OPENSSL_SHA_H 1
#define HAVE_OPENSSL_SHA256_INIT 1
@@ -75,13 +56,59 @@
#define HAVE_SHA512_INIT 1
#endif
+#define ARCHIVE_ACL_FREEBSD 1
+#define ARCHIVE_ACL_FREEBSD_NFS4 1
+#define ARCHIVE_XATTR_FREEBSD 1
+#define HAVE_ACL_ADD_FLAG_NP 1
+#define HAVE_ACL_ADD_PERM 1
+#define HAVE_ACL_CLEAR_FLAGS_NP 1
+#define HAVE_ACL_CLEAR_PERMS 1
+#define HAVE_ACL_CREATE_ENTRY 1
+#define HAVE_ACL_DELETE_DEF_FILE 1
+#define HAVE_ACL_ENTRY_T 1
+#define HAVE_ACL_FREE 1
+#define HAVE_ACL_GET_BRAND_NP 1
+#define HAVE_ACL_GET_ENTRY 1
+#define HAVE_ACL_GET_ENTRY_TYPE_NP 1
+#define HAVE_ACL_GET_FD 1
+#define HAVE_ACL_GET_FD_NP 1
+#define HAVE_ACL_GET_FILE 1
+#define HAVE_ACL_GET_FLAGSET_NP 1
+#define HAVE_ACL_GET_FLAG_NP 1
+#define HAVE_ACL_GET_LINK_NP 1
+#define HAVE_ACL_GET_PERMSET 1
+#define HAVE_ACL_GET_PERM_NP 1
+#define HAVE_ACL_GET_QUALIFIER 1
+#define HAVE_ACL_GET_TAG_TYPE 1
+#define HAVE_ACL_INIT 1
+#define HAVE_ACL_IS_TRIVIAL_NP 1
+#define HAVE_ACL_PERMSET_T 1
+#define HAVE_ACL_SET_ENTRY_TYPE_NP 1
+#define HAVE_ACL_SET_FD 1
+#define HAVE_ACL_SET_FD_NP 1
+#define HAVE_ACL_SET_FILE 1
+#define HAVE_ACL_SET_LINK_NP 1
+#define HAVE_ACL_SET_QUALIFIER 1
+#define HAVE_ACL_SET_TAG_TYPE 1
+#define HAVE_ACL_T 1
+#define HAVE_ACL_TAG_T 1
+#define HAVE_ARC4RANDOM_BUF 1
#define HAVE_BSDXML_H 1
#define HAVE_BZLIB_H 1
#define HAVE_CHFLAGS 1
#define HAVE_CHOWN 1
#define HAVE_CHROOT 1
+#define HAVE_CLOSEFROM 1
+#define HAVE_CLOSE_RANGE 1
#define HAVE_CTIME_R 1
#define HAVE_CTYPE_H 1
+#ifndef __linux__
+#define HAVE_D_MD_ORDER 1
+#endif
+#define HAVE_DECL_ACL_SYNCHRONIZE 1
+#define HAVE_DECL_ACL_TYPE_EXTENDED 0
+#define HAVE_DECL_ACL_TYPE_NFS4 1
+#define HAVE_DECL_ACL_USER 1
#define HAVE_DECL_EXTATTR_NAMESPACE_USER 1
#define HAVE_DECL_INT32_MAX 1
#define HAVE_DECL_INT32_MIN 1
@@ -95,15 +122,21 @@
#define HAVE_DECL_UINT32_MAX 1
#define HAVE_DECL_UINT64_MAX 1
#define HAVE_DECL_UINTMAX_MAX 1
+#define HAVE_DECL_XATTR_NOFOLLOW 0
#define HAVE_DIRENT_H 1
#define HAVE_DIRFD 1
#define HAVE_DLFCN_H 1
-#ifndef __linux__
-#define HAVE_D_MD_ORDER 1
-#endif
#define HAVE_EFTYPE 1
#define HAVE_EILSEQ 1
#define HAVE_ERRNO_H 1
+#define HAVE_EXTATTR_GET_FD 1
+#define HAVE_EXTATTR_GET_FILE 1
+#define HAVE_EXTATTR_GET_LINK 1
+#define HAVE_EXTATTR_LIST_FD 1
+#define HAVE_EXTATTR_LIST_FILE 1
+#define HAVE_EXTATTR_LIST_LINK 1
+#define HAVE_EXTATTR_SET_FD 1
+#define HAVE_EXTATTR_SET_LINK 1
#define HAVE_FCHDIR 1
#define HAVE_FCHFLAGS 1
#define HAVE_FCHMOD 1
@@ -120,26 +153,33 @@
#define HAVE_FSTATFS 1
#define HAVE_FSTATVFS 1
#define HAVE_FTRUNCATE 1
+#define HAVE_FUTIMENS 1
#define HAVE_FUTIMES 1
#define HAVE_FUTIMESAT 1
+#define HAVE_GETEGID 1
#define HAVE_GETEUID 1
#define HAVE_GETGRGID_R 1
#define HAVE_GETGRNAM_R 1
#define HAVE_GETLINE 1
-#define HAVE_GETOPT_OPTRESET 1
#define HAVE_GETPID 1
#define HAVE_GETPWNAM_R 1
#define HAVE_GETPWUID_R 1
+#define HAVE_GETRESGID 1
+#define HAVE_GETRESUID 1
#define HAVE_GETVFSBYNAME 1
#define HAVE_GMTIME_R 1
#define HAVE_GRP_H 1
#define HAVE_INTMAX_T 1
#define HAVE_INTTYPES_H 1
+#define HAVE_ISSETUGID 1
#define HAVE_LANGINFO_H 1
#define HAVE_LCHFLAGS 1
#define HAVE_LCHMOD 1
#define HAVE_LCHOWN 1
+#define HAVE_LIBBZ2 1
+#define HAVE_LIBLZMA 1
#define HAVE_LIBZ 1
+#define HAVE_LIBZSTD 1
#define HAVE_LIMITS_H 1
#define HAVE_LINK 1
#define HAVE_LINKAT 1
@@ -148,9 +188,10 @@
#define HAVE_LONG_LONG_INT 1
#define HAVE_LSTAT 1
#define HAVE_LUTIMES 1
+#define HAVE_LZMA_H 1
+#define HAVE_LZMA_STREAM_ENCODER_MT 1
#define HAVE_MBRTOWC 1
#define HAVE_MEMMOVE 1
-#define HAVE_MEMORY_H 1
#define HAVE_MEMSET 1
#define HAVE_MKDIR 1
#define HAVE_MKFIFO 1
@@ -162,7 +203,16 @@
#define HAVE_PIPE 1
#define HAVE_POLL 1
#define HAVE_POLL_H 1
+#if 0
+/*
+ * FreeBSD does have posix_spawn() and posix_spawnp(), but they are
+ * wrappers around fork() + execve() and fork() + execvp() respectively,
+ * so there is no reason to prefer them to the simpler alternatives,
+ * unlike e.g. Darwin where posix_spawn() is a system call.
+ */
+#define HAVE_POSIX_SPAWN 1
#define HAVE_POSIX_SPAWNP 1
+#endif
#define HAVE_PTHREAD_H 1
#define HAVE_PWD_H 1
#define HAVE_READLINK 1
@@ -182,6 +232,7 @@
#define HAVE_STATVFS 1
#define HAVE_STDARG_H 1
#define HAVE_STDINT_H 1
+#define HAVE_STDIO_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRCHR 1
#define HAVE_STRDUP 1
@@ -192,6 +243,8 @@
#define HAVE_STRING_H 1
#define HAVE_STRNLEN 1
#define HAVE_STRRCHR 1
+#define HAVE_STRUCT_STATFS 1
+#define HAVE_STRUCT_STATFS_F_IOSIZE 1
#define HAVE_STRUCT_STATFS_F_NAMEMAX 1
#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1
#define HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1
@@ -200,13 +253,17 @@
#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1
#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1
#define HAVE_STRUCT_TM_TM_GMTOFF 1
+#define HAVE_STRUCT_VFSCONF 1
+#define HAVE_STRUCT_XVFSCONF 1
#define HAVE_SYMLINK 1
+#define HAVE_SYSCONF 1
+#define HAVE_SYS_ACL_H 1
#define HAVE_SYS_CDEFS_H 1
+#define HAVE_SYS_EXTATTR_H 1
#define HAVE_SYS_IOCTL_H 1
#define HAVE_SYS_MOUNT_H 1
#define HAVE_SYS_PARAM_H 1
#define HAVE_SYS_POLL_H 1
-#define HAVE_SYS_QUEUE_H 1
#define HAVE_SYS_SELECT_H 1
#define HAVE_SYS_STATVFS_H 1
#define HAVE_SYS_STAT_H 1
@@ -214,6 +271,8 @@
#define HAVE_SYS_TYPES_H 1
#define HAVE_SYS_UTSNAME_H 1
#define HAVE_SYS_WAIT_H 1
+#define HAVE_TCGETATTR 1
+#define HAVE_TCSETATTR 1
#define HAVE_TIMEGM 1
#define HAVE_TIME_H 1
#define HAVE_TZSET 1
@@ -224,6 +283,7 @@
#define HAVE_UNSIGNED_LONG_LONG 1
#define HAVE_UNSIGNED_LONG_LONG_INT 1
#define HAVE_UTIME 1
+#define HAVE_UTIMENSAT 1
#define HAVE_UTIMES 1
#define HAVE_UTIME_H 1
#define HAVE_VFORK 1
@@ -240,19 +300,11 @@
#define HAVE_WMEMCPY 1
#define HAVE_WMEMMOVE 1
#define HAVE_ZLIB_H 1
+#define HAVE_ZSTD_H 1
+#define HAVE_ZSTD_compressStream 1
+#define HAVE_ZSTD_minCLevel 1
#define TIME_WITH_SYS_TIME 1
-#if __FreeBSD_version >= 1100056
-#define HAVE_FUTIMENS 1
-#define HAVE_UTIMENSAT 1
-#endif
-
-/* FreeBSD 4 and earlier lack intmax_t/uintmax_t */
-#if __FreeBSD__ < 5
-#define intmax_t int64_t
-#define uintmax_t uint64_t
-#endif
-
/* FreeBSD defines for archive_hash.h */
#ifdef WITH_OPENSSL
#define ARCHIVE_CRYPTO_MD5_OPENSSL 1
diff --git a/lib/libarchive/tests/Makefile b/lib/libarchive/tests/Makefile
index 880c0d3ce0c6..3a03725054f4 100644
--- a/lib/libarchive/tests/Makefile
+++ b/lib/libarchive/tests/Makefile
@@ -131,6 +131,8 @@ TESTS_SRCS= \
test_read_format_ar.c \
test_read_format_cab.c \
test_read_format_cab_filename.c \
+ test_read_format_cab_lzx_oob.c \
+ test_read_format_cab_skip_malformed.c \
test_read_format_cpio_afio.c \
test_read_format_cpio_bin.c \
test_read_format_cpio_bin_Z.c \
@@ -159,6 +161,7 @@ TESTS_SRCS= \
test_read_format_iso_Z.c \
test_read_format_iso_multi_extent.c \
test_read_format_iso_xorriso.c \
+ test_read_format_iso_zisofs_overflow.c \
test_read_format_isorr_rr_moved.c \
test_read_format_isojoliet_bz2.c \
test_read_format_isojoliet_long.c \
@@ -172,10 +175,12 @@ TESTS_SRCS= \
test_read_format_lha_bugfix_0.c \
test_read_format_lha_filename.c \
test_read_format_lha_filename_utf16.c \
+ test_read_format_lha_oversize_header.c \
test_read_format_mtree.c \
test_read_format_mtree_crash747.c \
test_read_format_pax_bz2.c \
test_read_format_rar.c \
+ test_read_format_rar5_loop_bug.c \
test_read_format_rar5.c \
test_read_format_rar_encryption.c \
test_read_format_rar_encryption_data.c \
@@ -242,6 +247,7 @@ TESTS_SRCS= \
test_sparse_basic.c \
test_tar_filenames.c \
test_tar_large.c \
+ test_v7tar_filename_encoding.c \
test_warn_missing_hardlink_target.c \
test_ustar_filenames.c \
test_ustar_filename_encoding.c \
@@ -499,8 +505,10 @@ ${PACKAGE}FILES+= test_read_format_7zip_lzma2_riscv.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_lzma2_sparc.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_malformed.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_malformed2.7z.uu
+${PACKAGE}FILES+= test_read_format_7zip_malformed3.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_packinfo_digests.7z.uu
${PACKAGE}FILES+= test_read_format_7zip_ppmd.7z.uu
+${PACKAGE}FILES+= test_read_format_7zip_sfx_elf64trunc.elf.uu
${PACKAGE}FILES+= test_read_format_7zip_sfx_elf.elf.uu
${PACKAGE}FILES+= test_read_format_7zip_sfx_modified_pe.exe.uu
${PACKAGE}FILES+= test_read_format_7zip_sfx_pe.exe.uu
@@ -517,6 +525,8 @@ ${PACKAGE}FILES+= test_read_format_cab_1.cab.uu
${PACKAGE}FILES+= test_read_format_cab_2.cab.uu
${PACKAGE}FILES+= test_read_format_cab_3.cab.uu
${PACKAGE}FILES+= test_read_format_cab_filename_cp932.cab.uu
+${PACKAGE}FILES+= test_read_format_cab_lzx_oob.cab.uu
+${PACKAGE}FILES+= test_read_format_cab_skip_malformed.cab.uu
${PACKAGE}FILES+= test_read_format_cpio_bin_be.cpio.uu
${PACKAGE}FILES+= test_read_format_cpio_bin_le.cpio.uu
${PACKAGE}FILES+= test_read_format_cpio_filename_cp866.cpio.uu
@@ -552,6 +562,7 @@ ${PACKAGE}FILES+= test_read_format_iso_rockridge_ce.iso.Z.uu
${PACKAGE}FILES+= test_read_format_iso_rockridge_new.iso.Z.uu
${PACKAGE}FILES+= test_read_format_iso_rockridge_rr_moved.iso.Z.uu
${PACKAGE}FILES+= test_read_format_iso_xorriso.iso.Z.uu
+${PACKAGE}FILES+= test_read_format_iso_zisofs_overflow.iso.uu
${PACKAGE}FILES+= test_read_format_iso_zisofs.iso.Z.uu
${PACKAGE}FILES+= test_read_format_lha_bugfix_0.lzh.uu
${PACKAGE}FILES+= test_read_format_lha_filename_cp932.lzh.uu
@@ -563,6 +574,7 @@ ${PACKAGE}FILES+= test_read_format_lha_header3.lzh.uu
${PACKAGE}FILES+= test_read_format_lha_lh0.lzh.uu
${PACKAGE}FILES+= test_read_format_lha_lh6.lzh.uu
${PACKAGE}FILES+= test_read_format_lha_lh7.lzh.uu
+${PACKAGE}FILES+= test_read_format_lha_oversize_header.lzh.uu
${PACKAGE}FILES+= test_read_format_lha_withjunk.lzh.uu
${PACKAGE}FILES+= test_read_format_mtree.mtree.uu
${PACKAGE}FILES+= test_read_format_mtree_crash747.mtree.bz2.uu
@@ -615,6 +627,7 @@ ${PACKAGE}FILES+= test_read_format_rar5_dirdata.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_distance_overflow.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_encrypted.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_encrypted_filenames.rar.uu
+${PACKAGE}FILES+= test_read_format_rar5_loop_bug.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_solid_encrypted.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_solid_encrypted_filenames.rar.uu
${PACKAGE}FILES+= test_read_format_rar5_extra_field_version.rar.uu
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index 28e55f58ccf3..c31f789fd1d1 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -468,8 +468,8 @@ MLINKS+=posix_spawn.3 posix_spawnp.3 \
posix_spawn_file_actions_addopen.3 posix_spawn_file_actions_addclose.3 \
posix_spawn_file_actions_addopen.3 posix_spawn_file_actions_addclosefrom_np.3 \
posix_spawn_file_actions_addopen.3 posix_spawn_file_actions_adddup2.3 \
- posix_spawn_file_actions_addopen.3 posix_spawn_file_actions_addchdir_np.3 \
- posix_spawn_file_actions_addopen.3 posix_spawn_file_actions_addfchdir_np.3 \
+ posix_spawn_file_actions_addopen.3 posix_spawn_file_actions_addchdir.3 \
+ posix_spawn_file_actions_addopen.3 posix_spawn_file_actions_addfchdir.3 \
posix_spawn_file_actions_init.3 posix_spawn_file_actions_destroy.3 \
posix_spawnattr_getflags.3 posix_spawnattr_setflags.3 \
posix_spawnattr_getexecfd_np.3 posix_spawnattr_setexecfd_np.3 \
@@ -562,6 +562,7 @@ MLINKS+=unvis.3 strunvis.3 \
unvis.3 strunvisx.3
MLINKS+=vis.3 nvis.3 \
vis.3 snvis.3 \
+ vis.3 stravis.3 \
vis.3 strenvisx.3 \
vis.3 strnunvis.3 \
vis.3 strnunvisx.3 \
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index ddbd0522e13f..60f34b3a1923 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -475,6 +475,8 @@ FBSD_1.8 {
};
FBSD_1.9 {
+ posix_spawn_file_actions_addchdir;
+ posix_spawn_file_actions_addfchdir;
posix_spawnattr_getexecfd_np;
posix_spawnattr_getprocdescp_np;
posix_spawnattr_setexecfd_np;
diff --git a/lib/libc/gen/dlopen.3 b/lib/libc/gen/dlopen.3
index 340545114114..2f10c17a4f53 100644
--- a/lib/libc/gen/dlopen.3
+++ b/lib/libc/gen/dlopen.3
@@ -164,6 +164,20 @@ Symbols from the loaded library are put before global symbols when
resolving symbolic references originated from the library.
.El
.Pp
+A special syntax for the
+.Fa path
+is supported, in the form of
+.Dl #number/name .
+The
+.Ql number
+should be a decimal number, which references an open file descriptor,
+and which must be also listed in the environment variable
+.Ev LD_LIBRARY_PATH_FDS .
+In this case, the linker tries to load an object that can be opened by
+.Ql openat(number, path, O_RDONLY) .
+This feature is only available to trusted processes, i.e.,
+the activated image must be not set-uid or set-gid.
+.Pp
If
.Fn dlopen
fails, it returns a null pointer, and sets an error condition which may
diff --git a/lib/libc/gen/memfd_create.c b/lib/libc/gen/memfd_create.c
index 78131f46d7b1..8e6c93be4337 100644
--- a/lib/libc/gen/memfd_create.c
+++ b/lib/libc/gen/memfd_create.c
@@ -95,16 +95,25 @@ memfd_create(const char *name, unsigned int flags)
npgs = getpagesizes(pgs, nitems(pgs));
if (npgs == -1)
goto clean;
- pgsize = (size_t)1 << ((flags & MFD_HUGE_MASK) >> MFD_HUGE_SHIFT);
- for (pgidx = 0; pgidx < npgs; pgidx++) {
- if (pgsize == pgs[pgidx])
- break;
- }
- if (pgidx == npgs) {
- errno = EOPNOTSUPP;
+ else if (npgs == 1) {
+ errno = ENOSYS;
goto clean;
}
+ if ((flags & MFD_HUGE_MASK) == 0) {
+ pgidx = 1;
+ } else {
+ pgsize = 1UL << ((flags & MFD_HUGE_MASK) >> MFD_HUGE_SHIFT);
+ for (pgidx = 1; pgidx < npgs; pgidx++) {
+ if (pgsize == pgs[pgidx])
+ break;
+ }
+ if (pgidx == npgs) {
+ errno = EOPNOTSUPP;
+ goto clean;
+ }
+ }
+
memset(&slc, 0, sizeof(slc));
slc.psind = pgidx;
slc.alloc_policy = SHM_LARGEPAGE_ALLOC_DEFAULT;
diff --git a/lib/libc/gen/pause.3 b/lib/libc/gen/pause.3
index 6b17ae10777d..85257071ce2f 100644
--- a/lib/libc/gen/pause.3
+++ b/lib/libc/gen/pause.3
@@ -77,7 +77,7 @@ A
system call first appeared in the Programmer's Workbench (PWB/UNIX)
and was then ported to
.At v7 .
-It was reimplemeted as a wrapper around the
+It was reimplemented as a wrapper around the
.Fn sigpause
and
.Fn sigblock
diff --git a/lib/libc/gen/posix_spawn.3 b/lib/libc/gen/posix_spawn.3
index f7489890db31..ad66d1a426c4 100644
--- a/lib/libc/gen/posix_spawn.3
+++ b/lib/libc/gen/posix_spawn.3
@@ -446,11 +446,11 @@ action.
.Xr sched_setscheduler 2 ,
.Xr setpgid 2 ,
.Xr vfork 2 ,
-.Xr posix_spawn_file_actions_addchdir_np 3 ,
+.Xr posix_spawn_file_actions_addchdir 3 ,
.Xr posix_spawn_file_actions_addclose 3 ,
.Xr posix_spawn_file_actions_addclosefrom_np 3 ,
.Xr posix_spawn_file_actions_adddup2 3 ,
-.Xr posix_spawn_file_actions_addfchdir_np 3 ,
+.Xr posix_spawn_file_actions_addfchdir 3 ,
.Xr posix_spawn_file_actions_addopen 3 ,
.Xr posix_spawn_file_actions_destroy 3 ,
.Xr posix_spawn_file_actions_init 3 ,
@@ -467,7 +467,7 @@ action.
.Xr posix_spawnattr_setexecfd_np 3 ,
.Xr posix_spawnattr_setflags 3 ,
.Xr posix_spawnattr_setpgroup 3 ,
-.Xr posix_spawnattr_setprocdescp_np 3,
+.Xr posix_spawnattr_setprocdescp_np 3 ,
.Xr posix_spawnattr_setschedparam 3 ,
.Xr posix_spawnattr_setschedpolicy 3 ,
.Xr posix_spawnattr_setsigdefault 3 ,
@@ -481,8 +481,10 @@ functions conform to
.St -p1003.1-2001 ,
except that they ignore all errors from
.Fn close .
-A future update of the Standard is expected to require that these functions
-not fail because a file descriptor to be closed (via
+The
+.St -p1003.1-2024 ,
+version of the Standard no longer requires that these functions
+fail because a file descriptor to be closed (via
.Fn posix_spawn_file_actions_addclose )
is not open.
.Sh HISTORY
diff --git a/lib/libc/gen/posix_spawn.c b/lib/libc/gen/posix_spawn.c
index 656c0f20f798..11cdb5a29d03 100644
--- a/lib/libc/gen/posix_spawn.c
+++ b/lib/libc/gen/posix_spawn.c
@@ -549,6 +549,8 @@ posix_spawn_file_actions_addchdir_np(posix_spawn_file_actions_t *
STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
return (0);
}
+__weak_reference(posix_spawn_file_actions_addchdir_np,
+ posix_spawn_file_actions_addchdir);
int
posix_spawn_file_actions_addfchdir_np(posix_spawn_file_actions_t *__restrict fa,
@@ -571,6 +573,9 @@ posix_spawn_file_actions_addfchdir_np(posix_spawn_file_actions_t *__restrict fa,
return (0);
}
+__weak_reference(posix_spawn_file_actions_addfchdir_np,
+ posix_spawn_file_actions_addfchdir);
+
int
posix_spawn_file_actions_addclosefrom_np (posix_spawn_file_actions_t *
__restrict fa, int from)
diff --git a/lib/libc/gen/posix_spawn_file_actions_addopen.3 b/lib/libc/gen/posix_spawn_file_actions_addopen.3
index 80bc91454471..1d0eac45f872 100644
--- a/lib/libc/gen/posix_spawn_file_actions_addopen.3
+++ b/lib/libc/gen/posix_spawn_file_actions_addopen.3
@@ -40,8 +40,8 @@
.Nm posix_spawn_file_actions_adddup2 ,
.Nm posix_spawn_file_actions_addclose ,
.Nm posix_spawn_file_actions_addclosefrom_np ,
-.Nm posix_spawn_file_actions_addchdir_np ,
-.Nm posix_spawn_file_actions_addfchdir_np
+.Nm posix_spawn_file_actions_addchdir ,
+.Nm posix_spawn_file_actions_addfchdir
.Nd "add open, dup2, close, closefrom, or chdir/fchdir actions to spawn file actions object"
.Sh LIBRARY
.Lb libc
@@ -72,12 +72,12 @@
.Fa "int from"
.Fc
.Ft int
-.Fo posix_spawn_file_actions_addchdir_np
+.Fo posix_spawn_file_actions_addchdir
.Fa "posix_spawn_file_actions_t *restrict file_actions"
.Fa "const char *restrict path"
.Fc
.Ft int
-.Fo posix_spawn_file_actions_addfchdir_np
+.Fo posix_spawn_file_actions_addfchdir
.Fa "posix_spawn_file_actions_t * file_actions"
.Fa "int fildes"
.Fc
@@ -189,9 +189,9 @@ For each open file descriptor, logically the close action is performed,
and any possible errors encountered are ignored.
.Pp
The
-.Fn posix_spawn_file_actions_addchdir_np
+.Fn posix_spawn_file_actions_addchdir
and
-.Fn posix_spawn_file_actions_addfchdir_np
+.Fn posix_spawn_file_actions_addfchdir
functions add a change current directory action to the object
referenced by
.Fa file_actions
@@ -201,11 +201,11 @@ in the order of insertion into the
object.
It also sets the working directory for the spawned program.
The
-.Fn posix_spawn_file_actions_addchdir_np
+.Fn posix_spawn_file_actions_addchdir
function takes the
.Fa path
to set as the working directory, while
-.Fn posix_spawn_file_actions_addfchdir_np
+.Fn posix_spawn_file_actions_addfchdir
takes the directory file descriptor.
.Sh RETURN VALUES
Upon successful completion, these functions return zero;
@@ -250,11 +250,8 @@ is equal to
A future update of the Standard is expected to require this behavior.
.Pp
The
-.Fn posix_spawn_file_actions_addchdir_np ,
-.Fn posix_spawn_file_actions_addfchdir_np ,
-and
.Fn posix_spawn_file_actions_addclosefrom_np
-functions are non-standard functions implemented after the similar
+function is non-standard and implemented after the similar
functionality provided by glibc.
.Sh HISTORY
The
@@ -271,5 +268,13 @@ and
.Fn posix_spawn_file_actions_addclosefrom_np
functions first appeared in
.Fx 13.1 .
+In
+.Fx 16.0 ,
+the
+.Fn posix_spawn_file_actions_addchdir ,
+.Fn posix_spawn_file_actions_addfchdir
+aliases where added to the corresponding functions with the
+.Ql _np
+suffix.
.Sh AUTHORS
.An \&Ed Schouten Aq Mt ed@FreeBSD.org
diff --git a/lib/libc/gen/sysctl.3 b/lib/libc/gen/sysctl.3
index ef897c653728..75fd6307bd30 100644
--- a/lib/libc/gen/sysctl.3
+++ b/lib/libc/gen/sysctl.3
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd July 31, 2025
+.Dd April 15, 2026
.Dt SYSCTL 3
.Os
.Sh NAME
@@ -325,7 +325,7 @@ information.
.Bl -column "KERNXMAXFILESPERPROCXXX" "struct clockrateXXX" -offset indent
.It Sy Second Level Name Ta Sy Type Ta Sy Changeable
.It Dv KERN_ARGMAX Ta integer Ta no
-.It Dv KERN_ARND Ta integer Ta no
+.It Dv KERN_ARND Ta byte buffer Ta no
.It Dv KERN_BOOTFILE Ta string Ta yes
.It Dv KERN_BOOTTIME Ta struct timeval Ta no
.It Dv KERN_CLOCKRATE Ta struct clockinfo Ta no
@@ -333,7 +333,7 @@ information.
.It Dv KERN_HOSTID Ta integer Ta yes
.It Dv KERN_HOSTUUID Ta string Ta yes
.It Dv KERN_HOSTNAME Ta string Ta yes
-.It Dv KERN_IOV_MAX Ta integer Ta yes
+.It Dv KERN_IOV_MAX Ta integer Ta no
.It Dv KERN_JOB_CONTROL Ta integer Ta no
.It Dv KERN_LOCKF Ta struct kinfo_lockf Ta no
.It Dv KERN_LOGSIGEXIT Ta integer Ta yes
@@ -457,7 +457,7 @@ the currently installed userland.
.It Li KERN_OSRELEASE
The system release string.
.It Li KERN_OSREV
-The system revision string.
+The system revision number.
.It Li KERN_OSTYPE
The system type string.
.It Li KERN_POSIX1
@@ -501,14 +501,14 @@ specifies the current process.
.It Dv KERN_PROC_GROUPS Ta "gid_t []"
.It Dv KERN_PROC_ENV Ta "Set of strings"
.It Dv KERN_PROC_AUXV Ta "Elf_Auxinfo []"
-.It Dv KERN_PROC_RLIMIT Ta "Integer"
-.It Dv KERN_PROC_PS_STRINGS Ta "Integer"
+.It Dv KERN_PROC_RLIMIT Ta "struct rlimit"
+.It Dv KERN_PROC_PS_STRINGS Ta "Pointer to struct ps_strings"
.It Dv KERN_PROC_UMASK Ta "Integer/short"
.It Dv KERN_PROC_OSREL Ta "Integer"
-.It Dv KERN_PROC_SIGTRAMP Ta "Integer"
-.It Dv KERN_PROC_CWD Ta "String"
+.It Dv KERN_PROC_SIGTRAMP Ta "struct kinfo_sigtramp"
+.It Dv KERN_PROC_CWD Ta "struct kinfo_file"
.It Dv KERN_PROC_NFDS Ta "Integer"
-.It Dv KERN_PROC_SIGFASTBLK Ta "Integer"
+.It Dv KERN_PROC_SIGFASTBLK Ta "Address"
.It Dv KERN_PROC_VM_LAYOUT Ta "struct kinfo_vm_layout"
.It Dv KERN_PROC_RLIMIT_USAGE Ta "rlim_t []"
.It Dv KERN_PROC_KQUEUE Ta "struct kinfo_knote []"
@@ -570,7 +570,8 @@ Read from the note of the elf executable at
time.
Might be modified by the process.
.It Dv KERN_PROC_SIGTRAMP
-Address of the signal trampoline in the process address space,
+Structure describing the address range of the signal trampoline in the
+process address space,
where, simplifying, the kernel passes control for signal delivery.
.It Dv KERN_PROC_CWD
Returns the current working directory for the process.
@@ -586,6 +587,12 @@ Fills a structure describing process virtual address space layout.
Like
.Dv KERN_PROC_RLIMIT ,
but instead of the limit, returns the accounted resource usage.
+If the MIB is of the form
+.Li kern.proc.rlimit_usage\&. Ns Va pid ,
+usage values for all resources are returned.
+If the MIB is of the form
+.Li kern.proc.rlimit_usage\&. Ns Va pid Ns \&. Ns Va resource ,
+the usage value for the specified resource is returned.
For resources which do not have a meaningful current value,
.Li \-1
is returned.
diff --git a/lib/libc/stdlib/atexit.3 b/lib/libc/stdlib/atexit.3
index 4ff384813550..4082c887497c 100644
--- a/lib/libc/stdlib/atexit.3
+++ b/lib/libc/stdlib/atexit.3
@@ -29,7 +29,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd September 6, 2002
+.Dd March 31, 2026
.Dt ATEXIT 3
.Os
.Sh NAME
@@ -90,6 +90,7 @@ function was called by a program that did not supply a
implementation.
.El
.Sh SEE ALSO
+.Xr _exit 2 ,
.Xr at_quick_exit 3 ,
.Xr exit 3
.Sh STANDARDS
diff --git a/lib/libc/tests/string/Makefile b/lib/libc/tests/string/Makefile
index a019939c30af..a4d23b2dcfe1 100644
--- a/lib/libc/tests/string/Makefile
+++ b/lib/libc/tests/string/Makefile
@@ -20,6 +20,7 @@ ATF_TESTS_C+= strcmp2_test
ATF_TESTS_C+= strcspn_test
ATF_TESTS_C+= strerror2_test
ATF_TESTS_C+= strlcpy_test
+ATF_TESTS_C+= strrchr2_test
ATF_TESTS_C+= strspn_test
ATF_TESTS_C+= strverscmp_test
ATF_TESTS_C+= strxfrm_test
@@ -49,6 +50,7 @@ NETBSD_ATF_TESTS_C+= swab_test
SRCS.memset2_test= memset_test.c
SRCS.strcmp2_test= strcmp_test.c
SRCS.strerror2_test= strerror_test.c
+SRCS.strrchr2_test= strrchr_test.c
.include "../Makefile.netbsd-tests"
diff --git a/lib/libc/tests/string/strrchr_test.c b/lib/libc/tests/string/strrchr_test.c
new file mode 100644
index 000000000000..1c3d912ec3f8
--- /dev/null
+++ b/lib/libc/tests/string/strrchr_test.c
@@ -0,0 +1,156 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023, 2026 Robert Clausecker <fuz@FreeBSD.org>
+ *
+ * Adapted from memrchr_test.c.
+ */
+
+#include <sys/cdefs.h>
+
+#include <dlfcn.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+static char *(*strrchr_fn)(const char *, int);
+
+/*
+ * Check that when looking for the character NUL, we find the
+ * string terminator, and not some NUL character after it.
+ */
+ATF_TC_WITHOUT_HEAD(nul);
+ATF_TC_BODY(nul, tc)
+{
+ size_t i, j, k;
+ char buf[1+15+64]; /* offset [0+15] + 64 buffer bytes + sentinels */
+
+ buf[0] = '\0';
+ memset(buf + 1, '-', sizeof(buf) - 1);
+
+ for (i = 0; i < 16; i++)
+ for (j = 0; j < 64; j++)
+ for (k = j; k < 64; k++) {
+ buf[i + j + 1] = '\0';
+ buf[i + k + 1] = '\0';
+ ATF_CHECK_EQ(strrchr_fn(buf + i + 1, '\0'), buf + i + j + 1);
+ buf[i + j + 1] = '-';
+ buf[i + k + 1] = '-';
+ }
+}
+
+/*
+ * Check that if the character 'X' does not occur in the string
+ * (but occurs before and after it), we correctly return NULL.
+ */
+ATF_TC_WITHOUT_HEAD(not_found);
+ATF_TC_BODY(not_found, tc)
+{
+ size_t i, j;
+ char buf[1+15+64+2]; /* offset [0..15] + 64 buffer bytes + sentinels */
+
+ buf[0] = 'X';
+ memset(buf + 1, '-', sizeof(buf) - 1);
+
+ for (i = 0; i < 16; i++)
+ for (j = 0; j < 64; j++) {
+ buf[i + j + 1] = '\0';
+ buf[i + j + 2] = 'X';
+ ATF_CHECK_EQ(strrchr_fn(buf + i + 1, 'X'), NULL);
+ buf[i + j + 1] = '-';
+ buf[i + j + 2] = '-';
+ }
+}
+
+static void
+do_found_test(char buf[], size_t first, size_t second)
+{
+ /* invariant: first <= second */
+
+ buf[first] = 'X';
+ buf[second] = 'X';
+ ATF_CHECK_EQ(strrchr_fn(buf, 'X'), buf + second);
+ buf[first] = '-';
+ buf[second] = '-';
+}
+
+/*
+ * Check that if the character 'X' occurs in the string multiple
+ * times (i. e. twice), its last encounter is returned.
+ */
+ATF_TC_WITHOUT_HEAD(found);
+ATF_TC_BODY(found, tc)
+{
+ size_t i, j, k, l;
+ char buf[1+15+64+2];
+
+ buf[0] = 'X';
+ memset(buf + 1, '-', sizeof(buf) - 1);
+
+ for (i = 0; i < 16; i++)
+ for (j = 0; j < 64; j++)
+ for (k = 0; k < j; k++)
+ for (l = 0; l <= k; l++) {
+ buf[i + j + 1] = '\0';
+ buf[i + j + 2] = 'X';
+ do_found_test(buf + i + 1, l, k);
+ buf[i + j + 1] = '-';
+ buf[i + j + 2] = '-';
+ }
+}
+
+static void
+do_values_test(char buf[], size_t len, size_t i, int c)
+{
+ /* sentinels */
+ buf[-1] = c;
+ buf[len] = '\0';
+ buf[len + 1] = 'c';
+
+ /* fill the string with some other character, but not with NUL */
+ memset(buf, c == UCHAR_MAX ? c - 1 : c + 1, len);
+
+ if (i < len) {
+ buf[i] = c;
+ ATF_CHECK_EQ(strrchr_fn(buf, c), buf + i);
+ } else
+ ATF_CHECK_EQ(strrchr_fn(buf, c), c == 0 ? buf + len : NULL);
+}
+
+/*
+ * Check that the character is found regardless of its value.
+ * This catches arithmetic (overflow) errors in incorrect SWAR
+ * implementations of byte-parallel character matching.
+ */
+ATF_TC_WITHOUT_HEAD(values);
+ATF_TC_BODY(values, tc)
+{
+ size_t i, j, k;
+ int c;
+ char buf[1+15+64+2];
+
+ for (i = 0; i < 16; i++)
+ for (j = 0; j < 64; j++)
+ for (k = 0; k <= j; k++)
+ for (c = 0; c <= UCHAR_MAX; c++)
+ do_values_test(buf + i + 1, j, k, c);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ void *dl_handle;
+
+ dl_handle = dlopen(NULL, RTLD_LAZY);
+ strrchr_fn = dlsym(dl_handle, "test_strrchr");
+ if (strrchr_fn == NULL)
+ strrchr_fn = strrchr;
+
+ ATF_TP_ADD_TC(tp, nul);
+ ATF_TP_ADD_TC(tp, not_found);
+ ATF_TP_ADD_TC(tp, found);
+ ATF_TP_ADD_TC(tp, values);
+
+ return (atf_no_error());
+}
diff --git a/lib/libcasper/services/cap_dns/cap_dns.c b/lib/libcasper/services/cap_dns/cap_dns.c
index 8681f0baef40..8e660b197e3a 100644
--- a/lib/libcasper/services/cap_dns/cap_dns.c
+++ b/lib/libcasper/services/cap_dns/cap_dns.c
@@ -267,7 +267,7 @@ cap_getaddrinfo(cap_channel_t *chan, const char *hostname, const char *servname,
}
nvlist_destroy(nvl);
if (curai == NULL && nvlai != NULL) {
- if (firstai == NULL)
+ if (firstai != NULL)
freeaddrinfo(firstai);
return (EAI_MEMORY);
}
diff --git a/lib/libexpat/expat_config.h b/lib/libexpat/expat_config.h
index 565404f1577b..2ee8a71a7871 100644
--- a/lib/libexpat/expat_config.h
+++ b/lib/libexpat/expat_config.h
@@ -89,7 +89,7 @@
#define PACKAGE_NAME "expat"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "expat 2.7.3"
+#define PACKAGE_STRING "expat 2.7.5"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "expat"
@@ -98,7 +98,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.7.3"
+#define PACKAGE_VERSION "2.7.5"
/* Define to 1 if all of the C89 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
@@ -106,7 +106,7 @@
#define STDC_HEADERS 1
/* Version number of package */
-#define VERSION "2.7.3"
+#define VERSION "2.7.5"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
diff --git a/lib/libexpat/libbsdxml.3 b/lib/libexpat/libbsdxml.3
index d25249bbc155..2eea4810ef6c 100644
--- a/lib/libexpat/libbsdxml.3
+++ b/lib/libexpat/libbsdxml.3
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"/
-.Dd September 28, 2025
+.Dd April 2, 2026
.Dt LIBBSDXML 3
.Os
.Sh NAME
@@ -34,7 +34,7 @@
.Sh DESCRIPTION
The
.Nm
-library is a verbatim copy of the eXpat XML library version 2.7.3.
+library is a verbatim copy of the eXpat XML library version 2.7.5.
.Pp
The
.Nm
diff --git a/lib/libgcc_s/Symbol.map b/lib/libgcc_s/Symbol.map
index e8f7e824adaf..91fdeac3f2cf 100644
--- a/lib/libgcc_s/Symbol.map
+++ b/lib/libgcc_s/Symbol.map
@@ -198,6 +198,7 @@ GCC_4.6.0 {
__divtf3;
__eqtf2;
__extenddftf2;
+ __extendhftf2;
__extendsftf2;
__fixtfdi;
__fixtfsi;
diff --git a/lib/libifconfig/libifconfig.c b/lib/libifconfig/libifconfig.c
index f844ae235a71..bc0fcb6021b2 100644
--- a/lib/libifconfig/libifconfig.c
+++ b/lib/libifconfig/libifconfig.c
@@ -562,7 +562,9 @@ ifconfig_create_interface(ifconfig_handle_t *h, const char *name, char **ifname)
(strncmp(name, "vlan",
strlen("vlan")) == 0) ||
(strncmp(name, "vxlan",
- strlen("vxlan")) == 0)) {
+ strlen("vxlan")) == 0) ||
+ (strncmp(name, "geneve",
+ strlen("geneve")) == 0)) {
h->error.errtype = OTHER;
h->error.errcode = ENOSYS;
return (-1);
diff --git a/lib/libifconfig/libifconfig_carp.c b/lib/libifconfig/libifconfig_carp.c
index 59faa8def496..8599470cd3f9 100644
--- a/lib/libifconfig/libifconfig_carp.c
+++ b/lib/libifconfig/libifconfig_carp.c
@@ -53,7 +53,7 @@ static struct snl_attr_parser ap_carp_get[] = {
{ .type = CARP_NL_STATE, .off = _OUT(carpr_state), .cb = snl_attr_get_uint32 },
{ .type = CARP_NL_ADVBASE, .off = _OUT(carpr_advbase), .cb = snl_attr_get_int32 },
{ .type = CARP_NL_ADVSKEW, .off = _OUT(carpr_advskew), .cb = snl_attr_get_int32 },
- { .type = CARP_NL_KEY, .off = _OUT(carpr_key), .cb = snl_attr_copy_string, .arg_u32 = CARP_KEY_LEN },
+ { .type = CARP_NL_KEY, .off = _OUT(carpr_key), .cb = snl_attr_get_bytes, .arg_u32 = CARP_KEY_LEN },
{ .type = CARP_NL_ADDR, .off = _OUT(carpr_addr), .cb = snl_attr_get_in_addr },
{ .type = CARP_NL_ADDR6, .off = _OUT(carpr_addr6), .cb = snl_attr_get_in6_addr },
{ .type = CARP_NL_VERSION, .off = _OUT(carpr_version), .cb = snl_attr_get_uint8 },
@@ -177,7 +177,8 @@ ifconfig_carp_set_info(ifconfig_handle_t *h, const char *name,
&carpr->carpr_addr);
snl_add_msg_attr(&nw, CARP_NL_ADDR6, sizeof(carpr->carpr_addr6),
&carpr->carpr_addr6);
- snl_add_msg_attr_string(&nw, CARP_NL_KEY, carpr->carpr_key);
+ snl_add_msg_attr(&nw, CARP_NL_KEY, sizeof(carpr->carpr_key),
+ carpr->carpr_key);
snl_add_msg_attr_u8(&nw, CARP_NL_VERSION, carpr->carpr_version);
snl_add_msg_attr_u8(&nw, CARP_NL_VRRP_PRIORITY, carpr->carpr_vrrp_prio);
snl_add_msg_attr_u16(&nw, CARP_NL_VRRP_ADV_INTER, carpr->carpr_vrrp_adv_inter);
diff --git a/lib/libifconfig/libifconfig_sfp.c b/lib/libifconfig/libifconfig_sfp.c
index 1ba6d231a992..a2cddf89a13a 100644
--- a/lib/libifconfig/libifconfig_sfp.c
+++ b/lib/libifconfig/libifconfig_sfp.c
@@ -32,6 +32,7 @@
#include <sys/socket.h>
#include <net/if.h>
+#include <net/cmis.h>
#include <net/sff8436.h>
#include <net/sff8472.h>
@@ -114,6 +115,50 @@ read_i2c(struct i2c_info *ii, uint8_t addr, uint8_t off, uint8_t len,
return (0);
}
+/*
+ * Reads i2c data with CMIS page/bank selection.
+ * For upper memory (offset >= 128), the page and bank fields select
+ * which CMIS register page is mapped into the 128-255 address range.
+ */
+static int
+read_i2c_page(struct i2c_info *ii, uint8_t addr, uint8_t page, uint8_t bank,
+ uint8_t off, uint8_t len, uint8_t *buf)
+{
+ struct ifi2creq req;
+ int i, l;
+
+ if (ii->error != 0)
+ return (ii->error);
+
+ ii->ifr.ifr_data = (caddr_t)&req;
+
+ i = 0;
+ l = 0;
+ memset(&req, 0, sizeof(req));
+ req.dev_addr = addr;
+ req.offset = off;
+ req.len = len;
+ req.page = page;
+ req.bank = bank;
+
+ while (len > 0) {
+ l = MIN(sizeof(req.data), len);
+ req.len = l;
+ if (ifconfig_ioctlwrap(ii->h, AF_LOCAL, SIOCGI2CPB,
+ &ii->ifr) != 0) {
+ ii->error = errno;
+ return (errno);
+ }
+
+ memcpy(&buf[i], req.data, l);
+ len -= l;
+ i += l;
+ req.offset += l;
+ }
+
+ return (0);
+}
+
static int
i2c_info_init(struct i2c_info *ii, ifconfig_handle_t *h, const char *name)
{
@@ -193,18 +238,76 @@ get_qsfp_info(struct i2c_info *ii, struct ifconfig_sfp_info *sfp)
return (ii->error);
}
+static int
+get_cmis_info(struct i2c_info *ii, struct ifconfig_sfp_info *sfp)
+{
+ uint8_t app_desc[CMIS_APP_DESC_SIZE];
+ uint8_t dpconfig, appsel;
+ uint8_t app_off;
+
+ /* Module ID from lower memory byte 0 */
+ read_i2c(ii, CMIS_BASE, CMIS_ID, 1, &sfp->sfp_id);
+
+ /* Connector type from Page 00h byte 203 */
+ read_i2c_page(ii, CMIS_BASE, 0x00, 0,
+ CMIS_P0_CONNECTOR, 1, &sfp->sfp_conn);
+
+ /* Media type from lower memory byte 85 */
+ read_i2c(ii, CMIS_BASE, CMIS_MEDIA_TYPE, 1,
+ &sfp->sfp_cmis_media_type);
+
+ /*
+ * Read the active AppSel code from the Active Control Set
+ * (Page 11h, byte 206, bits 7:4). This tells us which
+ * Application Descriptor is actually in use.
+ * AppSel is 1-based; 0 means no application selected.
+ */
+ dpconfig = 0;
+ read_i2c_page(ii, CMIS_BASE, 0x11, 0,
+ CMIS_P11_ACS_DPCONFIG1, 1, &dpconfig);
+ appsel = (dpconfig & CMIS_ACS_APPSEL_MASK) >> CMIS_ACS_APPSEL_SHIFT;
+
+ /* Fall back to first descriptor if AppSel is 0 or out of range */
+ if (appsel == 0 || appsel > CMIS_MAX_APP_DESC)
+ appsel = 1;
+
+ /* Read the active Application Descriptor */
+ app_off = CMIS_APP_DESC_START + (appsel - 1) * CMIS_APP_DESC_SIZE;
+ read_i2c(ii, CMIS_BASE, app_off, CMIS_APP_DESC_SIZE, app_desc);
+ if (ii->error != 0)
+ return (ii->error);
+
+ /* Store MediaInterfaceID based on media type */
+ switch (sfp->sfp_cmis_media_type) {
+ case SFP_CMIS_MEDIA_TYPE_SMF:
+ sfp->sfp_cmis_smf = app_desc[CMIS_APP_MEDIA_IF_ID];
+ break;
+ case SFP_CMIS_MEDIA_TYPE_MMF:
+ sfp->sfp_cmis_mmf = app_desc[CMIS_APP_MEDIA_IF_ID];
+ break;
+ }
+
+ /* Extract media lane count from app descriptor byte 2, bits 3:0 */
+ sfp->sfp_cmis_lanes = app_desc[CMIS_APP_LANE_COUNT] & 0x0F;
+
+ return (ii->error);
+}
+
int
ifconfig_sfp_get_sfp_info(ifconfig_handle_t *h,
const char *name, struct ifconfig_sfp_info *sfp)
{
struct i2c_info ii;
- char buf[8];
+ uint8_t buf[8];
memset(sfp, 0, sizeof(*sfp));
if (i2c_info_init(&ii, h, name) != 0)
return (-1);
+ if (ifconfig_sfp_id_is_cmis(ii.id))
+ return (get_cmis_info(&ii, sfp));
+
/* Read bytes 3-10 at once */
read_i2c(&ii, SFF_8472_BASE, SFF_8472_TRANS_START, 8, buf);
if (ii.error != 0)
@@ -246,6 +349,12 @@ channel_count(enum sfp_id id)
size_t
ifconfig_sfp_channel_count(const struct ifconfig_sfp_info *sfp)
{
+ /* CMIS modules: use lane count from Application Descriptor */
+ if (ifconfig_sfp_id_is_cmis(sfp->sfp_id)) {
+ if (sfp->sfp_cmis_lanes > 0)
+ return (sfp->sfp_cmis_lanes);
+ return (0);
+ }
return (channel_count(sfp->sfp_id));
}
@@ -256,7 +365,7 @@ ifconfig_sfp_channel_count(const struct ifconfig_sfp_info *sfp)
static void
get_sff_string(struct i2c_info *ii, uint8_t addr, uint8_t off, char *dst)
{
- read_i2c(ii, addr, off, SFF_VENDOR_STRING_SIZE, dst);
+ read_i2c(ii, addr, off, SFF_VENDOR_STRING_SIZE, (uint8_t *)dst);
dst += SFF_VENDOR_STRING_SIZE;
do { *dst-- = '\0'; } while (*dst == 0x20);
}
@@ -264,7 +373,7 @@ get_sff_string(struct i2c_info *ii, uint8_t addr, uint8_t off, char *dst)
static void
get_sff_date(struct i2c_info *ii, uint8_t addr, uint8_t off, char *dst)
{
- char buf[SFF_VENDOR_DATE_SIZE];
+ uint8_t buf[SFF_VENDOR_DATE_SIZE];
read_i2c(ii, addr, off, SFF_VENDOR_DATE_SIZE, buf);
sprintf(dst, "20%c%c-%c%c-%c%c", buf[0], buf[1], buf[2], buf[3],
@@ -291,6 +400,41 @@ get_qsfp_vendor_info(struct i2c_info *ii, struct ifconfig_sfp_vendor_info *vi)
return (ii->error);
}
+/*
+ * Read CMIS vendor strings from Page 00h (upper memory).
+ * Vendor info uses the same ASCII format as SFF-8436 but at
+ * different offsets and requires page selection.
+ */
+static void
+get_cmis_string(struct i2c_info *ii, uint8_t off, char *dst)
+{
+ read_i2c_page(ii, CMIS_BASE, 0x00, 0, off,
+ SFF_VENDOR_STRING_SIZE, dst);
+ dst += SFF_VENDOR_STRING_SIZE;
+ do { *dst-- = '\0'; } while (*dst == 0x20);
+}
+
+static void
+get_cmis_date(struct i2c_info *ii, uint8_t off, char *dst)
+{
+ char buf[SFF_VENDOR_DATE_SIZE];
+
+ read_i2c_page(ii, CMIS_BASE, 0x00, 0, off,
+ SFF_VENDOR_DATE_SIZE, buf);
+ sprintf(dst, "20%c%c-%c%c-%c%c", buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5]);
+}
+
+static int
+get_cmis_vendor_info(struct i2c_info *ii, struct ifconfig_sfp_vendor_info *vi)
+{
+ get_cmis_string(ii, CMIS_P0_VENDOR_NAME, vi->name);
+ get_cmis_string(ii, CMIS_P0_VENDOR_PN, vi->pn);
+ get_cmis_string(ii, CMIS_P0_VENDOR_SN, vi->sn);
+ get_cmis_date(ii, CMIS_P0_DATE_CODE, vi->date);
+ return (ii->error);
+}
+
int
ifconfig_sfp_get_sfp_vendor_info(ifconfig_handle_t *h,
const char *name, struct ifconfig_sfp_vendor_info *vi)
@@ -302,6 +446,8 @@ ifconfig_sfp_get_sfp_vendor_info(ifconfig_handle_t *h,
if (i2c_info_init(&ii, h, name) != 0)
return (-1);
+ if (ifconfig_sfp_id_is_cmis(ii.id))
+ return (get_cmis_vendor_info(&ii, vi));
if (ifconfig_sfp_id_is_qsfp(ii.id))
return (get_qsfp_vendor_info(&ii, vi));
return (get_sfp_vendor_info(&ii, vi));
@@ -386,7 +532,7 @@ get_sfp_status(struct i2c_info *ii, struct ifconfig_sfp_status *ss)
uint8_t diag_type, flags;
/* Read diagnostic monitoring type */
- read_i2c(ii, SFF_8472_BASE, SFF_8472_DIAG_TYPE, 1, (caddr_t)&diag_type);
+ read_i2c(ii, SFF_8472_BASE, SFF_8472_DIAG_TYPE, 1, &diag_type);
if (ii->error != 0)
return (-1);
@@ -457,6 +603,47 @@ get_qsfp_status(struct i2c_info *ii, struct ifconfig_sfp_status *ss)
return (ii->error);
}
+/*
+ * Read CMIS module status: temperature and voltage from lower memory,
+ * per-lane TX power, TX bias, and RX power from Page 11h Bank 0.
+ */
+static int
+get_cmis_status(struct i2c_info *ii, struct ifconfig_sfp_status *ss,
+ size_t channels)
+{
+ /* Temperature and voltage are in lower memory (same format as SFF) */
+ ss->temp = get_sff_temp(ii, CMIS_BASE, CMIS_TEMP);
+ ss->voltage = get_sff_voltage(ii, CMIS_BASE, CMIS_VCC);
+
+ if (channels == 0)
+ return (ii->error);
+
+ ss->channel = calloc(channels, sizeof(*ss->channel));
+ if (ss->channel == NULL) {
+ ii->h->error.errtype = OTHER;
+ ii->h->error.errcode = ENOMEM;
+ return (-1);
+ }
+
+ /* Read per-lane monitors from Page 11h Bank 0 */
+ for (size_t chan = 0; chan < channels; ++chan) {
+ uint8_t off;
+ uint8_t buf[2];
+
+ /* RX optical power */
+ off = CMIS_P11_RX_PWR_1 + chan * CMIS_LANE_MON_SIZE;
+ read_i2c_page(ii, CMIS_BASE, 0x11, 0, off, 2, buf);
+ ss->channel[chan].rx = (buf[0] << 8) | buf[1];
+
+ /* TX bias current */
+ off = CMIS_P11_TX_BIAS_1 + chan * CMIS_LANE_MON_SIZE;
+ read_i2c_page(ii, CMIS_BASE, 0x11, 0, off, 2, buf);
+ ss->channel[chan].tx = (buf[0] << 8) | buf[1];
+ }
+
+ return (ii->error);
+}
+
int
ifconfig_sfp_get_sfp_status(ifconfig_handle_t *h, const char *name,
struct ifconfig_sfp_status *ss)
@@ -468,6 +655,20 @@ ifconfig_sfp_get_sfp_status(ifconfig_handle_t *h, const char *name,
if (i2c_info_init(&ii, h, name) != 0)
return (-1);
+ if (ifconfig_sfp_id_is_cmis(ii.id)) {
+ /*
+ * For CMIS, we need the lane count from the module info.
+ * Read the first Application Descriptor to get it.
+ */
+ uint8_t app_desc[CMIS_APP_DESC_SIZE];
+ size_t channels;
+
+ read_i2c(&ii, CMIS_BASE, CMIS_APP_DESC_START,
+ CMIS_APP_DESC_SIZE, app_desc);
+ channels = app_desc[CMIS_APP_LANE_COUNT] & 0x0F;
+ return (get_cmis_status(&ii, ss, channels));
+ }
+
if (ifconfig_sfp_id_is_qsfp(ii.id))
return (get_qsfp_status(&ii, ss));
return (get_sfp_status(&ii, ss));
@@ -527,6 +728,21 @@ const char *
ifconfig_sfp_physical_spec(const struct ifconfig_sfp_info *sfp,
const struct ifconfig_sfp_info_strings *strings)
{
+ /* CMIS modules: look up media interface ID based on media type */
+ if (ifconfig_sfp_id_is_cmis(sfp->sfp_id)) {
+ switch (sfp->sfp_cmis_media_type) {
+ case SFP_CMIS_MEDIA_TYPE_SMF:
+ if (strings->sfp_cmis_smf != NULL)
+ return (strings->sfp_cmis_smf);
+ break;
+ case SFP_CMIS_MEDIA_TYPE_MMF:
+ if (strings->sfp_cmis_mmf != NULL)
+ return (strings->sfp_cmis_mmf);
+ break;
+ }
+ return ("Unknown");
+ }
+
switch (sfp->sfp_id) {
case SFP_ID_UNKNOWN:
break;
@@ -557,12 +773,19 @@ ifconfig_sfp_get_sfp_dump(ifconfig_handle_t *h, const char *name,
struct i2c_info ii;
uint8_t *buf = dump->data;
- memset(dump->data, 0, sizeof(dump->data));
+ memset(buf, 0, sizeof(dump->data));
if (i2c_info_init(&ii, h, name) != 0)
return (-1);
- if (ifconfig_sfp_id_is_qsfp(ii.id)) {
+ if (ifconfig_sfp_id_is_cmis(ii.id)) {
+ /* Lower memory (0-127), Page 00h (128-255), Page 11h */
+ read_i2c(&ii, CMIS_BASE, 0, 128, buf);
+ read_i2c_page(&ii, CMIS_BASE, 0x00, 0, 128, 128,
+ buf + 128);
+ read_i2c_page(&ii, CMIS_BASE, 0x11, 0, 128, 128,
+ buf + CMIS_DUMP_P11);
+ } else if (ifconfig_sfp_id_is_qsfp(ii.id)) {
read_i2c(&ii, SFF_8436_BASE, QSFP_DUMP0_START, QSFP_DUMP0_SIZE,
buf + QSFP_DUMP0_START);
read_i2c(&ii, SFF_8436_BASE, QSFP_DUMP1_START, QSFP_DUMP1_SIZE,
@@ -580,6 +803,9 @@ ifconfig_sfp_dump_region_count(const struct ifconfig_sfp_dump *dp)
{
uint8_t id_byte = dp->data[0];
+ if (ifconfig_sfp_id_is_cmis((enum sfp_id)id_byte))
+ return (3);
+
switch ((enum sfp_id)id_byte) {
case SFP_ID_UNKNOWN:
return (0);
diff --git a/lib/libifconfig/libifconfig_sfp.h b/lib/libifconfig/libifconfig_sfp.h
index 2e5374d6729e..9ed4f684e5c4 100644
--- a/lib/libifconfig/libifconfig_sfp.h
+++ b/lib/libifconfig/libifconfig_sfp.h
@@ -83,11 +83,15 @@ struct ifconfig_sfp_status {
#define QSFP_DUMP1_SIZE 128 /**< bytes in the second region
in a QSFP module dump */
+#define CMIS_DUMP_SIZE 512 /**< CMIS dump buffer size */
+#define CMIS_DUMP_P11 256 /**< offset of Page 11h in dump buffer */
+
/** SFP module I2C memory dump
- * SFP modules have one region, QSFP modules have two regions.
+ * SFP modules have one region, QSFP modules have two.
+ * CMIS modules have three: lower memory, Page 00h, and Page 11h.
*/
struct ifconfig_sfp_dump {
- uint8_t data[SFF_DUMP_SIZE]; /**< memory dump data */
+ uint8_t data[CMIS_DUMP_SIZE]; /**< memory dump data */
};
/** Get information about the static properties of an SFP/QSFP module
@@ -126,6 +130,25 @@ ifconfig_sfp_id_is_qsfp(enum sfp_id id)
}
}
+/** Is the given module ID a CMIS-managed module (QSFP-DD, OSFP, etc.)
+ * @param id The sfp_id field of a SFP module info object
+ * @return A bool true if CMIS-type sfp_id otherwise false
+ */
+static inline bool
+ifconfig_sfp_id_is_cmis(enum sfp_id id)
+{
+ switch (id) {
+ case SFP_ID_QSFP_DD:
+ case SFP_ID_QSFP8X:
+ case SFP_ID_SFP_DD:
+ case SFP_ID_DSFP:
+ case SFP_ID_QSFP_CMIS:
+ return (true);
+ default:
+ return (false);
+ }
+}
+
/** Get string descriptions of the given SFP/QSFP module info
* The strings are static and do not need to be freed.
* @see ifconfig_sfp_get_sfp_info to obtain the input info.
diff --git a/lib/libifconfig/sfp.lua b/lib/libifconfig/sfp.lua
index 4a43b2ed780b..1da49e35cade 100644
--- a/lib/libifconfig/sfp.lua
+++ b/lib/libifconfig/sfp.lua
@@ -359,6 +359,126 @@ enums = {
{0x0, "UNSPECIFIED", "Unspecified"},
},
},
+
+ "CMIS (OIF-CMIS-05.3) Media Type Encodings (Table 8-20)",
+ {
+ name = "cmis_media_type",
+ description = "CMIS media type",
+ bits = 8,
+ values = {
+ {0x00, "UNDEFINED", "Undefined"},
+ {0x01, "MMF", "Optical: MMF"},
+ {0x02, "SMF", "Optical: SMF"},
+ {0x03, "COPPER", "Passive/Linear Active Copper"},
+ {0x04, "ACTIVE", "Active Cable"},
+ {0x05, "BASET", "BASE-T"},
+ },
+ },
+
+ "CMIS Media Lane Count (from Application Descriptor)",
+ {
+ name = "cmis_lanes",
+ description = "CMIS media lane count",
+ bits = 8,
+ values = {
+ {0, "UNKNOWN", "Unknown"},
+ {1, "1", "1 lane"},
+ {2, "2", "2 lanes"},
+ {4, "4", "4 lanes"},
+ {8, "8", "8 lanes"},
+ },
+ },
+
+ "SFF-8024 Table 4-7: SMF Media Interface IDs (for CMIS MediaType=02h)",
+ "Verified against SFF-8024 Rev 4.6+ and SONiC sff8024.py",
+ {
+ name = "cmis_smf",
+ description = "CMIS SMF media interface",
+ bits = 8,
+ values = {
+ {0x00, "UNDEFINED", "Undefined"},
+ {0x01, "10GBASE_LW", "10GBASE-LW"},
+ {0x02, "10GBASE_EW", "10GBASE-EW"},
+ {0x03, "10G_ZW", "10G-ZW"},
+ {0x04, "10GBASE_LR", "10GBASE-LR"},
+ {0x05, "10GBASE_ER", "10GBASE-ER"},
+ {0x06, "10G_ZR", "10G-ZR"},
+ {0x07, "25GBASE_LR", "25GBASE-LR"},
+ {0x08, "25GBASE_ER", "25GBASE-ER"},
+ {0x09, "40GBASE_LR4", "40GBASE-LR4"},
+ {0x0A, "40GBASE_FR", "40GBASE-FR"},
+ {0x0B, "50GBASE_FR", "50GBASE-FR"},
+ {0x0C, "50GBASE_LR", "50GBASE-LR"},
+ {0x0D, "100GBASE_LR4", "100GBASE-LR4"},
+ {0x0E, "100GBASE_ER4", "100GBASE-ER4"},
+ {0x0F, "100G_PSM4", "100G PSM4"},
+ {0x10, "100G_CWDM4", "100G CWDM4"},
+ {0x11, "100G_4WDM_10", "100G 4WDM-10"},
+ {0x12, "100G_4WDM_20", "100G 4WDM-20"},
+ {0x13, "100G_4WDM_40", "100G 4WDM-40"},
+ {0x14, "100GBASE_DR", "100GBASE-DR"},
+ {0x15, "100G_FR", "100G-FR/100GBASE-FR1"},
+ {0x16, "100G_LR", "100G-LR/100GBASE-LR1"},
+ {0x17, "200GBASE_DR4", "200GBASE-DR4"},
+ {0x18, "200GBASE_FR4", "200GBASE-FR4"},
+ {0x19, "200GBASE_LR4", "200GBASE-LR4"},
+ {0x1A, "400GBASE_FR8", "400GBASE-FR8"},
+ {0x1B, "400GBASE_LR8", "400GBASE-LR8"},
+ {0x1C, "400GBASE_DR4", "400GBASE-DR4"},
+ {0x1D, "400G_FR4", "400G-FR4/400GBASE-FR4"},
+ {0x1E, "400G_LR4_10", "400G-LR4-10"},
+ {0x1F, "8GFC_SM", "8GFC-SM"},
+ {0x20, "10GFC_SM", "10GFC-SM"},
+ {0x21, "16GFC_SM", "16GFC-SM"},
+ {0x22, "32GFC_SM", "32GFC-SM"},
+ {0x23, "64GFC_SM", "64GFC-SM"},
+ {0x24, "128GFC_PSM4", "128GFC-PSM4"},
+ {0x25, "256GFC_PSM4", "256GFC-PSM4"},
+ {0x34, "100G_CWDM4_OCP", "100G CWDM4-OCP"},
+ {0x3E, "400ZR_DWDM", "400ZR DWDM"},
+ {0x40, "50GBASE_ER", "50GBASE-ER"},
+ {0x41, "200GBASE_ER4", "200GBASE-ER4"},
+ {0x42, "400GBASE_ER8", "400GBASE-ER8"},
+ {0x43, "400GBASE_LR4_6", "400GBASE-LR4-6"},
+ },
+ },
+
+ "SFF-8024 Table 4-6: MMF Media Interface IDs (for CMIS MediaType=01h)",
+ "Verified against SFF-8024 Rev 4.6+ and SONiC sff8024.py",
+ {
+ name = "cmis_mmf",
+ description = "CMIS MMF media interface",
+ bits = 8,
+ values = {
+ {0x00, "UNDEFINED", "Undefined"},
+ {0x01, "10GBASE_SW", "10GBASE-SW"},
+ {0x02, "10GBASE_SR", "10GBASE-SR"},
+ {0x03, "25GBASE_SR", "25GBASE-SR"},
+ {0x04, "40GBASE_SR4", "40GBASE-SR4"},
+ {0x05, "40GE_SWDM4", "40GE SWDM4"},
+ {0x06, "40GE_BIDI", "40GE BiDi"},
+ {0x07, "50GBASE_SR", "50GBASE-SR"},
+ {0x08, "100GBASE_SR10", "100GBASE-SR10"},
+ {0x09, "100GBASE_SR4", "100GBASE-SR4"},
+ {0x0A, "100GE_SWDM4", "100GE SWDM4"},
+ {0x0B, "100GE_BIDI", "100GE BiDi"},
+ {0x0C, "100GBASE_SR2", "100GBASE-SR2"},
+ {0x0D, "100G_SR", "100G-SR"},
+ {0x0E, "200GBASE_SR4", "200GBASE-SR4"},
+ {0x0F, "400GBASE_SR16", "400GBASE-SR16"},
+ {0x10, "400GBASE_SR8", "400GBASE-SR8"},
+ {0x11, "400G_SR4", "400G-SR4"},
+ {0x12, "800G_SR8", "800G-SR8"},
+ {0x13, "8GFC_MM", "8GFC-MM"},
+ {0x14, "10GFC_MM", "10GFC-MM"},
+ {0x15, "16GFC_MM", "16GFC-MM"},
+ {0x16, "32GFC_MM", "32GFC-MM"},
+ {0x17, "64GFC_MM", "64GFC-MM"},
+ {0x18, "128GFC_MM4", "128GFC-MM4"},
+ {0x19, "256GFC_MM4", "256GFC-MM4"},
+ {0x1A, "400GBASE_SR4_2", "400GBASE-SR4.2"},
+ },
+ },
}
-- Nothing else in this context.
diff --git a/lib/liblzma/config.h b/lib/liblzma/config.h
index af0ee2fefb39..db2d4e9c6a0d 100644
--- a/lib/liblzma/config.h
+++ b/lib/liblzma/config.h
@@ -409,7 +409,7 @@
#define PACKAGE_NAME "XZ Utils"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "XZ Utils 5.8.2"
+#define PACKAGE_STRING "XZ Utils 5.8.3"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "xz"
@@ -418,7 +418,7 @@
#define PACKAGE_URL "https://tukaani.org/xz/"
/* Define to the version of this package. */
-#define PACKAGE_VERSION "5.8.2"
+#define PACKAGE_VERSION "5.8.3"
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
@@ -494,6 +494,10 @@
#ifndef _ALL_SOURCE
# define _ALL_SOURCE 1
#endif
+/* Enable extensions on Cosmopolitan Libc. */
+#ifndef _COSMO_SOURCE
+# define _COSMO_SOURCE 1
+#endif
/* Enable general extensions on macOS. */
#ifndef _DARWIN_C_SOURCE
# define _DARWIN_C_SOURCE 1
@@ -583,7 +587,7 @@
/* Version number of package */
-#define VERSION "5.8.2"
+#define VERSION "5.8.3"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
diff --git a/lib/libmixer/mixer.c b/lib/libmixer/mixer.c
index 2be3a48eb755..d4c3bf5adf52 100644
--- a/lib/libmixer/mixer.c
+++ b/lib/libmixer/mixer.c
@@ -35,13 +35,11 @@
#define BASEPATH "/dev/mixer"
-static int _mixer_readvol(struct mix_dev *);
-
/*
* Fetch volume from the device.
*/
static int
-_mixer_readvol(struct mix_dev *dev)
+mixer_readvol(struct mix_dev *dev)
{
int v;
@@ -120,7 +118,7 @@ dunit:
dp->parent_mixer = m;
dp->devno = i;
dp->nctl = 0;
- if (MIX_ISDEV(m, i) && _mixer_readvol(dp) < 0)
+ if (MIX_ISDEV(m, i) && mixer_readvol(dp) < 0)
goto fail;
(void)strlcpy(dp->name, names[i], sizeof(dp->name));
TAILQ_INIT(&dp->ctls);
@@ -334,7 +332,7 @@ mixer_set_vol(struct mixer *m, mix_volume_t vol)
v = MIX_VOLDENORM(vol.left) | MIX_VOLDENORM(vol.right) << 8;
if (ioctl(m->fd, MIXER_WRITE(m->dev->devno), &v) < 0)
return (-1);
- if (_mixer_readvol(m->dev) < 0)
+ if (mixer_readvol(m->dev) < 0)
return (-1);
return (0);
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index cd484949e4da..59783592a370 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -4084,7 +4084,7 @@ pfctl_state_limiter_add(struct pfctl_handle *h, struct pfctl_state_lim *lim)
return (ENXIO);
while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
- if (! snl_parse_nlmsg(&h->ss, hdr, &statelim_parser, &lim))
+ if (! snl_parse_nlmsg(&h->ss, hdr, &statelim_parser, lim))
continue;
}
@@ -4153,7 +4153,7 @@ pfctl_source_limiter_add(struct pfctl_handle *h, struct pfctl_source_lim *lim)
return (ENXIO);
while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
- if (! snl_parse_nlmsg(&h->ss, hdr, &sourcelim_parser, &lim))
+ if (! snl_parse_nlmsg(&h->ss, hdr, &sourcelim_parser, lim))
continue;
}
diff --git a/lib/libpmc/libpmc_json.cc b/lib/libpmc/libpmc_json.cc
index 90881f22971e..1ac0b3a50a6c 100644
--- a/lib/libpmc/libpmc_json.cc
+++ b/lib/libpmc/libpmc_json.cc
@@ -74,8 +74,8 @@ startentry(struct pmclog_ev *ev)
{
char eventbuf[128];
- snprintf(eventbuf, sizeof(eventbuf), "%s, \"tsc\": \"%jd\"",
- typenames[ev->pl_type], (uintmax_t)ev->pl_ts.tv_sec);
+ snprintf(eventbuf, sizeof(eventbuf), "%s, \"tsc\": \"%ju\"",
+ typenames[ev->pl_type], (uintmax_t)ev->pl_tsc);
return (string(eventbuf));
}
@@ -393,4 +393,3 @@ event_to_json(struct pmclog_ev *ev){
errx(EX_USAGE, "ERROR: unrecognized event type: %d\n", ev->pl_type);
}
}
-
diff --git a/lib/libpmc/pmclog.3 b/lib/libpmc/pmclog.3
index 4af4150d60a9..452a14f42f55 100644
--- a/lib/libpmc/pmclog.3
+++ b/lib/libpmc/pmclog.3
@@ -77,7 +77,10 @@ struct pmclog_ev {
enum pmclog_state pl_state; /* parser state after 'get_event()' */
off_t pl_offset; /* byte offset in stream */
size_t pl_count; /* count of records so far */
- struct timespec pl_ts; /* log entry timestamp */
+ union {
+ uint64_t pl_tsc; /* TSC timestamp */
+ struct timespec pl_ts; /* log entry timestamp (legacy) */
+ };
enum pmclog_type pl_type; /* log entry kind */
union { /* log entry data */
struct pmclog_ev_callchain pl_cc;
@@ -136,8 +139,30 @@ Field
.Va pl_count
contains the serial number of this event.
Field
+.Va pl_tsc
+carries the raw CPU Time Stamp Counter (TSC) value recorded at the time
+of the event.
+This is not a wall-clock time; to convert to nanoseconds divide the TSC
+delta between two events by the TSC frequency
+.Pq Va pl_u.pl_i.pl_tsc_freq
+reported in the
+.Dv PMCLOG_TYPE_INITIALIZE
+record.
+The legacy
.Va pl_ts
-contains a timestamp with the system time when the event occurred.
+member aliases the same storage for ABI compatibility, but its contents
+no longer represent a wall-clock timestamp.
+.Pp
+Note that TSC-based timestamps and
+.Va pl_u.pl_i.pl_tsc_freq
+are only meaningful on x86 architectures
+.Pq amd64 and i386 .
+On all other architectures
+.Pq including arm64 and powerpc ,
+.Va pl_tsc
+and
+.Va pl_u.pl_i.pl_tsc_freq
+are set to zero.
Field
.Va pl_type
denotes the kind of the event returned in argument
diff --git a/lib/libpmc/pmclog.c b/lib/libpmc/pmclog.c
index 22ff50b10ee0..c3587af46c7b 100644
--- a/lib/libpmc/pmclog.c
+++ b/lib/libpmc/pmclog.c
@@ -287,8 +287,8 @@ pmclog_get_event(void *cookie, char **data, ssize_t *len,
return -1;
}
- /* copy out the time stamp */
- ev->pl_ts.tv_sec = ph->pl_tsc;
+ /* copy out the TSC from the event header */
+ ev->pl_tsc = ph->pl_tsc;
le += sizeof(*ph)/4;
evlen = PMCLOG_HEADER_TO_LENGTH(h);
diff --git a/lib/libpmc/pmclog.h b/lib/libpmc/pmclog.h
index 72e73e3928d2..a79d33529890 100644
--- a/lib/libpmc/pmclog.h
+++ b/lib/libpmc/pmclog.h
@@ -169,7 +169,10 @@ struct pmclog_ev {
enum pmclog_state pl_state; /* state after 'get_event()' */
off_t pl_offset; /* byte offset in stream */
size_t pl_count; /* count of records so far */
- struct timespec pl_ts; /* log entry timestamp */
+ union {
+ uint64_t pl_tsc; /* TSC timestamp */
+ struct timespec pl_ts; /* log entry timestamp (legacy) */
+ };
enum pmclog_type pl_type; /* type of log entry */
void *pl_data;
int pl_len;
@@ -229,4 +232,3 @@ void pmclog_close(void *_cookie);
__END_DECLS
#endif
-
diff --git a/lib/libsecureboot/h/verify_file.h b/lib/libsecureboot/h/verify_file.h
index f918ed6d0e38..19bef24b1dee 100644
--- a/lib/libsecureboot/h/verify_file.h
+++ b/lib/libsecureboot/h/verify_file.h
@@ -51,6 +51,7 @@ int ve_status_get(int);
int load_manifest(const char *, const char *, const char *, struct stat *);
int pass_manifest(const char *, const char *);
int pass_manifest_export_envs(void);
+int severity_guess(const char *);
void verify_report(const char *, int, int, struct stat *);
int verify_file(int, const char *, off_t, int, const char *);
void verify_pcr_export(void);
@@ -59,9 +60,9 @@ int is_verified(struct stat *);
void add_verify_status(struct stat *, int);
struct vectx;
-struct vectx* vectx_open(int, const char *, off_t, struct stat *, int *, const char *);
+struct vectx* vectx_open(int, const char *, int, off_t, struct stat *, int *, const char *);
ssize_t vectx_read(struct vectx *, void *, size_t);
off_t vectx_lseek(struct vectx *, off_t, int);
-int vectx_close(struct vectx *, int, const char *);
+int vectx_close(struct vectx *, const char *);
#endif /* _VERIFY_FILE_H_ */
diff --git a/lib/libsecureboot/tests/tvo.c b/lib/libsecureboot/tests/tvo.c
index 7851e79c5a2a..407fcbefd6db 100644
--- a/lib/libsecureboot/tests/tvo.c
+++ b/lib/libsecureboot/tests/tvo.c
@@ -170,8 +170,8 @@ main(int argc, char *argv[])
fstat(fd, &st);
lseek(fd, 0, SEEK_SET);
off = st.st_size % 512;
- vp = vectx_open(fd, argv[optind], off,
- &st, &error, __func__);
+ vp = vectx_open(fd, argv[optind], VE_GUESS,
+ off, &st, &error, __func__);
if (!vp) {
printf("vectx_open(%s) failed: %d %s\n",
argv[optind], error,
@@ -190,7 +190,7 @@ main(int argc, char *argv[])
off = vectx_lseek(vp, 0, SEEK_END);
/* repeating that should be harmless */
off = vectx_lseek(vp, 0, SEEK_END);
- error = vectx_close(vp, VE_MUST, __func__);
+ error = vectx_close(vp, __func__);
if (error) {
printf("vectx_close(%s) == %d %s\n",
argv[optind], error,
diff --git a/lib/libsecureboot/vectx.c b/lib/libsecureboot/vectx.c
index 2d56830cd81d..4b42293a0d93 100644
--- a/lib/libsecureboot/vectx.c
+++ b/lib/libsecureboot/vectx.c
@@ -60,6 +60,7 @@ struct vectx {
int vec_fd; /* file descriptor */
int vec_status; /* verification status */
int vec_closing; /* we are closing */
+ int vec_severity; /* usually VE_MUST */
};
@@ -93,7 +94,8 @@ struct vectx {
* NULL is only returned for non-files or out-of-memory.
*/
struct vectx *
-vectx_open(int fd, const char *path, off_t off, struct stat *stp,
+vectx_open(int fd, const char *path, int severity,
+ off_t off, struct stat *stp,
int *error, const char *caller)
{
struct vectx *ctx;
@@ -106,14 +108,19 @@ vectx_open(int fd, const char *path, off_t off, struct stat *stp,
stp = &st;
rc = verify_prep(fd, path, off, stp, __func__);
+ if (severity == VE_GUESS)
+ severity = severity_guess(path);
DEBUG_PRINTF(2,
- ("vectx_open: caller=%s,fd=%d,name='%s',prep_rc=%d\n",
- caller, fd, path, rc));
+ ("vectx_open: caller=%s,fd=%d,name='%s',prep_rc=%d,severity=%d\n",
+ caller, fd, path, rc, severity));
switch (rc) {
case VE_FINGERPRINT_NONE:
case VE_FINGERPRINT_UNKNOWN:
+ if (severity < VE_MUST)
+ break;
+ /* FALLTHROUGH */
case VE_FINGERPRINT_WRONG:
*error = rc;
return (NULL);
@@ -127,19 +134,24 @@ vectx_open(int fd, const char *path, off_t off, struct stat *stp,
ctx->vec_off = 0;
ctx->vec_hashed = 0;
ctx->vec_want = NULL;
+ ctx->vec_severity = severity;
ctx->vec_status = 0;
ctx->vec_hashsz = hashsz = 0;
ctx->vec_closing = 0;
- if (rc == 0) {
+ if (rc == VE_UNVERIFIED_OK) {
/* we are not verifying this */
*error = 0;
return (ctx);
}
cp = fingerprint_info_lookup(fd, path);
if (!cp) {
- ctx->vec_status = VE_FINGERPRINT_NONE;
- ve_error_set("%s: no entry", path);
+ if (severity < VE_MUST)
+ ctx->vec_status = VE_UNVERIFIED_OK;
+ else {
+ ctx->vec_status = VE_FINGERPRINT_NONE;
+ ve_error_set("%s: no entry", path);
+ }
} else {
if (strncmp(cp, "no_hash", 7) == 0) {
ctx->vec_status = VE_FINGERPRINT_IGNORE;
@@ -167,8 +179,12 @@ vectx_open(int fd, const char *path, off_t off, struct stat *stp,
cp += 7;
#endif
} else {
- ctx->vec_status = VE_FINGERPRINT_UNKNOWN;
- ve_error_set("%s: no supported fingerprint", path);
+ if (severity < VE_MUST)
+ ctx->vec_status = VE_UNVERIFIED_OK;
+ else {
+ ctx->vec_status = VE_FINGERPRINT_UNKNOWN;
+ ve_error_set("%s: no supported fingerprint", path);
+ }
}
}
*error = ctx->vec_status;
@@ -183,9 +199,9 @@ vectx_open(int fd, const char *path, off_t off, struct stat *stp,
}
}
DEBUG_PRINTF(2,
- ("vectx_open: caller=%s,name='%s',hashsz=%lu,status=%d\n",
+ ("vectx_open: caller=%s,name='%s',hashsz=%lu,severity=%d,status=%d\n",
caller, path, (unsigned long)ctx->vec_hashsz,
- ctx->vec_status));
+ severity, ctx->vec_status));
return (ctx);
enomem: /* unlikely */
@@ -379,7 +395,7 @@ vectx_lseek(struct vectx *ctx, off_t off, int whence)
* @return 0 or an error.
*/
int
-vectx_close(struct vectx *ctx, int severity, const char *caller)
+vectx_close(struct vectx *ctx, const char *caller)
{
int rc;
@@ -393,7 +409,7 @@ vectx_close(struct vectx *ctx, int severity, const char *caller)
* these tend to be processed in a more deterministic
* order, which makes our pseudo pcr more useful.
*/
- ve_pcr_updating_set((severity == VE_MUST));
+ ve_pcr_updating_set((ctx->vec_severity == VE_MUST));
#endif
/* make sure we have hashed it all */
vectx_lseek(ctx, 0, SEEK_END);
@@ -401,13 +417,13 @@ vectx_close(struct vectx *ctx, int severity, const char *caller)
ctx->vec_path, ctx->vec_want, ctx->vec_hashsz);
}
DEBUG_PRINTF(2,
- ("vectx_close: caller=%s,name='%s',rc=%d,severity=%d\n",
- caller,ctx->vec_path, rc, severity));
- verify_report(ctx->vec_path, severity, rc, NULL);
+ ("vectx_close: caller=%s,name='%s',severity=%d,rc=%d\n",
+ caller,ctx->vec_path, ctx->vec_severity, rc));
+ verify_report(ctx->vec_path, ctx->vec_severity, rc, NULL);
if (rc == VE_FINGERPRINT_WRONG) {
#if !defined(UNIT_TEST) && !defined(DEBUG_VECTX)
/* we are generally called with VE_MUST */
- if (severity > VE_WANT)
+ if (ctx->vec_severity > VE_WANT)
panic("cannot continue");
#endif
}
diff --git a/lib/libsecureboot/verify_file.c b/lib/libsecureboot/verify_file.c
index ee263dafe774..b1aad36672d0 100644
--- a/lib/libsecureboot/verify_file.c
+++ b/lib/libsecureboot/verify_file.c
@@ -271,7 +271,7 @@ find_manifest(const char *name)
# define ACCEPT_NO_FP_DEFAULT VE_MUST
#endif
-static int
+int
severity_guess(const char *filename)
{
const char *cp;
@@ -285,6 +285,7 @@ severity_guess(const char *filename)
*/
if ((cp = strrchr(filename, '.'))) {
if (strcmp(cp, ".cookie") == 0 ||
+ strcmp(cp, ".dof") == 0 ||
strcmp(cp, ".hints") == 0 ||
strcmp(cp, ".order") == 0 ||
strcmp(cp, ".tgz") == 0)
diff --git a/lib/libsys/_exit.2 b/lib/libsys/_exit.2
index 6f038f79f6ea..6e46e65ac86e 100644
--- a/lib/libsys/_exit.2
+++ b/lib/libsys/_exit.2
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd September 8, 2016
+.Dd March 31, 2026
.Dt EXIT 2
.Os
.Sh NAME
@@ -95,9 +95,9 @@ and all current access to the controlling terminal is revoked.
.Pp
Most C programs call the library routine
.Xr exit 3 ,
-which flushes buffers, closes streams, unlinks temporary files, etc.,
-before
-calling
+which flushes buffers, closes streams, unlinks temporary files, invokes
+.Xr atexit 3
+handlers, etc., before calling
.Fn _exit .
.Sh RETURN VALUES
The
@@ -108,6 +108,7 @@ can never return.
.Xr fork 2 ,
.Xr sigaction 2 ,
.Xr wait 2 ,
+.Xr atexit 3 ,
.Xr exit 3 ,
.Xr init 8
.Sh STANDARDS
diff --git a/lib/libsys/fork.2 b/lib/libsys/fork.2
index e59b208a9ff5..89a5631d7daa 100644
--- a/lib/libsys/fork.2
+++ b/lib/libsys/fork.2
@@ -138,6 +138,7 @@ services (
or
.Xr rtld 1 )
are available in the child if forked from multi-threaded parent.
+.Pp
In particular, if using dynamic linking, all dynamic symbols used by the
child after
.Fn _Fork
@@ -151,6 +152,7 @@ option to the static linker
or by using each symbol before the
.Fn _Fork
call to force the binding.
+Either of the methods subtly changes the ABI of the resulting binary.
.Sh RETURN VALUES
Upon successful completion,
.Fn fork
diff --git a/lib/libsys/mq_open.2 b/lib/libsys/mq_open.2
index 4800ab18de59..f0b8618f62a5 100644
--- a/lib/libsys/mq_open.2
+++ b/lib/libsys/mq_open.2
@@ -35,7 +35,7 @@
.\" the referee document. The original Standard can be obtained online at
.\" http://www.opengroup.org/unix/online.html.
.\"
-.Dd May 15, 2024
+.Dd April 2, 2026
.Dt MQ_OPEN 2
.Os
.Sh NAME
@@ -282,6 +282,24 @@ and either
or
.Va mq_msgsize
was less than or equal to zero.
+.It Bq Er EINVAL
+.Dv O_CREAT
+was specified in
+.Fa oflag ,
+the value of
+.Fa attr
+is not
+.Dv NULL ,
+and either
+.Va mq_maxmsg
+exceeds the
+.Va kern.mqueue.maxmsg
+sysctl limit,
+or
+.Va mq_msgsize
+exceeds the
+.Va kern.mqueue.maxmsgsize
+sysctl limit.
.It Bq Er EMFILE
Too many message queue descriptors or file descriptors are currently in use
by this process.
@@ -295,6 +313,9 @@ is longer than
.Brq Dv NAME_MAX .
.It Bq Er ENFILE
Too many message queues are currently open in the system.
+The system limit is controlled by the
+.Va kern.mqueue.maxmq
+sysctl.
.It Bq Er ENOENT
.Dv O_CREAT
is not set and the named message queue does not exist.
diff --git a/lib/libsys/ntp_adjtime.2 b/lib/libsys/ntp_adjtime.2
index 5be5194a9c1d..ed43fb79a9f1 100644
--- a/lib/libsys/ntp_adjtime.2
+++ b/lib/libsys/ntp_adjtime.2
@@ -27,13 +27,13 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd July 13, 2005
+.Dd March 22, 2026
.Dt NTP_ADJTIME 2
.Os
.Sh NAME
.Nm ntp_adjtime ,
.Nm ntp_gettime
-.Nd Network Time Protocol (NTP) daemon interface system calls
+.Nd Network Time Protocol daemon (ntpd) interface system calls
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -59,7 +59,7 @@ The time offset and related variables which are set by
are used by
.Fn hardclock
to adjust the phase and frequency of the phase- or frequency-lock loop
-(PLL resp. FLL) which controls the system clock.
+(PLL resp\&. FLL) which controls the system clock.
.Pp
The
.Fn ntp_gettime
diff --git a/lib/libsys/procctl.2 b/lib/libsys/procctl.2
index dfb7931de265..a09c38c7c977 100644
--- a/lib/libsys/procctl.2
+++ b/lib/libsys/procctl.2
@@ -56,7 +56,7 @@ to control as many of the selected processes as possible.
An error is only returned if no selected processes successfully complete
the request.
The following identifier types are supported:
-.Bl -tag -width P_PGID
+.Bl -tag -width indent
.It Dv P_PID
Control the process with the process ID
.Fa id .
@@ -79,7 +79,7 @@ All status query requests
require the caller to have the right to observe the target.
.Pp
The following commands are supported:
-.Bl -tag -width PROC_LOGSIGEXIT_STATUS
+.Bl -tag -width indent
.It Dv PROC_ASLR_CTL
Controls Address Space Layout Randomization (ASLR) in program
images created
@@ -91,7 +91,7 @@ The
.Fa data
parameter must point to an integer variable holding one of the following
values:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv PROC_ASLR_FORCE_ENABLE
Request that ASLR is enabled after execution, even if it is disabled
system-wide.
@@ -117,7 +117,7 @@ The
.Fa data
parameter must point to an integer variable, where one of the
following values is written:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv PROC_ASLR_FORCE_ENABLE
.It Dv PROC_ASLR_FORCE_DISABLE
.It Dv PROC_ASLR_NOFORCE
@@ -133,7 +133,7 @@ dump.
The
.Va arg
parameter must point to an integer variable holding one of the following values:
-.Bl -tag -width PROC_LOGSIGEXIT_CTL_FORCE_DISABLE
+.Bl -tag -width indent
.It Dv PROC_LOGSIGEXIT_CTL_FORCE_ENABLE
Enables logging of exits due to signals that would normally cause a core dump.
Logging is done via
@@ -155,7 +155,7 @@ The
.Va arg
parameter must point to an integer variable, where one of the following values
is written:
-.Bl -tag -width PROC_LOGSIGEXIT_CTL_FORCE_DISABLE
+.Bl -tag -width indent
.It Dv PROC_LOGSIGEXIT_CTL_FORCE_ENABLE
.It Dv PROC_LOGSIGEXIT_CTL_FORCE_DISABLE
.It Dv PROC_LOGSIGEXIT_CTL_NOFORCE
@@ -186,7 +186,7 @@ The
.Fa data
parameter must point to an integer variable holding one of the following
values:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv PROC_PROTMAX_FORCE_ENABLE
Use the permissions in
.Fa prot
@@ -214,7 +214,7 @@ The
.Fa data
parameter must point to an integer variable, where one of the
following values is written:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv PROC_PROTMAX_FORCE_ENABLE
.It Dv PROC_PROTMAX_FORCE_DISABLE
.It Dv PROC_PROTMAX_NOFORCE
@@ -233,7 +233,7 @@ The
parameter must point to an integer containing an operation and zero or more
optional flags.
The following operations are supported:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv PPROT_SET
Mark the selected processes as protected.
.It Dv PPROT_CLEAR
@@ -241,7 +241,7 @@ Clear the protected state of selected processes.
.El
.Pp
The following optional flags are supported:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv PPROT_DESCEND
Apply the requested operation to all child processes of each selected process
in addition to each selected process.
@@ -300,7 +300,7 @@ struct procctl_reaper_status {
The
.Fa rs_flags
may have the following flags returned:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv REAPER_STATUS_OWNED
The specified process is a reaper.
When this flag is returned, the specified process
@@ -380,7 +380,7 @@ the (grand-)parent of the descendant process.
The
.Fa pi_flags
field returns the following flags, further describing the descendant:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv REAPER_PIDINFO_VALID
Set to indicate that the
.Vt procctl_reaper_pidinfo
@@ -431,7 +431,7 @@ The
.Fa rk_flags
field further directs the operation.
It is or-ed from the following flags:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv REAPER_KILL_CHILDREN
Deliver the specified signal only to direct children of the reaper.
.It Dv REAPER_KILL_SUBTREE
@@ -473,7 +473,7 @@ as well as dumping core.
Possible values for the
.Fa data
argument are:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv PROC_TRACE_CTL_ENABLE
Enable tracing, after it was disabled by
.Dv PROC_TRACE_CTL_DISABLE .
@@ -524,7 +524,7 @@ system call.
Possible values for the
.Fa data
argument are:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv PROC_TRAPCAP_CTL_ENABLE
Enable
.Dv SIGTRAP
@@ -634,7 +634,7 @@ The
.Fa data
argument must point to an integer variable containing flags.
The following flags are allowed:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv PROC_STACKGAP_ENABLE
This flag is only accepted for consistency with
.Dv PROC_STACKGAP_STATUS .
@@ -667,7 +667,7 @@ Returns the current stack gap state for the specified process.
.Fa data
must point to an integer variable, which is used to return a bitmask
consisting of the following flags:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv PROC_STACKGAP_ENABLE
Stack gaps are enabled.
.It Dv PROC_STACKGAP_DISABLE
@@ -699,7 +699,7 @@ The
.Fa data
parameter must point to an integer variable holding the following
value:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv PROC_NO_NEW_PRIVS_ENABLE
Request set-user-ID and set-group-ID bits to be ignored.
.El
@@ -711,7 +711,7 @@ The
.Fa data
parameter must point to an integer variable, where one of the
following values is written:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv PROC_NO_NEW_PRIVS_ENABLE
.It Dv PROC_NO_NEW_PRIVS_DISABLE
.El
@@ -722,7 +722,7 @@ The
.Fa data
parameter must point to an integer variable holding one of the
following values:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv PROC_WX_MAPPINGS_PERMIT
Enable creation of mappings that have both write and execute
permissions in the specified process' current and future address spaces.
@@ -760,7 +760,7 @@ The
.Dv data
parameter must point to an integer variable, where one of the
following values is written:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv PROC_WX_MAPPINGS_PERMIT
Creation of simultaneously writable and executable mappings are permitted;
otherwise, the process cannot create such mappings.
@@ -779,7 +779,7 @@ creation, the
flag is set in the returned value.
.El
.Sh x86 MACHINE-SPECIFIC REQUESTS
-.Bl -tag -width PROC_KPTI_STATUS
+.Bl -tag -width indent
.It Dv PROC_KPTI_CTL
AMD64 only.
Controls the Kernel Page Table Isolation (KPTI) option for the children
@@ -795,7 +795,7 @@ The
.Fa data
parameter must point to an integer variable containing one of the
following commands:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv PROC_KPTI_CTL_ENABLE_ON_EXEC
Enable KPTI after
.Xr execve 2 .
@@ -811,7 +811,7 @@ Returns the current KPTI status for the specified process.
.Fa data
must point to an integer variable, where one of the
following values is written:
-.Bl -tag -width Ds
+.Bl -tag -width indent
.It Dv PROC_KPTI_CTL_ENABLE_ON_EXEC
.It Dv PROC_KPTI_CTL_DISABLE_ON_EXEC
.El
diff --git a/lib/libsys/shm_open.2 b/lib/libsys/shm_open.2
index c3196d966e6b..58597a341b9e 100644
--- a/lib/libsys/shm_open.2
+++ b/lib/libsys/shm_open.2
@@ -26,7 +26,7 @@
.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd August 4, 2025
+.Dd March 26, 2025
.Dt SHM_OPEN 2
.Os
.Sh NAME
@@ -343,7 +343,25 @@ Allow adding seals to the resulting file descriptor using the
.Xr fcntl 2
command.
.It Dv MFD_HUGETLB
-This flag is currently unsupported.
+Create a memfd backed by a
+.Dq largepage
+object.
+One of the
+.Dv MFD_HUGE_*
+flags defined in
+.In sys/mman.h
+may be included to specify a fixed size.
+If a specific size is not requested, the smallest supported large page size is
+selected.
+.Pp
+The behavior documented above for the
+.Fn shm_create_largepage
+.Fa psind
+argument also applies to largepage objects created by
+.Fn memfd_create ,
+and the
+.Dv SHM_LARGEPAGE_ALLOC_DEFAULT
+policy will always be used.
.El
.Sh RETURN VALUES
If successful,
@@ -458,17 +476,22 @@ argument was too long.
.Pp
An invalid or unsupported flag was included in
.Fa flags .
+.It Bq Er EINVAL
+A hugetlb mapping was requested, but
+.Dv MFD_HUGETLB
+was not specified in
+.Fa flags .
.It Bq Er EMFILE
The process has already reached its limit for open file descriptors.
.It Bq Er ENFILE
The system file table is full.
.It Bq Er ENOSYS
-In
-.Fa memfd_create ,
.Dv MFD_HUGETLB
was specified in
.Fa flags ,
and this system does not support forced hugetlb mappings.
+.It Bq Er EOPNOTSUPP
+This system does not support the requested hugetlb page size.
.El
.Pp
.Fn shm_open
diff --git a/lib/libsys/stat.2 b/lib/libsys/stat.2
index 8107740bd901..b31975ee068f 100644
--- a/lib/libsys/stat.2
+++ b/lib/libsys/stat.2
@@ -295,7 +295,7 @@ has these bits:
#define S_IFWHT 0160000 /* whiteout */
#define S_ISUID 0004000 /* set user id on execution */
#define S_ISGID 0002000 /* set group id on execution */
-#define S_ISVTX 0001000 /* save swapped text even after use */
+#define S_ISVTX 0001000 /* sticky(7) bit is set */
#define S_IRWXU 0000700 /* RWX mask for owner */
#define S_IRUSR 0000400 /* read permission, owner */
#define S_IWUSR 0000200 /* write permission, owner */
diff --git a/lib/libsys/x86/pkru.3 b/lib/libsys/x86/pkru.3
index 95bc66c979ac..75580953e6ed 100644
--- a/lib/libsys/x86/pkru.3
+++ b/lib/libsys/x86/pkru.3
@@ -71,17 +71,17 @@ Only one key may apply to a given range at a time.
The default protection key index is zero, it is used even if no key
was explicitly assigned to the address, or if the key was removed.
.Pp
-The protection prevents the system from accessing user addresses as well
-as the user applications.
-When a system call was unable to read or write user memory due to key
-protection, it returns the
-.Er EFAULT
-error code.
-Note that some side effects may have occurred if this error is reported.
+If the user application attempts a memory access which is prohibited by the
+PKRU register, the offending thread receives a synchronous
+.Dv SIGSEGV
+signal with
+.Va si_code
+set to
+.Dv SEGV_PKUERR .
+PKRU protections might prevent the kernel from accessing protected
+user addresses when handling system calls, but this is not guaranteed and
+must not be relied upon.
.Pp
-Protection keys require that the system uses 4-level paging
-(also called long mode),
-which means that it is only available on amd64 system.
Both 64-bit and 32-bit applications can use protection keys.
More information about the hardware feature is provided in the IA32 Software
Developer's Manual published by Intel Corp.
diff --git a/lib/libsysdecode/Makefile b/lib/libsysdecode/Makefile
index 60422d3fc9ef..85c76bcffd8e 100644
--- a/lib/libsysdecode/Makefile
+++ b/lib/libsysdecode/Makefile
@@ -2,7 +2,7 @@
LIB= sysdecode
-SRCS= errno.c flags.c ioctl.c signal.c syscallnames.c utrace.c support.c
+SRCS= errno.c flags.c ioctl.c netlink.c signal.c syscallnames.c utrace.c support.c
.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" || \
${MACHINE_CPUARCH} == "i386"
SRCS+= linux.c
diff --git a/lib/libsysdecode/netlink.c b/lib/libsysdecode/netlink.c
new file mode 100644
index 000000000000..a28a0a061134
--- /dev/null
+++ b/lib/libsysdecode/netlink.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2026 Ishan Agrawal
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/param.h>
+#include <netlink/netlink.h>
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#include "sysdecode.h"
+
+/*
+ * Decodes a buffer as a Netlink message stream.
+ *
+ * Returns true if the data was successfully decoded as Netlink.
+ * Returns false if the data is malformed, allowing the caller
+ * to fallback to a standard hex/string dump.
+ */
+bool
+sysdecode_netlink(FILE *fp, const void *buf, size_t len)
+{
+ const struct nlmsghdr *nl = buf;
+ size_t remaining = len;
+ bool first = true;
+
+ /* Basic sanity check: Buffer must be at least one header size. */
+ if (remaining < sizeof(struct nlmsghdr))
+ return (false);
+
+ /* * Protocol Sanity Check:
+ * The first message length must be valid (>= header) and fit
+ * inside the provided buffer snapshot.
+ */
+ if (nl->nlmsg_len < sizeof(struct nlmsghdr) || nl->nlmsg_len > remaining)
+ return (false);
+
+ fprintf(fp, "netlink{");
+
+ while (remaining >= sizeof(struct nlmsghdr)) {
+ if (!first)
+ fprintf(fp, ",");
+
+ /* Safety check for current message. */
+ if (nl->nlmsg_len < sizeof(struct nlmsghdr) ||
+ nl->nlmsg_len > remaining) {
+ fprintf(fp, "<truncated>");
+ break;
+ }
+
+ fprintf(fp, "len=%u,type=", nl->nlmsg_len);
+
+ /* Decode Standard Message Types. */
+ switch (nl->nlmsg_type) {
+ case NLMSG_NOOP:
+ fprintf(fp, "NLMSG_NOOP");
+ break;
+ case NLMSG_ERROR:
+ fprintf(fp, "NLMSG_ERROR");
+ break;
+ case NLMSG_DONE:
+ fprintf(fp, "NLMSG_DONE");
+ break;
+ case NLMSG_OVERRUN:
+ fprintf(fp, "NLMSG_OVERRUN");
+ break;
+ default:
+ fprintf(fp, "%u", nl->nlmsg_type);
+ break;
+ }
+
+ fprintf(fp, ",flags=");
+ /* TODO: decode flags symbolically using sysdecode_mask. */
+ fprintf(fp, "0x%x", nl->nlmsg_flags);
+
+ fprintf(fp, ",seq=%u,pid=%u", nl->nlmsg_seq, nl->nlmsg_pid);
+
+ /* Handle Alignment (Netlink messages are 4-byte aligned). */
+ size_t aligned_len = NLMSG_ALIGN(nl->nlmsg_len);
+ if (aligned_len > remaining)
+ remaining = 0;
+ else
+ remaining -= aligned_len;
+
+ nl = (const struct nlmsghdr *)(const void *)((const char *)nl + aligned_len);
+ first = false;
+ }
+
+ fprintf(fp, "}");
+ return (true);
+}
diff --git a/lib/libsysdecode/sysdecode.h b/lib/libsysdecode/sysdecode.h
index c95d7f71379b..dad9d447478c 100644
--- a/lib/libsysdecode/sysdecode.h
+++ b/lib/libsysdecode/sysdecode.h
@@ -134,6 +134,7 @@ bool sysdecode_wait4_options(FILE *_fp, int _options, int *_rem);
bool sysdecode_wait6_options(FILE *_fp, int _options, int *_rem);
const char *sysdecode_whence(int _whence);
bool sysdecode_shmflags(FILE *_fp, int _flags, int *_rem);
+bool sysdecode_netlink(FILE *_fp, const void *_buf, size_t _len);
#if defined(__i386__) || defined(__amd64__) || defined(__aarch64__)
diff --git a/lib/libthr/libthr.3 b/lib/libthr/libthr.3
index b84176abcd32..5d9c5ec6706b 100644
--- a/lib/libthr/libthr.3
+++ b/lib/libthr/libthr.3
@@ -52,6 +52,12 @@ The library is tightly integrated with the run-time link editor
and
.Lb libc ;
all three components must be built from the same source tree.
+Together, they constitute the base C runtime environment of
+.Fx ,
+running on top of the
+.Fx
+kernel.
+.Pp
Mixing
.Li libc
and
@@ -263,6 +269,25 @@ the critical section.
This should be taken into account when interpreting
.Xr ktrace 1
logs.
+.Pp
+The
+.Nm
+library uses the
+.Va SIGTHR
+signal for internal operations, in particular,
+for cancellation requests.
+This signal's masking and disposition is controlled by the library,
+and user programs should not try to modify them.
+The library interposes functions controlling signals to prevent
+inadvertent modifications and to guard portable code against
+exposure to
+.Va SIGTHR .
+.Pp
+Note: similarly, the
+.Va SIGLIBRT
+signal is reserved for use by
+.Lb librt ,
+and should be not modified by users.
.Sh PROCESS-SHARED SYNCHRONIZATION OBJECTS
In the
.Li libthr
diff --git a/lib/libzstd/Makefile b/lib/libzstd/Makefile
index 4a1557a14517..82e9d2a5b243 100644
--- a/lib/libzstd/Makefile
+++ b/lib/libzstd/Makefile
@@ -15,6 +15,7 @@ SRCS= entropy_common.c \
zstd_compress_literals.c \
zstd_compress_sequences.c \
zstd_compress_superblock.c \
+ zstd_preSplit.c \
zstdmt_compress.c \
huf_decompress.c \
zstd_ddict.c \
@@ -54,6 +55,9 @@ ZSTDDIR= ${SRCTOP}/sys/contrib/zstd
.include <bsd.compiler.mk>
+# These symbols are needed by dll-linked CLI zstd(1).
+CFLAGS.pool.c+= -fvisibility=default
+
CFLAGS.huf_decompress.c+= ${NO_WBITWISE_INSTEAD_OF_LOGICAL}
# https://github.com/facebook/zstd/commit/812e8f2a [zstd 1.4.1]
diff --git a/lib/msun/Makefile b/lib/msun/Makefile
index 24989749a502..d61f4e9a1659 100644
--- a/lib/msun/Makefile
+++ b/lib/msun/Makefile
@@ -75,8 +75,11 @@ COMMON_SRCS= b_tgamma.c \
s_exp2.c s_exp2f.c s_expm1.c s_expm1f.c s_fabsf.c s_fdim.c \
s_finite.c s_finitef.c \
s_floor.c s_floorf.c s_fma.c s_fmaf.c \
- s_fmax.c s_fmaxf.c s_fmin.c \
- s_fminf.c s_frexp.c s_frexpf.c s_ilogb.c s_ilogbf.c \
+ s_fmax.c s_fmaxf.c s_fmaximum.c s_fmaximumf.c \
+ s_fmaximum_mag.c s_fmaximum_magf.c s_fmaximum_num.c s_fmaximum_numf.c \
+ s_fmin.c s_fminf.c s_fminimum.c s_fminimumf.c \
+ s_fminimum_mag.c s_fminimum_magf.c s_fminimum_num.c s_fminimum_numf.c \
+ s_frexp.c s_frexpf.c s_ilogb.c s_ilogbf.c \
s_ilogbl.c s_isfinite.c s_isnan.c s_isnormal.c \
s_llrint.c s_llrintf.c s_llround.c s_llroundf.c s_llroundl.c \
s_log1p.c s_log1pf.c s_logb.c s_logbf.c s_lrint.c s_lrintf.c \
@@ -114,6 +117,7 @@ LIBC_ARCH=${MACHINE_CPUARCH}
CFLAGS+= -I${.CURDIR}/src -I${LIBC_SRCTOP}/include \
-I${LIBC_SRCTOP}/${LIBC_ARCH}
SYM_MAPS+= ${.CURDIR}/Symbol.map
+SYM_MAPS+= ${.CURDIR}/${ARCH_SUBDIR}/Symbol.map
VERSION_DEF= ${LIBC_SRCTOP}/Versions.def
SYMBOL_MAPS= ${SYM_MAPS}
@@ -131,7 +135,9 @@ COMMON_SRCS+= b_tgammal.c catrigl.c \
s_asinhl.c s_atanl.c s_cbrtl.c s_ceill.c s_cexpl.c \
s_clogl.c s_cosl.c s_cospil.c s_cprojl.c \
s_csqrtl.c s_erfl.c s_exp2l.c s_expl.c s_floorl.c s_fmal.c \
- s_fmaxl.c s_fminl.c s_frexpl.c s_logbl.c s_logl.c s_nanl.c \
+ s_fmaxl.c s_fmaximuml.c s_fmaximum_magl.c s_fmaximum_numl.c \
+ s_fminl.c s_fminimuml.c s_fminimum_magl.c s_fminimum_numl.c \
+ s_frexpl.c s_logbl.c s_logl.c s_nanl.c \
s_nextafterl.c s_nexttoward.c s_remquol.c s_rintl.c s_roundl.c \
s_scalbnl.c s_sinl.c s_sincosl.c s_sinpil.c \
s_tanhl.c s_tanl.c s_tanpil.c s_truncl.c w_cabsl.c
@@ -175,8 +181,9 @@ MAN= acos.3 acosh.3 asin.3 asinh.3 atan.3 atan2.3 atanh.3 \
cpow.3 csqrt.3 erf.3 \
exp.3 fabs.3 fdim.3 \
feclearexcept.3 feenableexcept.3 fegetenv.3 \
- fegetround.3 fenv.3 floor.3 \
- fma.3 fmax.3 fmod.3 hypot.3 ieee.3 ieee_test.3 ilogb.3 j0.3 \
+ fegetround.3 fenv.3 floor.3 fma.3 \
+ fmax.3 fmaximum.3 fmaximum_mag.3 fmaximum_num.3 fmod.3 \
+ hypot.3 ieee.3 ieee_test.3 ilogb.3 j0.3 \
lgamma.3 log.3 lrint.3 lround.3 math.3 nan.3 \
nextafter.3 remainder.3 rint.3 \
round.3 scalbn.3 signbit.3 sin.3 sincos.3 \
@@ -229,6 +236,15 @@ MLINKS+=floor.3 floorf.3 floor.3 floorl.3
MLINKS+=fma.3 fmaf.3 fma.3 fmal.3
MLINKS+=fmax.3 fmaxf.3 fmax.3 fmaxl.3 \
fmax.3 fmin.3 fmax.3 fminf.3 fmax.3 fminl.3
+MLINKS+=fmaximum.3 fmaximumf.3 fmaximum.3 fmaximuml.3 \
+ fmaximum.3 fminimum.3 fmaximum.3 fminimumf.3 \
+ fmaximum.3 fminimuml.3
+MLINKS+=fmaximum_mag.3 fmaximum_magf.3 fmaximum_mag.3 fmaximum_magl.3 \
+ fmaximum_mag.3 fminimum_mag.3 fmaximum_mag.3 fminimum_magf.3 \
+ fmaximum_mag.3 fminimum_magl.3
+MLINKS+=fmaximum_num.3 fmaximum_numf.3 fmaximum_num.3 fmaximum_numl.3 \
+ fmaximum_num.3 fminimum_num.3 fmaximum_num.3 fminimum_numf.3 \
+ fmaximum_num.3 fminimum_numl.3
MLINKS+=fmod.3 fmodf.3 fmod.3 fmodl.3
MLINKS+=hypot.3 cabs.3 hypot.3 cabsf.3 hypot.3 cabsl.3 \
hypot.3 hypotf.3 hypot.3 hypotl.3
diff --git a/lib/msun/Symbol.map b/lib/msun/Symbol.map
index 4d5a5e4d7e6e..35addfcee3d5 100644
--- a/lib/msun/Symbol.map
+++ b/lib/msun/Symbol.map
@@ -316,3 +316,26 @@ FBSD_1.7 {
tanpif;
tanpil;
};
+
+/* First added in 16.0-CURRENT */
+
+FBSD_1.9 {
+ fmaximum;
+ fmaximumf;
+ fmaximuml;
+ fminimum;
+ fminimumf;
+ fminimuml;
+ fmaximum_mag;
+ fmaximum_magf;
+ fmaximum_magl;
+ fminimum_mag;
+ fminimum_magf;
+ fminimum_magl;
+ fmaximum_num;
+ fmaximum_numf;
+ fmaximum_numl;
+ fminimum_num;
+ fminimum_numf;
+ fminimum_numl;
+};
diff --git a/lib/msun/aarch64/Symbol.map b/lib/msun/aarch64/Symbol.map
new file mode 100644
index 000000000000..b468c814ff06
--- /dev/null
+++ b/lib/msun/aarch64/Symbol.map
@@ -0,0 +1,10 @@
+FBSD_1.9 {
+ fesetexceptflag;
+ feraiseexcept;
+ fegetenv;
+ feholdexcept;
+ feupdateenv;
+ feenableexcept;
+ fedisableexcept;
+ fegetexcept;
+};
diff --git a/lib/msun/aarch64/fenv.c b/lib/msun/aarch64/fenv.c
index 4c54656be7d3..3d7e467880c7 100644
--- a/lib/msun/aarch64/fenv.c
+++ b/lib/msun/aarch64/fenv.c
@@ -25,7 +25,6 @@
* SUCH DAMAGE.
*/
-#define __fenv_static
#include "fenv.h"
/*
@@ -34,26 +33,86 @@
*/
const fenv_t __fe_dfl_env = 0;
-#ifdef __GNUC_GNU_INLINE__
-#error "This file must be compiled with C99 'inline' semantics"
-#endif
-
int
(feclearexcept)(int excepts)
{
return (__feclearexcept_int(excepts));
}
-extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
-extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
-extern inline int feraiseexcept(int __excepts);
-extern inline int fetestexcept(int __excepts);
-extern inline int fegetround(void);
-extern inline int fesetround(int __round);
-extern inline int fegetenv(fenv_t *__envp);
-extern inline int feholdexcept(fenv_t *__envp);
-extern inline int fesetenv(const fenv_t *__envp);
-extern inline int feupdateenv(const fenv_t *__envp);
-extern inline int feenableexcept(int __mask);
-extern inline int fedisableexcept(int __mask);
-extern inline int fegetexcept(void);
+int
+(fegetexceptflag)(fexcept_t *flagp, int excepts)
+{
+ return (__fegetexceptflag_int(flagp, excepts));
+}
+
+int
+(fesetexceptflag)(const fexcept_t *flagp, int excepts)
+{
+ return (__fesetexceptflag_int(flagp, excepts));
+}
+
+int
+(feraiseexcept)(int excepts)
+{
+ return (__feraiseexcept_int(excepts));
+}
+
+int
+(fetestexcept)(int excepts)
+{
+ return (__fetestexcept_int(excepts));
+}
+
+int
+(fegetround)(void)
+{
+ return (__fegetround_int());
+}
+
+int
+(fesetround)(int round)
+{
+ return (__fesetround_int(round));
+}
+
+int
+(fegetenv)(fenv_t *envp)
+{
+ return (__fegetenv_int(envp));
+}
+
+int
+(feholdexcept)(fenv_t *envp)
+{
+ return (__feholdexcept_int(envp));
+}
+
+int
+(fesetenv)(const fenv_t *envp)
+{
+ return (__fesetenv_int(envp));
+}
+
+int
+(feupdateenv)(const fenv_t *envp)
+{
+ return (__feupdateenv_int(envp));
+}
+
+int
+(feenableexcept)(int mask)
+{
+ return (__feenableexcept_int(mask));
+}
+
+int
+(fedisableexcept)(int mask)
+{
+ return (__fedisableexcept_int(mask));
+}
+
+int
+(fegetexcept)(void)
+{
+ return (__fegetexcept_int());
+}
diff --git a/lib/msun/aarch64/fenv.h b/lib/msun/aarch64/fenv.h
index d125978b887b..5d47940cf9eb 100644
--- a/lib/msun/aarch64/fenv.h
+++ b/lib/msun/aarch64/fenv.h
@@ -82,7 +82,34 @@ extern const fenv_t __fe_dfl_env;
#define __msr_fpsr(__r) __asm __volatile("msr fpsr, %0" : : "r" (__r))
int feclearexcept(int);
+int fegetexceptflag(fexcept_t *, int);
+int fesetexceptflag(const fexcept_t *, int);
+int feraiseexcept(int);
+int fetestexcept(int);
+int fegetround(void);
+int fesetround(int);
+int fegetenv(fenv_t *);
+int feholdexcept(fenv_t *);
+int fesetenv(const fenv_t *);
+int feupdateenv(const fenv_t *);
+int feenableexcept(int);
+int fedisableexcept(int);
+int fegetexcept(void);
+
#define feclearexcept(a) __feclearexcept_int(a)
+#define fegetexceptflag(e, a) __fegetexceptflag_int(e, a)
+#define fesetexceptflag(e, a) __fesetexceptflag_int(e, a)
+#define feraiseexcept(a) __feraiseexcept_int(a)
+#define fetestexcept(a) __fetestexcept_int(a)
+#define fegetround() __fegetround_int()
+#define fesetround(a) __fesetround_int(a)
+#define fegetenv(e) __fegetenv_int(e)
+#define feholdexcept(e) __feholdexcept_int(e)
+#define fesetenv(e) __fesetenv_int(e)
+#define feupdateenv(e) __feupdateenv_int(e)
+#define feenableexcept(a) __feenableexcept_int(a)
+#define fedisableexcept(a) __fedisableexcept_int(a)
+#define fegetexcept() __fegetexcept_int()
__fenv_static inline int
__feclearexcept_int(int __excepts)
@@ -96,7 +123,7 @@ __feclearexcept_int(int __excepts)
}
__fenv_static inline int
-fegetexceptflag(fexcept_t *__flagp, int __excepts)
+__fegetexceptflag_int(fexcept_t *__flagp, int __excepts)
{
fexcept_t __r;
@@ -106,7 +133,7 @@ fegetexceptflag(fexcept_t *__flagp, int __excepts)
}
__fenv_static inline int
-fesetexceptflag(const fexcept_t *__flagp, int __excepts)
+__fesetexceptflag_int(const fexcept_t *__flagp, int __excepts)
{
fexcept_t __r;
@@ -118,7 +145,7 @@ fesetexceptflag(const fexcept_t *__flagp, int __excepts)
}
__fenv_static inline int
-feraiseexcept(int __excepts)
+__feraiseexcept_int(int __excepts)
{
fexcept_t __r;
@@ -129,7 +156,7 @@ feraiseexcept(int __excepts)
}
__fenv_static inline int
-fetestexcept(int __excepts)
+__fetestexcept_int(int __excepts)
{
fexcept_t __r;
@@ -138,7 +165,7 @@ fetestexcept(int __excepts)
}
__fenv_static inline int
-fegetround(void)
+__fegetround_int(void)
{
fenv_t __r;
@@ -147,7 +174,7 @@ fegetround(void)
}
__fenv_static inline int
-fesetround(int __round)
+__fesetround_int(int __round)
{
fenv_t __r;
@@ -161,7 +188,7 @@ fesetround(int __round)
}
__fenv_static inline int
-fegetenv(fenv_t *__envp)
+__fegetenv_int(fenv_t *__envp)
{
__uint64_t fpcr;
__uint64_t fpsr;
@@ -174,7 +201,7 @@ fegetenv(fenv_t *__envp)
}
__fenv_static inline int
-feholdexcept(fenv_t *__envp)
+__feholdexcept_int(fenv_t *__envp)
{
fenv_t __r;
@@ -191,7 +218,7 @@ feholdexcept(fenv_t *__envp)
}
__fenv_static inline int
-fesetenv(const fenv_t *__envp)
+__fesetenv_int(const fenv_t *__envp)
{
__msr_fpcr((*__envp) >> 32);
@@ -200,7 +227,7 @@ fesetenv(const fenv_t *__envp)
}
__fenv_static inline int
-feupdateenv(const fenv_t *__envp)
+__feupdateenv_int(const fenv_t *__envp)
{
fexcept_t __r;
@@ -212,10 +239,8 @@ feupdateenv(const fenv_t *__envp)
#if __BSD_VISIBLE
-/* We currently provide no external definitions of the functions below. */
-
static inline int
-feenableexcept(int __mask)
+__feenableexcept_int(int __mask)
{
fenv_t __old_r, __new_r;
@@ -226,7 +251,7 @@ feenableexcept(int __mask)
}
static inline int
-fedisableexcept(int __mask)
+__fedisableexcept_int(int __mask)
{
fenv_t __old_r, __new_r;
@@ -237,7 +262,7 @@ fedisableexcept(int __mask)
}
static inline int
-fegetexcept(void)
+__fegetexcept_int(void)
{
fenv_t __r;
diff --git a/lib/msun/amd64/Makefile.inc b/lib/msun/amd64/Makefile.inc
index dcdc2495d690..f1e6aef552ca 100644
--- a/lib/msun/amd64/Makefile.inc
+++ b/lib/msun/amd64/Makefile.inc
@@ -6,4 +6,3 @@ ARCH_SRCS = e_fmod.S e_fmodf.S e_fmodl.S \
s_remquo.S s_remquof.S s_remquol.S \
s_rintl.S s_scalbn.S s_scalbnf.S s_scalbnl.S
LDBL_PREC = 64
-SYM_MAPS += ${.CURDIR}/amd64/Symbol.map
diff --git a/lib/msun/amd64/fenv.c b/lib/msun/amd64/fenv.c
index cd3b83d11585..fe9ecfff3b83 100644
--- a/lib/msun/amd64/fenv.c
+++ b/lib/msun/amd64/fenv.c
@@ -29,13 +29,8 @@
#include <sys/types.h>
#include <machine/fpu.h>
-#define __fenv_static
#include "fenv.h"
-#ifdef __GNUC_GNU_INLINE__
-#error "This file must be compiled with C99 'inline' semantics"
-#endif
-
const fenv_t __fe_dfl_env = {
{ 0xffff0000 | __INITIAL_FPUCW__,
0xffff0000,
@@ -52,7 +47,11 @@ int
return (__feclearexcept_int(excepts));
}
-extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
+int
+(fegetexceptflag)(fexcept_t *flagp, int excepts)
+{
+ return (__fegetexceptflag_int(flagp, excepts));
+}
int
fesetexceptflag(const fexcept_t *flagp, int excepts)
@@ -82,9 +81,23 @@ feraiseexcept(int excepts)
return (0);
}
-extern inline int fetestexcept(int __excepts);
-extern inline int fegetround(void);
-extern inline int fesetround(int __round);
+int
+(fetestexcept)(int excepts)
+{
+ return (__fetestexcept_int(excepts));
+}
+
+int
+(fegetround)(void)
+{
+ return (__fegetround_int());
+}
+
+int
+(fesetround)(int round)
+{
+ return (__fesetround_int(round));
+}
int
fegetenv(fenv_t *envp)
@@ -115,7 +128,11 @@ feholdexcept(fenv_t *envp)
return (0);
}
-extern inline int fesetenv(const fenv_t *__envp);
+int
+(fesetenv)(const fenv_t *envp)
+{
+ return (__fesetenv_int(envp));
+}
int
feupdateenv(const fenv_t *envp)
diff --git a/lib/msun/arm/Makefile.inc b/lib/msun/arm/Makefile.inc
index 6e3ddb351dd3..e155f1a2cae4 100644
--- a/lib/msun/arm/Makefile.inc
+++ b/lib/msun/arm/Makefile.inc
@@ -1,5 +1,4 @@
LDBL_PREC = 53
-SYM_MAPS += ${.CURDIR}/arm/Symbol.map
.if defined(CPUTYPE) && ${CPUTYPE:M*soft*} != ""
ARCH_SRCS = fenv-softfp.c fenv-vfp.c
diff --git a/lib/msun/arm/fenv.c b/lib/msun/arm/fenv.c
index c8edf3fef037..2cf5bbdea28f 100644
--- a/lib/msun/arm/fenv.c
+++ b/lib/msun/arm/fenv.c
@@ -27,7 +27,6 @@
* SUCH DAMAGE.
*/
-#define __fenv_static
#include "fenv.h"
#include <machine/acle-compat.h>
@@ -66,29 +65,89 @@ const fenv_t __fe_dfl_env = 0;
#include "fenv-softfloat.h"
#endif
-#ifdef __GNUC_GNU_INLINE__
-#error "This file must be compiled with C99 'inline' semantics"
-#endif
-
int
(feclearexcept)(int excepts)
{
return (__feclearexcept_int(excepts));
}
-extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
-extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
-extern inline int feraiseexcept(int __excepts);
-extern inline int fetestexcept(int __excepts);
-extern inline int fegetround(void);
-extern inline int fesetround(int __round);
-extern inline int fegetenv(fenv_t *__envp);
-extern inline int feholdexcept(fenv_t *__envp);
-extern inline int fesetenv(const fenv_t *__envp);
-extern inline int feupdateenv(const fenv_t *__envp);
-extern inline int feenableexcept(int __mask);
-extern inline int fedisableexcept(int __mask);
-extern inline int fegetexcept(void);
+int
+(fegetexceptflag)(fexcept_t *flagp, int excepts)
+{
+ return (__fegetexceptflag_int(flagp, excepts));
+}
+
+int
+(fesetexceptflag)(const fexcept_t *flagp, int excepts)
+{
+ return (__fesetexceptflag_int(flagp, excepts));
+}
+
+int
+(feraiseexcept)(int excepts)
+{
+ return (__feraiseexcept_int(excepts));
+}
+
+int
+(fetestexcept)(int excepts)
+{
+ return (__fetestexcept_int(excepts));
+}
+
+int
+(fegetround)(void)
+{
+ return (__fegetround_int());
+}
+
+int
+(fesetround)(int round)
+{
+ return (__fesetround_int(round));
+}
+
+int
+(fegetenv)(fenv_t *envp)
+{
+ return (__fegetenv_int(envp));
+}
+
+int
+(feholdexcept)(fenv_t *envp)
+{
+ return (__feholdexcept_int(envp));
+}
+
+int
+(fesetenv)(const fenv_t *envp)
+{
+ return (__fesetenv_int(envp));
+}
+
+int
+(feupdateenv)(const fenv_t *envp)
+{
+ return (__feupdateenv_int(envp));
+}
+
+int
+(feenableexcept)(int mask)
+{
+ return (__feenableexcept_int(mask));
+}
+
+int
+(fedisableexcept)(int mask)
+{
+ return (__fedisableexcept_int(mask));
+}
+
+int
+(fegetexcept)(void)
+{
+ return (__fegetexcept_int());
+}
#else /* !FENV_MANGLE && SOFTFP_ABI */
/* Set by libc when the VFP unit is enabled */
@@ -158,7 +217,8 @@ __softfp_round_from_vfp(int round)
}
}
-int feclearexcept(int __excepts)
+int
+(feclearexcept)(int __excepts)
{
if (_libc_arm_fpu_present)
@@ -168,7 +228,8 @@ int feclearexcept(int __excepts)
return (0);
}
-int fegetexceptflag(fexcept_t *__flagp, int __excepts)
+int
+(fegetexceptflag)(fexcept_t *__flagp, int __excepts)
{
fexcept_t __vfp_flagp;
@@ -182,7 +243,8 @@ int fegetexceptflag(fexcept_t *__flagp, int __excepts)
return (0);
}
-int fesetexceptflag(const fexcept_t *__flagp, int __excepts)
+int
+(fesetexceptflag)(const fexcept_t *__flagp, int __excepts)
{
if (_libc_arm_fpu_present)
@@ -192,7 +254,8 @@ int fesetexceptflag(const fexcept_t *__flagp, int __excepts)
return (0);
}
-int feraiseexcept(int __excepts)
+int
+(feraiseexcept)(int __excepts)
{
if (_libc_arm_fpu_present)
@@ -202,7 +265,8 @@ int feraiseexcept(int __excepts)
return (0);
}
-int fetestexcept(int __excepts)
+int
+(fetestexcept)(int __excepts)
{
int __got_excepts;
@@ -214,7 +278,8 @@ int fetestexcept(int __excepts)
return (__got_excepts);
}
-int fegetround(void)
+int
+(fegetround)(void)
{
if (_libc_arm_fpu_present)
@@ -222,7 +287,8 @@ int fegetround(void)
return __softfp_fegetround();
}
-int fesetround(int __round)
+int
+(fesetround)(int __round)
{
if (_libc_arm_fpu_present)
@@ -232,7 +298,8 @@ int fesetround(int __round)
return (0);
}
-int fegetenv(fenv_t *__envp)
+int
+(fegetenv)(fenv_t *__envp)
{
fenv_t __vfp_envp;
@@ -245,7 +312,8 @@ int fegetenv(fenv_t *__envp)
return (0);
}
-int feholdexcept(fenv_t *__envp)
+int
+(feholdexcept)(fenv_t *__envp)
{
fenv_t __vfp_envp;
@@ -258,7 +326,8 @@ int feholdexcept(fenv_t *__envp)
return (0);
}
-int fesetenv(const fenv_t *__envp)
+int
+(fesetenv)(const fenv_t *__envp)
{
if (_libc_arm_fpu_present)
@@ -268,7 +337,8 @@ int fesetenv(const fenv_t *__envp)
return (0);
}
-int feupdateenv(const fenv_t *__envp)
+int
+(feupdateenv)(const fenv_t *__envp)
{
if (_libc_arm_fpu_present)
@@ -278,7 +348,8 @@ int feupdateenv(const fenv_t *__envp)
return (0);
}
-int feenableexcept(int __mask)
+int
+(feenableexcept)(int __mask)
{
int __unmasked;
@@ -290,7 +361,8 @@ int feenableexcept(int __mask)
return (__unmasked);
}
-int fedisableexcept(int __mask)
+int
+(fedisableexcept)(int __mask)
{
int __unmasked;
@@ -302,7 +374,8 @@ int fedisableexcept(int __mask)
return (__unmasked);
}
-int fegetexcept(void)
+int
+(fegetexcept)(void)
{
int __unmasked;
@@ -315,4 +388,3 @@ int fegetexcept(void)
}
#endif
-
diff --git a/lib/msun/arm/fenv.h b/lib/msun/arm/fenv.h
index 14638dd33aa7..78ca9ef0f589 100644
--- a/lib/msun/arm/fenv.h
+++ b/lib/msun/arm/fenv.h
@@ -112,7 +112,39 @@ int fegetexcept(void);
#define _FPU_MASK_SHIFT 8
int feclearexcept(int);
+int fegetexceptflag(fexcept_t *, int);
+int fesetexceptflag(const fexcept_t *, int);
+int feraiseexcept(int);
+int fetestexcept(int);
+int fegetround(void);
+int fesetround(int);
+int fegetenv(fenv_t *);
+int feholdexcept(fenv_t *);
+int fesetenv(const fenv_t *);
+int feupdateenv(const fenv_t *);
+int fegetexcept(void);
+#if __BSD_VISIBLE
+int feenableexcept(int);
+int fedisableexcept(int);
+int fegetexcept(void);
+#endif
+
#define feclearexcept(a) __feclearexcept_int(a)
+#define fegetexceptflag(e, a) __fegetexceptflag_int(e, a)
+#define fesetexceptflag(e, a) __fesetexceptflag_int(e, a)
+#define feraiseexcept(a) __feraiseexcept_int(a)
+#define fetestexcept(a) __fetestexcept_int(a)
+#define fegetround() __fegetround_int()
+#define fesetround(a) __fesetround_int(a)
+#define fegetenv(e) __fegetenv_int(e)
+#define feholdexcept(e) __feholdexcept_int(e)
+#define fesetenv(e) __fesetenv_int(e)
+#define feupdateenv(e) __feupdateenv_int(e)
+#if __BSD_VISIBLE
+#define feenableexcept(a) __feenableexcept_int(a)
+#define fedisableexcept(a) __fedisableexcept_int(a)
+#define fegetexcept() __fegetexcept_int()
+#endif
__fenv_static inline int
__feclearexcept_int(int __excepts)
@@ -126,7 +158,7 @@ __feclearexcept_int(int __excepts)
}
__fenv_static inline int
-fegetexceptflag(fexcept_t *__flagp, int __excepts)
+__fegetexceptflag_int(fexcept_t *__flagp, int __excepts)
{
fexcept_t __fpsr;
@@ -136,7 +168,7 @@ fegetexceptflag(fexcept_t *__flagp, int __excepts)
}
__fenv_static inline int
-fesetexceptflag(const fexcept_t *__flagp, int __excepts)
+__fesetexceptflag_int(const fexcept_t *__flagp, int __excepts)
{
fexcept_t __fpsr;
@@ -148,7 +180,7 @@ fesetexceptflag(const fexcept_t *__flagp, int __excepts)
}
__fenv_static inline int
-feraiseexcept(int __excepts)
+__feraiseexcept_int(int __excepts)
{
fexcept_t __ex = __excepts;
@@ -157,7 +189,7 @@ feraiseexcept(int __excepts)
}
__fenv_static inline int
-fetestexcept(int __excepts)
+__fetestexcept_int(int __excepts)
{
fexcept_t __fpsr;
@@ -166,7 +198,7 @@ fetestexcept(int __excepts)
}
__fenv_static inline int
-fegetround(void)
+__fegetround_int(void)
{
fenv_t __fpsr;
@@ -175,7 +207,7 @@ fegetround(void)
}
__fenv_static inline int
-fesetround(int __round)
+__fesetround_int(int __round)
{
fenv_t __fpsr;
@@ -187,7 +219,7 @@ fesetround(int __round)
}
__fenv_static inline int
-fegetenv(fenv_t *__envp)
+__fegetenv_int(fenv_t *__envp)
{
vmrs_fpscr(*__envp);
@@ -195,7 +227,7 @@ fegetenv(fenv_t *__envp)
}
__fenv_static inline int
-feholdexcept(fenv_t *__envp)
+__feholdexcept_int(fenv_t *__envp)
{
fenv_t __env;
@@ -207,7 +239,7 @@ feholdexcept(fenv_t *__envp)
}
__fenv_static inline int
-fesetenv(const fenv_t *__envp)
+__fesetenv_int(const fenv_t *__envp)
{
vmsr_fpscr(*__envp);
@@ -215,7 +247,7 @@ fesetenv(const fenv_t *__envp)
}
__fenv_static inline int
-feupdateenv(const fenv_t *__envp)
+__feupdateenv_int(const fenv_t *__envp)
{
fexcept_t __fpsr;
@@ -230,7 +262,7 @@ feupdateenv(const fenv_t *__envp)
/* We currently provide no external definitions of the functions below. */
__fenv_static inline int
-feenableexcept(int __mask)
+__feenableexcept_int(int __mask)
{
fenv_t __old_fpsr, __new_fpsr;
@@ -242,7 +274,7 @@ feenableexcept(int __mask)
}
__fenv_static inline int
-fedisableexcept(int __mask)
+__fedisableexcept_int(int __mask)
{
fenv_t __old_fpsr, __new_fpsr;
@@ -254,7 +286,7 @@ fedisableexcept(int __mask)
}
__fenv_static inline int
-fegetexcept(void)
+__fegetexcept_int(void)
{
fenv_t __fpsr;
diff --git a/lib/msun/i387/Makefile.inc b/lib/msun/i387/Makefile.inc
index 73feb52de6a2..f70c6b1bb569 100644
--- a/lib/msun/i387/Makefile.inc
+++ b/lib/msun/i387/Makefile.inc
@@ -17,4 +17,3 @@ ARCH_SRCS+= e_fmodl.S \
s_logbl.S s_lrintl.S s_remquol.S s_rintl.S s_scalbnl.S s_truncl.S
LDBL_PREC = 64 # XXX 64-bit format, but truncated to 53 bits
-SYM_MAPS += ${.CURDIR}/i387/Symbol.map
diff --git a/lib/msun/i387/fenv.c b/lib/msun/i387/fenv.c
index e0485a3597f6..bae8de2fb969 100644
--- a/lib/msun/i387/fenv.c
+++ b/lib/msun/i387/fenv.c
@@ -29,13 +29,8 @@
#include <sys/types.h>
#include <machine/npx.h>
-#define __fenv_static
#include "fenv.h"
-#ifdef __GNUC_GNU_INLINE__
-#error "This file must be compiled with C99 'inline' semantics"
-#endif
-
const fenv_t __fe_dfl_env = {
__INITIAL_NPXCW__,
0x0000,
@@ -94,7 +89,11 @@ int
return (__feclearexcept_int(excepts));
}
-extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
+int
+(fegetexceptflag)(fexcept_t *flagp, int excepts)
+{
+ return (__fegetexceptflag_int(flagp, excepts));
+}
int
fesetexceptflag(const fexcept_t *flagp, int excepts)
@@ -127,9 +126,23 @@ feraiseexcept(int excepts)
return (0);
}
-extern inline int fetestexcept(int __excepts);
-extern inline int fegetround(void);
-extern inline int fesetround(int __round);
+int
+(fetestexcept)(int excepts)
+{
+ return (__fetestexcept_int(excepts));
+}
+
+int
+(fegetround)(void)
+{
+ return (__fegetround_int());
+}
+
+int
+(fesetround)(int round)
+{
+ return (__fesetround_int(round));
+}
int
fegetenv(fenv_t *envp)
@@ -166,7 +179,11 @@ feholdexcept(fenv_t *envp)
return (0);
}
-extern inline int fesetenv(const fenv_t *__envp);
+int
+(fesetenv)(const fenv_t *envp)
+{
+ return (__fesetenv_int(envp));
+}
int
feupdateenv(const fenv_t *envp)
diff --git a/lib/msun/man/fmax.3 b/lib/msun/man/fmax.3
index 25fc9b6d518a..3b167a0b6f8d 100644
--- a/lib/msun/man/fmax.3
+++ b/lib/msun/man/fmax.3
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd June 29, 2004
+.Dd April 11, 2026
.Dt FMAX 3
.Os
.Sh NAME
@@ -68,10 +68,6 @@ functions return the smaller of
.Fa x
and
.Fa y .
-They treat
-.Li +0.0
-as being larger than
-.Li -0.0 .
If one argument is an \*(Na, then the other argument is returned.
If both arguments are \*(Nas, then the result is an \*(Na.
These routines do not raise any floating-point exceptions.
@@ -90,6 +86,20 @@ and
.Fn fminl
functions conform to
.St -isoC-99 .
+.Sh CAVEATS
+The library implementations of these functions treat
+.Li +0.0
+as being larger than
+.Li -0.0 .
+This behavior is not specified by the C standard, is not portable,
+and may not occur in light of compiler optimizations.
+Applications requiring specific handling of signed zeroes or
+.No \*(Na
+values are recommended to use
+.Xr fmaximum_num 3
+and
+.Xr fminimum_num 3
+instead, which have strictly defined behavior for these cases.
.Sh HISTORY
These routines first appeared in
.Fx 5.3 .
diff --git a/lib/msun/man/fmaximum.3 b/lib/msun/man/fmaximum.3
new file mode 100644
index 000000000000..ef26c12268c0
--- /dev/null
+++ b/lib/msun/man/fmaximum.3
@@ -0,0 +1,103 @@
+.\" Copyright (c) 2004 David Schultz <das@FreeBSD.org>
+.\" Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd April 4, 2026
+.Dt FMAXIMUM 3
+.Os
+.Sh NAME
+.Nm fmaximum ,
+.Nm fmaximumf ,
+.Nm fmaximuml ,
+.Nm fminimum ,
+.Nm fminimumf ,
+.Nm fminimuml
+.Nd floating-point maximum and minimum functions
+.Sh LIBRARY
+.Lb libm
+.Sh SYNOPSIS
+.In math.h
+.Ft double
+.Fn fmaximum "double x" "double y"
+.Ft float
+.Fn fmaximumf "float x" "float y"
+.Ft "long double"
+.Fn fmaximuml "long double x" "long double y"
+.Ft double
+.Fn fminimum "double x" "double y"
+.Ft float
+.Fn fminimumf "float x" "float y"
+.Ft "long double"
+.Fn fminimuml "long double x" "long double y"
+.Sh DESCRIPTION
+The
+.Fn fmaximum ,
+.Fn fmaximumf ,
+and
+.Fn fmaximuml
+functions return the larger of
+.Fa x
+and
+.Fa y ,
+and likewise, the
+.Fn fminimum ,
+.Fn fminimumf ,
+and
+.Fn fminimuml
+functions return the smaller of
+.Fa x
+and
+.Fa y .
+They treat
+.Li +0.0
+as being larger than
+.Li -0.0 .
+.Pp
+Unlike the
+.Xr fmax 3
+family of functions, which ignore an \*(Na, if either argument to
+.Fn fmaximum
+or
+.Fn fminimum
+is an \*(Na, then the result is an \*(Na.
+These routines do not raise any floating-point exceptions.
+.Sh SEE ALSO
+.Xr fmax 3 ,
+.Xr fmaximum_num 3 ,
+.Xr fmaximum_mag 3 ,
+.Xr math 3
+.Sh STANDARDS
+The
+.Fn fmaximum ,
+.Fn fmaximumf ,
+.Fn fmaximuml ,
+.Fn fminimum ,
+.Fn fminimumf ,
+and
+.Fn fminimuml
+functions conform to
+.St -isoC-2023 .
+.Sh HISTORY
+These routines first appeared in
+.Fx 16.0 .
diff --git a/lib/msun/man/fmaximum_mag.3 b/lib/msun/man/fmaximum_mag.3
new file mode 100644
index 000000000000..f5e4c39f96ef
--- /dev/null
+++ b/lib/msun/man/fmaximum_mag.3
@@ -0,0 +1,102 @@
+.\" Copyright (c) 2004 David Schultz <das@FreeBSD.org>
+.\" Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd April 3, 2026
+.Dt FMAXIMUM_MAG 3
+.Os
+.Sh NAME
+.Nm fmaximum_mag ,
+.Nm fmaximum_magf ,
+.Nm fmaximum_magl ,
+.Nm fminimum_mag ,
+.Nm fminimum_magf ,
+.Nm fminimum_magl
+.Nd floating-point maximum and minimum magnitude functions
+.Sh LIBRARY
+.Lb libm
+.Sh SYNOPSIS
+.In math.h
+.Ft double
+.Fn fmaximum_mag "double x" "double y"
+.Ft float
+.Fn fmaximum_magf "float x" "float y"
+.Ft "long double"
+.Fn fmaximum_magl "long double x" "long double y"
+.Ft double
+.Fn fminimum_mag "double x" "double y"
+.Ft float
+.Fn fminimum_magf "float x" "float y"
+.Ft "long double"
+.Fn fminimum_magl "long double x" "long double y"
+.Sh DESCRIPTION
+The
+.Fn fmaximum_mag ,
+.Fn fmaximum_magf ,
+and
+.Fn fmaximum_magl
+functions determine the larger of the absolute values of
+.Fa x
+and
+.Fa y ,
+and return the argument with the larger absolute value.
+If the absolute values are equal, the behavior is equivalent to calling the corresponding
+.Fn fmaximum
+function on the arguments.
+.Pp
+Likewise, the
+.Fn fminimum_mag ,
+.Fn fminimum_magf ,
+and
+.Fn fminimum_magl
+functions determine the smaller of the absolute values of
+.Fa x
+and
+.Fa y ,
+and return the argument with the smaller absolute value.
+If the absolute values are equal, the behavior is equivalent to calling the corresponding
+.Fn fminimum
+function on the arguments.
+.Pp
+If either argument is an \*(Na, then the result is an \*(Na.
+These routines do not raise any floating-point exceptions.
+.Sh SEE ALSO
+.Xr fmax 3 ,
+.Xr fmaximum 3 ,
+.Xr fmaximum_num 3 ,
+.Xr math 3
+.Sh STANDARDS
+The
+.Fn fmaximum_mag ,
+.Fn fmaximum_magf ,
+.Fn fmaximum_magl ,
+.Fn fminimum_mag ,
+.Fn fminimum_magf ,
+and
+.Fn fminimum_magl
+functions conform to
+.St -isoC-2023 .
+.Sh HISTORY
+These routines first appeared in
+.Fx 16.0 .
diff --git a/lib/msun/man/fmaximum_num.3 b/lib/msun/man/fmaximum_num.3
new file mode 100644
index 000000000000..33fa759f0173
--- /dev/null
+++ b/lib/msun/man/fmaximum_num.3
@@ -0,0 +1,113 @@
+.\" Copyright (c) 2004 David Schultz <das@FreeBSD.org>
+.\" Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd April 3, 2026
+.Dt FMAXIMUM_NUM 3
+.Os
+.Sh NAME
+.Nm fmaximum_num ,
+.Nm fmaximum_numf ,
+.Nm fmaximum_numl ,
+.Nm fminimum_num ,
+.Nm fminimum_numf ,
+.Nm fminimum_numl
+.Nd floating-point maximum and minimum number functions
+.Sh LIBRARY
+.Lb libm
+.Sh SYNOPSIS
+.In math.h
+.Ft double
+.Fn fmaximum_num "double x" "double y"
+.Ft float
+.Fn fmaximum_numf "float x" "float y"
+.Ft "long double"
+.Fn fmaximum_numl "long double x" "long double y"
+.Ft double
+.Fn fminimum_num "double x" "double y"
+.Ft float
+.Fn fminimum_numf "float x" "float y"
+.Ft "long double"
+.Fn fminimum_numl "long double x" "long double y"
+.Sh DESCRIPTION
+The
+.Fn fmaximum_num ,
+.Fn fmaximum_numf ,
+and
+.Fn fmaximum_numl
+functions determine the larger of
+.Fa x
+and
+.Fa y ,
+preferring a numeric value over an \*(Na.
+If one argument is a numeric value and the other is an \*(Na,
+the numeric value is returned.
+If both arguments are numeric, the larger value is returned.
+If both arguments are \*(Nas, a quiet \*(Na is returned.
+For the purpose of these functions, positive zero is considered
+greater than negative zero.
+.Pp
+Likewise, the
+.Fn fminimum_num ,
+.Fn fminimum_numf ,
+and
+.Fn fminimum_numl
+functions determine the smaller of
+.Fa x
+and
+.Fa y ,
+preferring a numeric value over an \*(Na.
+If one argument is a numeric value and the other is an \*(Na,
+the numeric value is returned.
+If both arguments are numeric, the smaller value is returned.
+If both arguments are \*(Nas, a quiet \*(Na is returned.
+For the purpose of these functions, negative zero is considered
+less than positive zero.
+.Pp
+Unlike with the
+.Xr fmaximum 3
+and
+.Xr fmaximum_mag 3
+families of functions, if either argument is a signaling \*(Na,
+an invalid exception is raised.
+Otherwise, these routines do not raise any floating-point exceptions.
+.Sh SEE ALSO
+.Xr fmax 3 ,
+.Xr fmaximum 3 ,
+.Xr fmaximum_mag 3 ,
+.Xr math 3
+.Sh STANDARDS
+The
+.Fn fmaximum_num ,
+.Fn fmaximum_numf ,
+.Fn fmaximum_numl ,
+.Fn fminimum_num ,
+.Fn fminimum_numf ,
+and
+.Fn fminimum_numl
+functions conform to
+.St -isoC-2023 .
+.Sh HISTORY
+These routines first appeared in
+.Fx 16.0 .
diff --git a/lib/msun/man/math.3 b/lib/msun/man/math.3
index 47353298bb54..f98c5e1a2a75 100644
--- a/lib/msun/man/math.3
+++ b/lib/msun/man/math.3
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 7, 2017
+.Dd April 11, 2026
.Dt MATH 3
.Os
.Sh NAME
@@ -115,8 +115,14 @@ scalbn adjust exponent
copysign copy sign bit
fabs absolute value
fdim positive difference
-fmax maximum function
-fmin minimum function
+fmax maximum function (legacy)
+fmaximum maximum function (prefers \*(Na)
+fmaximum_mag maximum magnitude (prefers \*(Na)
+fmaximum_num maximum function (avoids \*(Na)
+fmin minimum function (legacy)
+fminimum minimum function (prefers \*(Na)
+fminimum_mag minimum magnitude (prefers \*(Na)
+fminimum_num minimum function (avoids \*(Na)
signbit extract sign bit
.El
.Ss Not a Number Functions
diff --git a/lib/msun/powerpc/Makefile.inc b/lib/msun/powerpc/Makefile.inc
index 35747abb7087..2ae9bacdaab0 100644
--- a/lib/msun/powerpc/Makefile.inc
+++ b/lib/msun/powerpc/Makefile.inc
@@ -1,2 +1 @@
LDBL_PREC = 53
-SYM_MAPS += ${.CURDIR}/powerpc/Symbol.map
diff --git a/lib/msun/powerpc/fenv.c b/lib/msun/powerpc/fenv.c
index bcf78d5c096e..3104b59d4dfb 100644
--- a/lib/msun/powerpc/fenv.c
+++ b/lib/msun/powerpc/fenv.c
@@ -26,13 +26,8 @@
* SUCH DAMAGE.
*/
-#define __fenv_static
#include "fenv.h"
-#ifdef __GNUC_GNU_INLINE__
-#error "This file must be compiled with C99 'inline' semantics"
-#endif
-
const fenv_t __fe_dfl_env = 0x00000000;
int
@@ -41,15 +36,74 @@ int
return (__feclearexcept_int(excepts));
}
-extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
-extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
-extern inline int feraiseexcept(int __excepts);
-extern inline int fetestexcept(int __excepts);
-extern inline int fegetround(void);
-extern inline int fesetround(int __round);
-extern inline int fegetenv(fenv_t *__envp);
-extern inline int feholdexcept(fenv_t *__envp);
-extern inline int fesetenv(const fenv_t *__envp);
-extern inline int feupdateenv(const fenv_t *__envp);
-extern inline int feenableexcept(int __mask);
-extern inline int fedisableexcept(int __mask);
+int
+(fegetexceptflag)(fexcept_t *flagp, int excepts)
+{
+ return (__fegetexceptflag_int(flagp, excepts));
+}
+
+int
+(fesetexceptflag)(const fexcept_t *flagp, int excepts)
+{
+ return (__fesetexceptflag_int(flagp, excepts));
+}
+
+int
+(feraiseexcept)(int excepts)
+{
+ return (__feraiseexcept_int(excepts));
+}
+
+int
+(fetestexcept)(int excepts)
+{
+ return (__fetestexcept_int(excepts));
+}
+
+int
+(fegetround)(void)
+{
+ return (__fegetround_int());
+}
+
+int
+(fesetround)(int round)
+{
+ return (__fesetround_int(round));
+}
+
+int
+(fegetenv)(fenv_t *envp)
+{
+ return (__fegetenv_int(envp));
+}
+
+int
+(feholdexcept)(fenv_t *envp)
+{
+ return (__feholdexcept_int(envp));
+}
+
+int
+(fesetenv)(const fenv_t *envp)
+{
+ return (__fesetenv_int(envp));
+}
+
+int
+(feupdateenv)(const fenv_t *envp)
+{
+ return (__feupdateenv_int(envp));
+}
+
+int
+(feenableexcept)(int mask)
+{
+ return (__feenableexcept_int(mask));
+}
+
+int
+(fedisableexcept)(int mask)
+{
+ return (__fedisableexcept_int(mask));
+}
diff --git a/lib/msun/powerpc/fenv.h b/lib/msun/powerpc/fenv.h
index 74a71ef39e5a..f6fb354470c7 100644
--- a/lib/msun/powerpc/fenv.h
+++ b/lib/msun/powerpc/fenv.h
@@ -112,7 +112,28 @@ union __fpscr {
};
int feclearexcept(int);
+int fegetexceptflag(fexcept_t *, int);
+int fesetexceptflag(const fexcept_t *, int);
+int feraiseexcept(int);
+int fetestexcept(int);
+int fegetround(void);
+int fesetround(int);
+int fegetenv(fenv_t *);
+int feholdexcept(fenv_t *);
+int fesetenv(const fenv_t *);
+int feupdateenv(const fenv_t *);
+
#define feclearexcept(a) __feclearexcept_int(a)
+#define fegetexceptflag(e, a) __fegetexceptflag_int(e, a)
+#define fesetexceptflag(e, a) __fesetexceptflag_int(e, a)
+#define feraiseexcept(a) __feraiseexcept_int(a)
+#define fetestexcept(a) __fetestexcept_int(a)
+#define fegetround() __fegetround_int()
+#define fesetround(a) __fesetround_int(a)
+#define fegetenv(e) __fegetenv_int(e)
+#define feholdexcept(e) __feholdexcept_int(e)
+#define fesetenv(e) __fesetenv_int(e)
+#define feupdateenv(e) __feupdateenv_int(e)
__fenv_static inline int
__feclearexcept_int(int __excepts)
@@ -128,7 +149,7 @@ __feclearexcept_int(int __excepts)
}
__fenv_static inline int
-fegetexceptflag(fexcept_t *__flagp, int __excepts)
+__fegetexceptflag_int(fexcept_t *__flagp, int __excepts)
{
union __fpscr __r;
@@ -138,7 +159,7 @@ fegetexceptflag(fexcept_t *__flagp, int __excepts)
}
__fenv_static inline int
-fesetexceptflag(const fexcept_t *__flagp, int __excepts)
+__fesetexceptflag_int(const fexcept_t *__flagp, int __excepts)
{
union __fpscr __r;
@@ -152,7 +173,7 @@ fesetexceptflag(const fexcept_t *__flagp, int __excepts)
}
__fenv_static inline int
-feraiseexcept(int __excepts)
+__feraiseexcept_int(int __excepts)
{
union __fpscr __r;
@@ -165,7 +186,7 @@ feraiseexcept(int __excepts)
}
__fenv_static inline int
-fetestexcept(int __excepts)
+__fetestexcept_int(int __excepts)
{
union __fpscr __r;
@@ -174,7 +195,7 @@ fetestexcept(int __excepts)
}
__fenv_static inline int
-fegetround(void)
+__fegetround_int(void)
{
union __fpscr __r;
@@ -183,7 +204,7 @@ fegetround(void)
}
__fenv_static inline int
-fesetround(int __round)
+__fesetround_int(int __round)
{
union __fpscr __r;
@@ -197,7 +218,7 @@ fesetround(int __round)
}
__fenv_static inline int
-fegetenv(fenv_t *__envp)
+__fegetenv_int(fenv_t *__envp)
{
union __fpscr __r;
@@ -207,7 +228,7 @@ fegetenv(fenv_t *__envp)
}
__fenv_static inline int
-feholdexcept(fenv_t *__envp)
+__feholdexcept_int(fenv_t *__envp)
{
union __fpscr __r;
@@ -219,7 +240,7 @@ feholdexcept(fenv_t *__envp)
}
__fenv_static inline int
-fesetenv(const fenv_t *__envp)
+__fesetenv_int(const fenv_t *__envp)
{
union __fpscr __r;
@@ -229,7 +250,7 @@ fesetenv(const fenv_t *__envp)
}
__fenv_static inline int
-feupdateenv(const fenv_t *__envp)
+__feupdateenv_int(const fenv_t *__envp)
{
union __fpscr __r;
@@ -242,8 +263,14 @@ feupdateenv(const fenv_t *__envp)
#if __BSD_VISIBLE
+int feenableexcept(int);
+int fedisableexcept(int);
+
+#define feenableexcept(a) __feenableexcept_int(a)
+#define fedisableexcept(a) __fedisableexcept_int(a)
+
__fenv_static inline int
-feenableexcept(int __mask)
+__feenableexcept_int(int __mask)
{
union __fpscr __r;
fenv_t __oldmask;
@@ -256,7 +283,7 @@ feenableexcept(int __mask)
}
__fenv_static inline int
-fedisableexcept(int __mask)
+__fedisableexcept_int(int __mask)
{
union __fpscr __r;
fenv_t __oldmask;
diff --git a/lib/msun/riscv/Makefile.inc b/lib/msun/riscv/Makefile.inc
index 6262cfd6981e..ee32db47286d 100644
--- a/lib/msun/riscv/Makefile.inc
+++ b/lib/msun/riscv/Makefile.inc
@@ -1,2 +1 @@
LDBL_PREC = 113
-SYM_MAPS += ${.CURDIR}/riscv/Symbol.map
diff --git a/lib/msun/riscv/fenv.c b/lib/msun/riscv/fenv.c
index 4d1b2cb2f611..7fdedca1f09c 100644
--- a/lib/msun/riscv/fenv.c
+++ b/lib/msun/riscv/fenv.c
@@ -24,13 +24,8 @@
* SUCH DAMAGE.
*/
-#define __fenv_static
#include "fenv.h"
-#ifdef __GNUC_GNU_INLINE__
-#error "This file must be compiled with C99 'inline' semantics"
-#endif
-
/*
* Hopefully the system ID byte is immutable, so it's valid to use
* this as a default environment.
@@ -43,16 +38,74 @@ int
return (__feclearexcept_int(excepts));
}
-extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
-extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
-extern inline int feraiseexcept(int __excepts);
-extern inline int fetestexcept(int __excepts);
-extern inline int fegetround(void);
-extern inline int fesetround(int __round);
-extern inline int fegetenv(fenv_t *__envp);
-extern inline int feholdexcept(fenv_t *__envp);
-extern inline int fesetenv(const fenv_t *__envp);
-extern inline int feupdateenv(const fenv_t *__envp);
-extern inline int feenableexcept(int __mask);
-extern inline int fedisableexcept(int __mask);
-extern inline int fegetexcept(void);
+int
+(fegetexceptflag)(fexcept_t *flagp, int excepts)
+{
+ return (__fegetexceptflag_int(flagp, excepts));
+}
+
+int
+(fesetexceptflag)(const fexcept_t *flagp, int excepts)
+{
+ return (__fesetexceptflag_int(flagp, excepts));
+}
+
+int
+(feraiseexcept)(int excepts)
+{
+ return (__feraiseexcept_int(excepts));
+}
+
+int
+(fetestexcept)(int excepts)
+{
+ return (__fetestexcept_int(excepts));
+}
+
+int
+(fegetround)(void)
+{
+ return (__fegetround_int());
+}
+
+int
+(fesetround)(int round)
+{
+ return (__fesetround_int(round));
+}
+
+int
+(fegetenv)(fenv_t *envp)
+{
+ return (__fegetenv_int(envp));
+}
+
+int
+(feholdexcept)(fenv_t *envp)
+{
+ return (__feholdexcept_int(envp));
+}
+
+int
+(fesetenv)(const fenv_t *envp)
+{
+ return (__fesetenv_int(envp));
+}
+
+int
+(feupdateenv)(const fenv_t *envp)
+{
+ return (__feupdateenv_int(envp));
+}
+
+int
+(feenableexcept)(int mask)
+{
+ return (__feenableexcept_int(mask));
+}
+
+int
+(fedisableexcept)(int mask)
+{
+ return (__fedisableexcept_int(mask));
+}
diff --git a/lib/msun/riscv/fenv.h b/lib/msun/riscv/fenv.h
index 4e8f81aa04c1..1059744941f3 100644
--- a/lib/msun/riscv/fenv.h
+++ b/lib/msun/riscv/fenv.h
@@ -80,7 +80,28 @@ extern const fenv_t __fe_dfl_env;
#define __wfs(__fcsr) __asm __volatile("csrw fcsr, %0" :: "r" (__fcsr))
int feclearexcept(int);
+int fegetexceptflag(fexcept_t *, int);
+int fesetexceptflag(const fexcept_t *, int);
+int feraiseexcept(int);
+int fetestexcept(int);
+int fegetround(void);
+int fesetround(int);
+int fegetenv(fenv_t *);
+int feholdexcept(fenv_t *);
+int fesetenv(const fenv_t *);
+int feupdateenv(const fenv_t *);
+
#define feclearexcept(a) __feclearexcept_int(a)
+#define fegetexceptflag(e, a) __fegetexceptflag_int(e, a)
+#define fesetexceptflag(e, a) __fesetexceptflag_int(e, a)
+#define feraiseexcept(a) __feraiseexcept_int(a)
+#define fetestexcept(a) __fetestexcept_int(a)
+#define fegetround() __fegetround_int()
+#define fesetround(a) __fesetround_int(a)
+#define fegetenv(e) __fegetenv_int(e)
+#define feholdexcept(e) __feholdexcept_int(e)
+#define fesetenv(e) __fesetenv_int(e)
+#define feupdateenv(e) __feupdateenv_int(e)
__fenv_static inline int
__feclearexcept_int(int __excepts)
@@ -92,7 +113,7 @@ __feclearexcept_int(int __excepts)
}
__fenv_static inline int
-fegetexceptflag(fexcept_t *__flagp, int __excepts)
+__fegetexceptflag_int(fexcept_t *__flagp, int __excepts)
{
fexcept_t __fcsr;
@@ -103,7 +124,7 @@ fegetexceptflag(fexcept_t *__flagp, int __excepts)
}
__fenv_static inline int
-fesetexceptflag(const fexcept_t *__flagp, int __excepts)
+__fesetexceptflag_int(const fexcept_t *__flagp, int __excepts)
{
fexcept_t __fcsr;
@@ -115,7 +136,7 @@ fesetexceptflag(const fexcept_t *__flagp, int __excepts)
}
__fenv_static inline int
-feraiseexcept(int __excepts)
+__feraiseexcept_int(int __excepts)
{
__asm __volatile("csrs fflags, %0" :: "r"(__excepts));
@@ -124,7 +145,7 @@ feraiseexcept(int __excepts)
}
__fenv_static inline int
-fetestexcept(int __excepts)
+__fetestexcept_int(int __excepts)
{
fexcept_t __fcsr;
@@ -134,7 +155,7 @@ fetestexcept(int __excepts)
}
__fenv_static inline int
-fegetround(void)
+__fegetround_int(void)
{
fexcept_t __fcsr;
@@ -144,7 +165,7 @@ fegetround(void)
}
__fenv_static inline int
-fesetround(int __round)
+__fesetround_int(int __round)
{
fexcept_t __fcsr;
@@ -160,7 +181,7 @@ fesetround(int __round)
}
__fenv_static inline int
-fegetenv(fenv_t *__envp)
+__fegetenv_int(fenv_t *__envp)
{
__rfs(*__envp);
@@ -169,7 +190,7 @@ fegetenv(fenv_t *__envp)
}
__fenv_static inline int
-feholdexcept(fenv_t *__envp __unused)
+__feholdexcept_int(fenv_t *__envp __unused)
{
/* No exception traps. */
@@ -178,7 +199,7 @@ feholdexcept(fenv_t *__envp __unused)
}
__fenv_static inline int
-fesetenv(const fenv_t *__envp)
+__fesetenv_int(const fenv_t *__envp)
{
__wfs(*__envp);
@@ -187,7 +208,7 @@ fesetenv(const fenv_t *__envp)
}
__fenv_static inline int
-feupdateenv(const fenv_t *__envp)
+__feupdateenv_int(const fenv_t *__envp)
{
fexcept_t __fcsr;
@@ -200,8 +221,14 @@ feupdateenv(const fenv_t *__envp)
#if __BSD_VISIBLE
+int feenableexcept(int);
+int fedisableexcept(int);
+
+#define feenableexcept(a) __feenableexcept_int(a)
+#define fedisableexcept(a) __fedisableexcept_int(a)
+
__fenv_static inline int
-feenableexcept(int __mask __unused)
+__feenableexcept_int(int __mask __unused)
{
/* No exception traps. */
@@ -210,7 +237,7 @@ feenableexcept(int __mask __unused)
}
__fenv_static inline int
-fedisableexcept(int __mask __unused)
+__fedisableexcept_int(int __mask __unused)
{
/* No exception traps. */
diff --git a/lib/msun/src/math.h b/lib/msun/src/math.h
index 25bd64e36a63..853984953a91 100644
--- a/lib/msun/src/math.h
+++ b/lib/msun/src/math.h
@@ -520,6 +520,24 @@ long double sinpil(long double);
double tanpi(double);
float tanpif(float);
long double tanpil(long double);
+double fmaximum(double, double);
+float fmaximumf(float, float);
+long double fmaximuml(long double, long double);
+double fminimum(double, double);
+float fminimumf(float, float);
+long double fminimuml(long double, long double);
+double fmaximum_mag(double, double);
+float fmaximum_magf(float, float);
+long double fmaximum_magl(long double, long double);
+double fminimum_mag(double, double);
+float fminimum_magf(float, float);
+long double fminimum_magl(long double, long double);
+double fmaximum_num(double, double);
+float fmaximum_numf(float, float);
+long double fmaximum_numl(long double, long double);
+double fminimum_num(double, double);
+float fminimum_numf(float, float);
+long double fminimum_numl(long double, long double);
#endif /* __ISO_C_VISIBLE >= 2023 */
__END_DECLS
diff --git a/lib/msun/src/s_fmaximum.c b/lib/msun/src/s_fmaximum.c
new file mode 100644
index 000000000000..f9e1998a84c2
--- /dev/null
+++ b/lib/msun/src/s_fmaximum.c
@@ -0,0 +1,65 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <float.h>
+#include <math.h>
+
+#include "fpmath.h"
+
+#ifdef USE_BUILTIN_FMAXIMUM
+double
+fmaximum(double x, double y)
+{
+ return (__builtin_fmaximum(x, y));
+}
+#else
+double
+fmaximum(double x, double y)
+{
+ union IEEEd2bits u[2];
+
+ u[0].d = x;
+ u[1].d = y;
+
+ /* Handle NaN according to ISO/IEC 60559. NaN argument -> NaN return */
+ if ((u[0].bits.exp == 2047 && (u[0].bits.manh | u[0].bits.manl) != 0) ||
+ (u[1].bits.exp == 2047 && (u[1].bits.manh | u[1].bits.manl) != 0))
+ return (NAN);
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[u[0].bits.sign].d);
+
+ return (x > y ? x : y);
+}
+#endif
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(fmaximum, fmaximuml);
+#endif
diff --git a/lib/msun/src/s_fmaximum_mag.c b/lib/msun/src/s_fmaximum_mag.c
new file mode 100644
index 000000000000..1b1250f4c36e
--- /dev/null
+++ b/lib/msun/src/s_fmaximum_mag.c
@@ -0,0 +1,73 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <float.h>
+#include <math.h>
+
+#include "fpmath.h"
+
+#ifdef USE_BUILTIN_FMAXIMUM_MAG
+double
+fmaximum_mag(double x, double y)
+{
+ return (__builtin_fmaximum_mag(x, y));
+}
+#else
+double
+fmaximum_mag(double x, double y)
+{
+ union IEEEd2bits u[2];
+
+ u[0].d = x;
+ u[1].d = y;
+
+ /* Handle NaN according to ISO/IEC 60559. NaN argument -> NaN return */
+ if ((u[0].bits.exp == 2047 && (u[0].bits.manh | u[0].bits.manl) != 0) ||
+ (u[1].bits.exp == 2047 && (u[1].bits.manh | u[1].bits.manl) != 0))
+ return (NAN);
+
+ double ax = fabs(x);
+ double ay = fabs(y);
+
+ if (ay > ax)
+ return (y);
+ if (ax > ay)
+ return (x);
+
+ /* If magnitudes are equal, we break the tie with the sign */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[u[0].bits.sign].d);
+
+ return (x);
+}
+#endif
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(fmaximum_mag, fmaximum_magl);
+#endif
+
diff --git a/lib/msun/src/s_fmaximum_magf.c b/lib/msun/src/s_fmaximum_magf.c
new file mode 100644
index 000000000000..6193b9184970
--- /dev/null
+++ b/lib/msun/src/s_fmaximum_magf.c
@@ -0,0 +1,68 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <math.h>
+
+#include "fpmath.h"
+
+#ifdef USE_BUILTIN_FMAXIMUM_MAGF
+float
+fmaximum_magf(float x, float y)
+{
+ return (__builtin_fmaximum_magf(x, y));
+}
+#else
+float
+fmaximum_magf(float x, float y)
+{
+ union IEEEf2bits u[2];
+
+ u[0].f = x;
+ u[1].f = y;
+
+ /* Handle NaN according to ISO/IEC 60559. NaN argument -> NaN return */
+ if ((u[0].bits.exp == 255 && u[0].bits.man != 0) ||
+ (u[1].bits.exp == 255 && u[1].bits.man != 0))
+ return (NAN);
+
+ float ax = fabsf(x);
+ float ay = fabsf(y);
+
+ if (ay > ax)
+ return (y);
+ if (ax > ay)
+ return (x);
+
+ /* If magnitudes are equal, we break the tie with the sign */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[u[0].bits.sign].f);
+
+ return (x);
+}
+#endif
+
diff --git a/lib/msun/src/s_fmaximum_magl.c b/lib/msun/src/s_fmaximum_magl.c
new file mode 100644
index 000000000000..f2426b050d33
--- /dev/null
+++ b/lib/msun/src/s_fmaximum_magl.c
@@ -0,0 +1,62 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <math.h>
+
+#include "fpmath.h"
+
+long double
+fmaximum_magl(long double x, long double y)
+{
+ union IEEEl2bits u[2];
+
+ u[0].e = x;
+ mask_nbit_l(u[0]);
+ u[1].e = y;
+ mask_nbit_l(u[1]);
+
+ /* Handle NaN according to ISO/IEC 60559. NaN argument -> NaN return */
+ if ((u[0].bits.exp == 32767 && (u[0].bits.manh | u[0].bits.manl) != 0) ||
+ (u[1].bits.exp == 32767 && (u[1].bits.manh | u[1].bits.manl) != 0))
+ return (NAN);
+
+ long double ax = fabsl(x);
+ long double ay = fabsl(y);
+
+ if (ay > ax)
+ return (y);
+ if (ax > ay)
+ return (x);
+
+ /* If magnitudes are equal, we break the tie with the sign */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[0].bits.sign ? y : x);
+
+ return (x);
+}
+
diff --git a/lib/msun/src/s_fmaximum_num.c b/lib/msun/src/s_fmaximum_num.c
new file mode 100644
index 000000000000..cf16c76f89b9
--- /dev/null
+++ b/lib/msun/src/s_fmaximum_num.c
@@ -0,0 +1,74 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <float.h>
+#include <math.h>
+#include <stdbool.h>
+
+#include "fpmath.h"
+
+#ifdef USE_BUILTIN_FMAXIMUM_NUM
+double
+fmaximum_num(double x, double y)
+{
+ return (__builtin_fmaximum_num(x, y));
+}
+#else
+double
+fmaximum_num(double x, double y)
+{
+ union IEEEd2bits u[2];
+ bool nan_x, nan_y;
+
+ u[0].d = x;
+ u[1].d = y;
+
+ nan_x = u[0].bits.exp == 2047 && (u[0].bits.manh | u[0].bits.manl) != 0;
+ nan_y = u[1].bits.exp == 2047 && (u[1].bits.manh | u[1].bits.manl) != 0;
+
+ if (nan_x || nan_y) {
+ /* These ternary conditionals force (x+y), so that sNaN's raise exceptions */
+ if (nan_x && nan_y)
+ return (x + y);
+ if (nan_x)
+ return ((x + y) != 0.0 ? y : y);
+ return ((x + y) != 0.0 ? x : x);
+ }
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[u[0].bits.sign].d);
+
+ return (x > y ? x : y);
+}
+#endif
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(fmaximum_num, fmaximum_numl);
+#endif
diff --git a/lib/msun/src/s_fmaximum_numf.c b/lib/msun/src/s_fmaximum_numf.c
new file mode 100644
index 000000000000..c30179e47f9e
--- /dev/null
+++ b/lib/msun/src/s_fmaximum_numf.c
@@ -0,0 +1,70 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <math.h>
+#include <stdbool.h>
+
+#include "fpmath.h"
+
+#ifdef USE_BUILTIN_FMAXIMUM_NUMF
+float
+fmaximum_numf(float x, float y)
+{
+ return (__builtin_fmaximum_numf(x, y));
+}
+#else
+float
+fmaximum_numf(float x, float y)
+{
+ union IEEEf2bits u[2];
+ bool nan_x, nan_y;
+
+ u[0].f = x;
+ u[1].f = y;
+
+ nan_x = u[0].bits.exp == 255 && u[0].bits.man != 0;
+ nan_y = u[1].bits.exp == 255 && u[1].bits.man != 0;
+
+ if (nan_x || nan_y) {
+ /* These ternary conditionals force (x+y), so that sNaN's raise exceptions */
+ if (nan_x && nan_y)
+ return (x + y);
+ if (nan_x)
+ return ((x + y) != 0.0 ? y : y);
+ return ((x + y) != 0.0 ? x : x);
+ }
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[u[0].bits.sign].f);
+
+ return (x > y ? x : y);
+}
+#endif
+
diff --git a/lib/msun/src/s_fmaximum_numl.c b/lib/msun/src/s_fmaximum_numl.c
new file mode 100644
index 000000000000..2291d01ca4f4
--- /dev/null
+++ b/lib/msun/src/s_fmaximum_numl.c
@@ -0,0 +1,63 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <math.h>
+#include <stdbool.h>
+
+#include "fpmath.h"
+
+long double
+fmaximum_numl(long double x, long double y)
+{
+ union IEEEl2bits u[2];
+ bool nan_x, nan_y;
+
+ u[0].e = x;
+ mask_nbit_l(u[0]);
+ u[1].e = y;
+ mask_nbit_l(u[1]);
+
+ nan_x = u[0].bits.exp == 32767 && (u[0].bits.manh | u[0].bits.manl) != 0;
+ nan_y = u[1].bits.exp == 32767 && (u[1].bits.manh | u[1].bits.manl) != 0;
+
+ if (nan_x || nan_y) {
+ /* These ternary conditionals force (x+y), so that sNaN's raise exceptions */
+ if (nan_x && nan_y)
+ return (x + y);
+ if (nan_x)
+ return ((x + y) != 0.0 ? y : y);
+ return ((x + y) != 0.0 ? x : x);
+ }
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[0].bits.sign ? y : x);
+
+ return (x > y ? x : y);
+}
diff --git a/lib/msun/src/s_fmaximumf.c b/lib/msun/src/s_fmaximumf.c
new file mode 100644
index 000000000000..db4b96c14749
--- /dev/null
+++ b/lib/msun/src/s_fmaximumf.c
@@ -0,0 +1,60 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <math.h>
+
+#include "fpmath.h"
+
+#ifdef USE_BUILTIN_FMAXIMUMF
+float
+fmaximumf(float x, float y)
+{
+ return (__builtin_fmaximumf(x, y));
+}
+#else
+float
+fmaximumf(float x, float y)
+{
+ union IEEEf2bits u[2];
+
+ u[0].f = x;
+ u[1].f = y;
+
+ /* Handle NaN according to ISO/IEC 60559. NaN argument -> NaN return */
+ if ((u[0].bits.exp == 255 && u[0].bits.man != 0) ||
+ (u[1].bits.exp == 255 && u[1].bits.man != 0))
+ return (NAN);
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[u[0].bits.sign].f);
+
+ return (x > y ? x : y);
+}
+#endif
diff --git a/lib/msun/src/s_fmaximuml.c b/lib/msun/src/s_fmaximuml.c
new file mode 100644
index 000000000000..c849478cf05a
--- /dev/null
+++ b/lib/msun/src/s_fmaximuml.c
@@ -0,0 +1,54 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <math.h>
+
+#include "fpmath.h"
+
+long double
+fmaximuml(long double x, long double y)
+{
+ union IEEEl2bits u[2];
+
+ u[0].e = x;
+ mask_nbit_l(u[0]);
+ u[1].e = y;
+ mask_nbit_l(u[1]);
+
+ /* Handle NaN according to ISO/IEC 60559. NaN argument -> NaN return */
+ if ((u[0].bits.exp == 32767 && (u[0].bits.manh | u[0].bits.manl) != 0) ||
+ (u[1].bits.exp == 32767 && (u[1].bits.manh | u[1].bits.manl) != 0))
+ return (NAN);
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[0].bits.sign ? y : x);
+
+ return (x > y ? x : y);
+}
diff --git a/lib/msun/src/s_fminimum.c b/lib/msun/src/s_fminimum.c
new file mode 100644
index 000000000000..fa3fd17fe241
--- /dev/null
+++ b/lib/msun/src/s_fminimum.c
@@ -0,0 +1,66 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <float.h>
+#include <math.h>
+
+#include "fpmath.h"
+
+#ifdef USE_BUILTIN_FMINIMUM
+double
+fminimum(double x, double y)
+{
+ return (__builtin_fminimum(x, y));
+}
+#else
+double
+fminimum(double x, double y)
+{
+ union IEEEd2bits u[2];
+
+ u[0].d = x;
+ u[1].d = y;
+
+ /* Handle NaN according to ISO/IEC 60559. NaN argument -> NaN return */
+ if (u[0].bits.exp == 2047 && (u[0].bits.manh | u[0].bits.manl) != 0 ||
+ u[1].bits.exp == 2047 && (u[1].bits.manh | u[1].bits.manl) != 0)
+ return (NAN);
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[u[1].bits.sign].d);
+
+ return (x < y ? x : y);
+}
+#endif
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(fminimum, fminimuml);
+#endif
+
diff --git a/lib/msun/src/s_fminimum_mag.c b/lib/msun/src/s_fminimum_mag.c
new file mode 100644
index 000000000000..cd21fb948a8e
--- /dev/null
+++ b/lib/msun/src/s_fminimum_mag.c
@@ -0,0 +1,74 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <float.h>
+#include <math.h>
+
+#include "fpmath.h"
+
+#ifdef USE_BUILTIN_FMINIMUM_MAG
+double
+fminimum_mag(double x, double y)
+{
+ return (__builtin_fminimum_mag(x, y));
+}
+#else
+double
+fminimum_mag(double x, double y)
+{
+ union IEEEd2bits u[2];
+
+ u[0].d = x;
+ u[1].d = y;
+
+ /* Handle NaN according to ISO/IEC 60559. NaN argument -> NaN return */
+ if (u[0].bits.exp == 2047 && (u[0].bits.manh | u[0].bits.manl) != 0 ||
+ u[1].bits.exp == 2047 && (u[1].bits.manh | u[1].bits.manl) != 0)
+ return (NAN);
+
+ double ax = fabs(x);
+ double ay = fabs(y);
+
+ if (ay < ax)
+ return (y);
+ if (ax < ay)
+ return (x);
+
+ /* If magnitudes are equal, we break the tie with the sign */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[u[1].bits.sign].d);
+
+ return (x);
+}
+#endif
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(fminimum_mag, fminimum_magl);
+#endif
+
+
diff --git a/lib/msun/src/s_fminimum_magf.c b/lib/msun/src/s_fminimum_magf.c
new file mode 100644
index 000000000000..9c04859184ea
--- /dev/null
+++ b/lib/msun/src/s_fminimum_magf.c
@@ -0,0 +1,69 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <math.h>
+
+#include "fpmath.h"
+
+#ifdef USE_BUILTIN_FMINIMUM_MAGF
+float
+fminimum_magf(float x, float y)
+{
+ return (__builtin_fminimum_magf(x, y));
+}
+#else
+float
+fminimum_magf(float x, float y)
+{
+ union IEEEf2bits u[2];
+
+ u[0].f = x;
+ u[1].f = y;
+
+ /* Handle NaN according to ISO/IEC 60559. NaN argument -> NaN return */
+ if (u[0].bits.exp == 255 && u[0].bits.man != 0 ||
+ u[1].bits.exp == 255 && u[1].bits.man != 0)
+ return (NAN);
+
+ float ax = fabsf(x);
+ float ay = fabsf(y);
+
+ if (ay < ax)
+ return (y);
+ if (ax < ay)
+ return (x);
+
+ /* If magnitudes are equal, we break the tie with the sign */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[u[1].bits.sign].f);
+
+ return (x);
+}
+#endif
+
+
diff --git a/lib/msun/src/s_fminimum_magl.c b/lib/msun/src/s_fminimum_magl.c
new file mode 100644
index 000000000000..e6ab22afe7f0
--- /dev/null
+++ b/lib/msun/src/s_fminimum_magl.c
@@ -0,0 +1,63 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <math.h>
+
+#include "fpmath.h"
+
+long double
+fminimum_magl(long double x, long double y)
+{
+ union IEEEl2bits u[2];
+
+ u[0].e = x;
+ mask_nbit_l(u[0]);
+ u[1].e = y;
+ mask_nbit_l(u[1]);
+
+ /* Handle NaN according to ISO/IEC 60559. NaN argument -> NaN return */
+ if (u[0].bits.exp == 32767 && (u[0].bits.manh | u[0].bits.manl) != 0 ||
+ u[1].bits.exp == 32767 && (u[1].bits.manh | u[1].bits.manl) != 0)
+ return (NAN);
+
+ long double ax = fabsl(x);
+ long double ay = fabsl(y);
+
+ if (ay < ax)
+ return (y);
+ if (ax < ay)
+ return (x);
+
+ /* If magnitudes are equal, we break the tie with the sign */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[1].bits.sign ? y : x);
+
+ return (x);
+}
+
+
diff --git a/lib/msun/src/s_fminimum_num.c b/lib/msun/src/s_fminimum_num.c
new file mode 100644
index 000000000000..71b5f072c32d
--- /dev/null
+++ b/lib/msun/src/s_fminimum_num.c
@@ -0,0 +1,76 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <float.h>
+#include <math.h>
+#include <stdbool.h>
+
+#include "fpmath.h"
+
+#ifdef USE_BUILTIN_FMINIMUM_NUM
+double
+fminimum_num(double x, double y)
+{
+ return (__builtin_fminimum_num(x, y));
+}
+#else
+double
+fminimum_num(double x, double y)
+{
+ union IEEEd2bits u[2];
+ bool nan_x, nan_y;
+
+ u[0].d = x;
+ u[1].d = y;
+
+ nan_x = u[0].bits.exp == 2047 && (u[0].bits.manh | u[0].bits.manl) != 0;
+ nan_y = u[1].bits.exp == 2047 && (u[1].bits.manh | u[1].bits.manl) != 0;
+
+ if (nan_x || nan_y) {
+ /* These ternary conditionals force (x+y), so that sNaN's raise exceptions */
+ if (nan_x && nan_y)
+ return (x + y);
+ if (nan_x)
+ return ((x + y) != 0.0 ? y : y);
+ return ((x + y) != 0.0 ? x : x);
+ }
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[u[1].bits.sign].d);
+
+ return (x < y ? x : y);
+}
+#endif
+
+#if (LDBL_MANT_DIG == 53)
+__weak_reference(fminimum_num, fminimum_numl);
+#endif
+
+
diff --git a/lib/msun/src/s_fminimum_numf.c b/lib/msun/src/s_fminimum_numf.c
new file mode 100644
index 000000000000..d5bab31ce403
--- /dev/null
+++ b/lib/msun/src/s_fminimum_numf.c
@@ -0,0 +1,71 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <math.h>
+#include <stdbool.h>
+
+#include "fpmath.h"
+
+#ifdef USE_BUILTIN_FMINIMUM_NUMF
+float
+fminimum_numf(float x, float y)
+{
+ return (__builtin_fminimum_numf(x, y));
+}
+#else
+float
+fminimum_numf(float x, float y)
+{
+ union IEEEf2bits u[2];
+ bool nan_x, nan_y;
+
+ u[0].f = x;
+ u[1].f = y;
+
+ nan_x = u[0].bits.exp == 255 && u[0].bits.man != 0;
+ nan_y = u[1].bits.exp == 255 && u[1].bits.man != 0;
+
+ if (nan_x || nan_y) {
+ /* These ternary conditionals force (x+y), so that sNaN's raise exceptions */
+ if (nan_x && nan_y)
+ return (x + y);
+ if (nan_x)
+ return ((x + y) != 0.0 ? y : y);
+ return ((x + y) != 0.0 ? x : x);
+ }
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[u[1].bits.sign].f);
+
+ return (x < y ? x : y);
+}
+#endif
+
+
diff --git a/lib/msun/src/s_fminimum_numl.c b/lib/msun/src/s_fminimum_numl.c
new file mode 100644
index 000000000000..6b26d2218d42
--- /dev/null
+++ b/lib/msun/src/s_fminimum_numl.c
@@ -0,0 +1,65 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <math.h>
+#include <stdbool.h>
+
+#include "fpmath.h"
+
+long double
+fminimum_numl(long double x, long double y)
+{
+ union IEEEl2bits u[2];
+ bool nan_x, nan_y;
+
+ u[0].e = x;
+ mask_nbit_l(u[0]);
+ u[1].e = y;
+ mask_nbit_l(u[1]);
+
+ nan_x = u[0].bits.exp == 32767 && (u[0].bits.manh | u[0].bits.manl) != 0;
+ nan_y = u[1].bits.exp == 32767 && (u[1].bits.manh | u[1].bits.manl) != 0;
+
+ if (nan_x || nan_y) {
+ /* These ternary conditionals force (x+y), so that sNaN's raise exceptions */
+ if (nan_x && nan_y)
+ return (x + y);
+ if (nan_x)
+ return ((x + y) != 0.0 ? y : y);
+ return ((x + y) != 0.0 ? x : x);
+ }
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[1].bits.sign ? y : x);
+
+ return (x < y ? x : y);
+}
+
+
diff --git a/lib/msun/src/s_fminimumf.c b/lib/msun/src/s_fminimumf.c
new file mode 100644
index 000000000000..08ac3ca4c158
--- /dev/null
+++ b/lib/msun/src/s_fminimumf.c
@@ -0,0 +1,61 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <math.h>
+
+#include "fpmath.h"
+
+#ifdef USE_BUILTIN_FMINIMUMF
+float
+fminimumf(float x, float y)
+{
+ return (__builtin_fminimumf(x, y));
+}
+#else
+float
+fminimumf(float x, float y)
+{
+ union IEEEf2bits u[2];
+
+ u[0].f = x;
+ u[1].f = y;
+
+ /* Handle NaN according to ISO/IEC 60559. NaN argument -> NaN return */
+ if (u[0].bits.exp == 255 && u[0].bits.man != 0 ||
+ u[1].bits.exp == 255 && u[1].bits.man != 0)
+ return (NAN);
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[u[1].bits.sign].f);
+
+ return (x < y ? x : y);
+}
+#endif
+
diff --git a/lib/msun/src/s_fminimuml.c b/lib/msun/src/s_fminimuml.c
new file mode 100644
index 000000000000..1ef9078ee674
--- /dev/null
+++ b/lib/msun/src/s_fminimuml.c
@@ -0,0 +1,55 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <math.h>
+
+#include "fpmath.h"
+
+long double
+fminimuml(long double x, long double y)
+{
+ union IEEEl2bits u[2];
+
+ u[0].e = x;
+ mask_nbit_l(u[0]);
+ u[1].e = y;
+ mask_nbit_l(u[1]);
+
+ /* Handle NaN according to ISO/IEC 60559. NaN argument -> NaN return */
+ if (u[0].bits.exp == 32767 && (u[0].bits.manh | u[0].bits.manl) != 0 ||
+ u[1].bits.exp == 32767 && (u[1].bits.manh | u[1].bits.manl) != 0)
+ return (NAN);
+
+ /* Handle comparisons of signed zeroes. */
+ if (u[0].bits.sign != u[1].bits.sign)
+ return (u[1].bits.sign ? y : x);
+
+ return (x < y ? x : y);
+}
+
diff --git a/lib/msun/tests/Makefile b/lib/msun/tests/Makefile
index d2a3ebffadb3..d723e0aaf656 100644
--- a/lib/msun/tests/Makefile
+++ b/lib/msun/tests/Makefile
@@ -58,6 +58,7 @@ ATF_TESTS_C+= exponential_test
ATF_TESTS_C+= fenv_test
ATF_TESTS_C+= fma_test
ATF_TESTS_C+= fmaxmin_test
+ATF_TESTS_C+= fmaximum_fminimum_test
ATF_TESTS_C+= ilogb2_test
ATF_TESTS_C+= invtrig_test
ATF_TESTS_C+= invctrig_test
diff --git a/lib/msun/tests/fmaximum_fminimum_test.c b/lib/msun/tests/fmaximum_fminimum_test.c
new file mode 100644
index 000000000000..4c8ec9a5b0e0
--- /dev/null
+++ b/lib/msun/tests/fmaximum_fminimum_test.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.org>
+ * Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Tests for fmaximum{,f,l}(), fminimum{,f,l}(), fmaximum_mag{,f,l},
+ * fminimum_mag{,f,l}, fmaximum_num{,f,l}, fminimum_num{,f,l}
+ */
+
+#include <sys/cdefs.h>
+#include <fenv.h>
+#include <float.h>
+#include <math.h>
+
+#include "test-utils.h"
+
+#pragma STDC FENV_ACCESS ON
+
+/*
+ * Test whether func(x, y) has the expected result, and make sure no
+ * exceptions are raised.
+ */
+#define TEST(func, type, x, y, expected, rmode) do { \
+ type __x = (x); /* convert before we clear exceptions */ \
+ type __y = (y); \
+ ATF_REQUIRE_EQ(0, feclearexcept(ALL_STD_EXCEPT)); \
+ long double __result = func((__x), (__y)); \
+ CHECK_FP_EXCEPTIONS_MSG(0, ALL_STD_EXCEPT, \
+ #func "(%.20Lg, %.20Lg) rmode%d", (x), (y), rmode); \
+ ATF_CHECK_MSG(fpequal_cs(__result, (expected), true), \
+ #func "(%.20Lg, %.20Lg) rmode%d = %.20Lg, expected %.20Lg", \
+ (x), (y), rmode, __result, (expected)); \
+} while (0)
+
+static void
+testall_r(long double big, long double small, int rmode)
+{
+ long double expected_max, expected_min;
+ if (isnan(big) || isnan(small)) {
+ expected_max = NAN;
+ expected_min = expected_max;
+ } else {
+ expected_max = big;
+ expected_min = small;
+ }
+
+ TEST(fmaximumf, float, big, small, expected_max, rmode);
+ TEST(fmaximumf, float, small, big, expected_max, rmode);
+ TEST(fmaximum, double, big, small, expected_max, rmode);
+ TEST(fmaximum, double, small, big, expected_max, rmode);
+ TEST(fmaximuml, long double, big, small, expected_max, rmode);
+ TEST(fmaximuml, long double, small, big, expected_max, rmode);
+ TEST(fminimumf, float, big, small, expected_min, rmode);
+ TEST(fminimumf, float, small, big, expected_min, rmode);
+ TEST(fminimum, double, big, small, expected_min, rmode);
+ TEST(fminimum, double, small, big, expected_min, rmode);
+ TEST(fminimuml, long double, big, small, expected_min, rmode);
+ TEST(fminimuml, long double, small, big, expected_min, rmode);
+}
+
+static void
+testall_mag_r(long double big, long double small, int rmode) {
+ long double expected_max_mag, expected_min_mag;
+ if (isnan(big) || isnan(small)) {
+ expected_max_mag = NAN;
+ expected_min_mag = expected_max_mag;
+ } else {
+ if (fabsl(small) > fabsl(big)) {
+ expected_max_mag = small;
+ expected_min_mag = big;
+ } else {
+ expected_max_mag = big;
+ expected_min_mag = small;
+ }
+ }
+
+ TEST(fmaximum_magf, float, big, small, expected_max_mag, rmode);
+ TEST(fmaximum_magf, float, small, big, expected_max_mag, rmode);
+ TEST(fmaximum_mag, double, big, small, expected_max_mag, rmode);
+ TEST(fmaximum_mag, double, small, big, expected_max_mag, rmode);
+ TEST(fmaximum_magl, long double, big, small, expected_max_mag, rmode);
+ TEST(fmaximum_magl, long double, small, big, expected_max_mag, rmode);
+ TEST(fminimum_magf, float, big, small, expected_min_mag, rmode);
+ TEST(fminimum_magf, float, small, big, expected_min_mag, rmode);
+ TEST(fminimum_mag, double, big, small, expected_min_mag, rmode);
+ TEST(fminimum_mag, double, small, big, expected_min_mag, rmode);
+ TEST(fminimum_magl, long double, big, small, expected_min_mag, rmode);
+ TEST(fminimum_magl, long double, small, big, expected_min_mag, rmode);
+}
+
+static void
+testall_num_r(long double big, long double small, int rmode) {
+ long double expected_max_num = isnan(big) ? small : big;
+ long double expected_min_num = isnan(small) ? big : small;
+
+ TEST(fmaximum_numf, float, big, small, expected_max_num, rmode);
+ TEST(fmaximum_numf, float, small, big, expected_max_num, rmode);
+ TEST(fmaximum_num, double, big, small, expected_max_num, rmode);
+ TEST(fmaximum_num, double, small, big, expected_max_num, rmode);
+ TEST(fmaximum_numl, long double, big, small, expected_max_num, rmode);
+ TEST(fmaximum_numl, long double, small, big, expected_max_num, rmode);
+ TEST(fminimum_numf, float, big, small, expected_min_num, rmode);
+ TEST(fminimum_numf, float, small, big, expected_min_num, rmode);
+ TEST(fminimum_num, double, big, small, expected_min_num, rmode);
+ TEST(fminimum_num, double, small, big, expected_min_num, rmode);
+ TEST(fminimum_numl, long double, big, small, expected_min_num, rmode);
+ TEST(fminimum_numl, long double, small, big, expected_min_num, rmode);
+}
+
+/*
+ * Test all the functions: fmaximumf, fmaximum, fmaximuml, fminimumf, fminimum, fminimuml
+ * in all rounding modes and with the arguments in different orders.
+ * The input 'big' must be >= 'small'.
+ */
+static void
+testall(long double big, long double small)
+{
+ static const int rmodes[] = {
+ FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO
+ };
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ fesetround(rmodes[i]);
+ testall_r(big, small, rmodes[i]);
+ testall_mag_r(big, small, rmodes[i]);
+ testall_num_r(big, small, rmodes[i]);
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(test1);
+ATF_TC_BODY(test1, tc)
+{
+ testall(1.0, 0.0);
+}
+
+ATF_TC_WITHOUT_HEAD(test2);
+ATF_TC_BODY(test2, tc)
+{
+ testall(42.0, nextafterf(42.0, -INFINITY));
+}
+ATF_TC_WITHOUT_HEAD(test3);
+ATF_TC_BODY(test3, tc)
+{
+ testall(nextafterf(42.0, INFINITY), 42.0);
+}
+
+ATF_TC_WITHOUT_HEAD(test4);
+ATF_TC_BODY(test4, tc)
+{
+ testall(-5.0, -5.0);
+}
+
+ATF_TC_WITHOUT_HEAD(test5);
+ATF_TC_BODY(test5, tc)
+{
+ testall(-3.0, -4.0);
+}
+
+ATF_TC_WITHOUT_HEAD(test6);
+ATF_TC_BODY(test6, tc)
+{
+ testall(1.0, NAN);
+}
+ATF_TC_WITHOUT_HEAD(test7);
+ATF_TC_BODY(test7, tc)
+{
+ testall(INFINITY, NAN);
+}
+
+ATF_TC_WITHOUT_HEAD(test8);
+ATF_TC_BODY(test8, tc)
+{
+ testall(INFINITY, 1.0);
+}
+
+ATF_TC_WITHOUT_HEAD(test9);
+ATF_TC_BODY(test9, tc)
+{
+ testall(-3.0, -INFINITY);
+}
+
+ATF_TC_WITHOUT_HEAD(test10);
+ATF_TC_BODY(test10, tc)
+{
+ testall(3.0, -INFINITY);
+}
+
+ATF_TC_WITHOUT_HEAD(test11);
+ATF_TC_BODY(test11, tc)
+{
+ testall(NAN, NAN);
+}
+
+ATF_TC_WITHOUT_HEAD(test12);
+ATF_TC_BODY(test12, tc)
+{
+ testall(0.0, -0.0);
+}
+
+
+ATF_TC_WITHOUT_HEAD(test13);
+ATF_TC_BODY(test13, tc)
+{
+ testall(2.0, -2.0);
+}
+
+ATF_TC_WITHOUT_HEAD(test14);
+ATF_TC_BODY(test14, tc)
+{
+ testall(-0.0, -0.0);
+}
+
+ATF_TC_WITHOUT_HEAD(test15);
+ATF_TC_BODY(test15, tc)
+{
+ testall(0.0, 0.0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, test1);
+ ATF_TP_ADD_TC(tp, test2);
+ ATF_TP_ADD_TC(tp, test3);
+ ATF_TP_ADD_TC(tp, test4);
+ ATF_TP_ADD_TC(tp, test5);
+ ATF_TP_ADD_TC(tp, test6);
+ ATF_TP_ADD_TC(tp, test7);
+ ATF_TP_ADD_TC(tp, test8);
+ ATF_TP_ADD_TC(tp, test9);
+ ATF_TP_ADD_TC(tp, test10);
+ ATF_TP_ADD_TC(tp, test11);
+ ATF_TP_ADD_TC(tp, test12);
+ ATF_TP_ADD_TC(tp, test13);
+ ATF_TP_ADD_TC(tp, test14);
+ ATF_TP_ADD_TC(tp, test15);
+
+ return (atf_no_error());
+}
diff --git a/lib/msun/x86/fenv.h b/lib/msun/x86/fenv.h
index b806222e5ef6..b5da37902083 100644
--- a/lib/msun/x86/fenv.h
+++ b/lib/msun/x86/fenv.h
@@ -108,7 +108,7 @@ int feraiseexcept(int __excepts);
int feupdateenv(const fenv_t *__envp);
__fenv_static inline int
-fegetround(void)
+__fegetround_int(void)
{
__uint16_t __control;
@@ -144,7 +144,18 @@ fegetexcept(void)
#endif /* __BSD_VISIBLE */
int feclearexcept(int);
+int fegetexceptflag(fexcept_t *, int);
+int fetestexcept(int);
+int fesetround(int);
+int fegetround(void);
+int fesetenv(const fenv_t *);
+
#define feclearexcept(a) __feclearexcept_int(a)
+#define fegetexceptflag(e, a) __fegetexceptflag_int(e, a)
+#define fetestexcept(a) __fetestexcept_int(a)
+#define fesetround(a) __fesetround_int(a)
+#define fegetround() __fegetround_int()
+#define fesetenv(a) __fesetenv_int(a)
#ifdef __i386__
@@ -188,7 +199,7 @@ __feclearexcept_int(int __excepts)
}
__fenv_static inline int
-fegetexceptflag(fexcept_t *__flagp, int __excepts)
+__fegetexceptflag_int(fexcept_t *__flagp, int __excepts)
{
__uint32_t __mxcsr;
__uint16_t __status;
@@ -203,7 +214,7 @@ fegetexceptflag(fexcept_t *__flagp, int __excepts)
}
__fenv_static inline int
-fetestexcept(int __excepts)
+__fetestexcept_int(int __excepts)
{
__uint32_t __mxcsr;
__uint16_t __status;
@@ -217,7 +228,7 @@ fetestexcept(int __excepts)
}
__fenv_static inline int
-fesetround(int __round)
+__fesetround_int(int __round)
{
__uint32_t __mxcsr;
__uint16_t __control;
@@ -241,7 +252,7 @@ fesetround(int __round)
}
__fenv_static inline int
-fesetenv(const fenv_t *__envp)
+__fesetenv_int(const fenv_t *__envp)
{
fenv_t __env = *__envp;
__uint32_t __mxcsr;
@@ -283,7 +294,7 @@ __feclearexcept_int(int __excepts)
}
__fenv_static inline int
-fegetexceptflag(fexcept_t *__flagp, int __excepts)
+__fegetexceptflag_int(fexcept_t *__flagp, int __excepts)
{
__uint32_t __mxcsr;
__uint16_t __status;
@@ -295,7 +306,7 @@ fegetexceptflag(fexcept_t *__flagp, int __excepts)
}
__fenv_static inline int
-fetestexcept(int __excepts)
+__fetestexcept_int(int __excepts)
{
__uint32_t __mxcsr;
__uint16_t __status;
@@ -306,7 +317,7 @@ fetestexcept(int __excepts)
}
__fenv_static inline int
-fesetround(int __round)
+__fesetround_int(int __round)
{
__uint32_t __mxcsr;
__uint16_t __control;
@@ -328,7 +339,7 @@ fesetround(int __round)
}
__fenv_static inline int
-fesetenv(const fenv_t *__envp)
+__fesetenv_int(const fenv_t *__envp)
{
/*