diff options
Diffstat (limited to 'lib')
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) { /* |
