Merge "Add the %m GNU extension to printf/wprintf."
diff --git a/README.md b/README.md
index a6cf467..12c5235 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,17 @@
-Using bionic
-============
+# bionic
-See the [additional documentation](docs/).
+[bionic](https://en.wikipedia.org/wiki/Bionic_(software)) is Android's
+C library, math library, and dynamic linker.
-Working on bionic
-=================
+# Using bionic as an app developer
-What are the big pieces of bionic?
-----------------------------------
+See the [user documentation](docs/).
+
+# Working on bionic itself
+
+This documentation is about making changes to bionic itself.
+
+## What are the big pieces of bionic?
#### libc/ --- libc.so, libc.a
@@ -51,10 +55,9 @@
The `benchmarks/` directory contains benchmarks, with its own [documentation](benchmarks/README.md).
-What's in libc/?
-----------------
+## What's in libc/?
-<pre>
+```
libc/
arch-arm/
arch-arm64/
@@ -69,12 +72,6 @@
bionic/
# Every architecture needs a handful of machine-specific assembler files.
# They live here.
- include/
- machine/
- # The majority of header files are actually in libc/include/, but many
- # of them pull in a <machine/something.h> for things like limits,
- # endianness, and how floating point numbers are represented. Those
- # headers live here.
string/
# Most architectures have a handful of optional assembler files
# implementing optimized versions of various routines. The <string.h>
@@ -141,11 +138,10 @@
zoneinfo/
# Android-format time zone data.
# See 'Updating tzdata' later.
-</pre>
+```
-Adding libc wrappers for system calls
--------------------------------------
+## Adding libc wrappers for system calls
The first question you should ask is "should I add a libc wrapper for
this system call?". The answer is usually "no".
@@ -183,8 +179,7 @@
correct system call is being made.)
-Updating kernel header files
-----------------------------
+## Updating kernel header files
As mentioned above, this is currently a two-step process:
@@ -197,8 +192,7 @@
`TARGET_DEVICE_KERNEL_HEADERS` and friends described in [config.mk](https://android.googlesource.com/platform/build/+/master/core/config.mk#186).
-Updating tzdata
----------------
+## Updating tzdata
This is fully automated (and these days handled by the libcore team, because
they own icu, and that needs to be updated in sync with bionic):
@@ -206,8 +200,7 @@
1. Run update-tzdata.py in external/icu/tools/.
-Verifying changes
------------------
+## Verifying changes
If you make a change that is likely to have a wide effect on the tree (such as a
libc header change), you should run `make checkbuild`. A regular `make` will
@@ -218,8 +211,7 @@
`make checkbuild` is enough.
-Running the tests
------------------
+## Running the tests
The tests are all built from the tests/ directory.
@@ -285,8 +277,7 @@
$ ./tests/run-on-host.sh glibc
-Gathering test coverage
------------------------
+## Gathering test coverage
For either host or target coverage, you must first:
@@ -319,8 +310,7 @@
The coverage report is now available at `covreport/index.html`.
-Attaching GDB to the tests
---------------------------
+## Attaching GDB to the tests
Bionic's test runner will run each test in its own process by default to prevent
tests failures from impacting other tests. This also has the added benefit of
@@ -330,7 +320,6 @@
each test from being forked, run the tests with the flag `--no-isolate`.
-32-bit ABI bugs
----------------
+## 32-bit ABI bugs
See [32-bit ABI bugs](docs/32-bit-abi.md).
diff --git a/docs/status.md b/docs/status.md
index d589721..e41baa6 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -37,11 +37,11 @@
Current libc symbols: https://android.googlesource.com/platform/bionic/+/master/libc/libc.map.txt
-New libc functions in Q:
+New libc functions in Q (API level 29):
* `timespec_get` (C11 `<time.h>` addition)
* `res_randomid` (in `<resolv.h>`)
-New libc functions in P:
+New libc functions in P (API level 28):
* `__freading`/`__fwriting` (completing <stdio_ext.h>)
* `endhostent`/`endnetent`/`endprotoent`/`getnetent`/`getprotoent`/`sethostent`/`setnetent`/`setprotoent` (completing <netdb.h>)
* `fexecve`
@@ -58,12 +58,12 @@
* `swab`
* `syncfs`
-New libc behavior in P:
+New libc behavior in P (API level 28):
* `%C` and `%S` support in the printf family (previously only the wprintf family supported these)
* `%mc`/`%ms`/`%m[` support in the scanf family
* `%s` support in strptime (strftime already supported it)
-New libc functions in O:
+New libc functions in O (API level 26):
* `sendto` FORTIFY support
* `__system_property_read_callback`/`__system_property_wait`
* legacy `bsd_signal`
@@ -86,18 +86,90 @@
* `strtod_l`/`strtof_l`/`strtol_l`/`strtoul_l`
* <wctype.h> `towctrans`/`towctrans_l`/`wctrans`/`wctrans_l`
-New libc functions in N:
+New libc functions in N (API level 24):
* more FORTIFY support functions (`fread`/`fwrite`/`getcwd`/`pwrite`/`write`)
* all remaining `_FILE_OFFSET_BITS=64` functions, completing `_FILE_OFFSET_BITS=64` support in bionic (8)
* all 7 `pthread_barrier*` functions
* all 5 `pthread_spin*` functions
* `lockf`/`preadv`/`pwritev`/`scandirat` and `off64_t` variants
* `adjtimex`/`clock_adjtime`
- * `getifaddrs`/`freeifaddrs`/`if_freenameindex`/`if_nameindex`
+ * <ifaddrs.h> `getifaddrs`/`freeifaddrs`/`if_freenameindex`/`if_nameindex`
* `getgrgid_r`/`getgrnam_r`
* GNU extensions `fileno_unlocked`/`strchrnul`
* 32-bit `prlimit`
+New libc functions in M (API level 23):
+ * <dirent.h> `telldir`, `seekdir`.
+ * <malloc.h> `malloc_info`.
+ * <netdb.h> `gethostbyaddr_r`, `gethostbyname2_r`.
+ * <pthread.h> `pthread_rwlockattr_getkind_np`/`pthread_rwlockattr_setkind_np`.
+ * <pty.h> `forkpty`, `openpty`.
+ * <signal.h> `sigqueue`, `sigtimedwait`, `sigwaitinfo`.
+ * <stdio.h> `fmemopen`, `open_memstream`, `feof_unlocked`, `ferror_unlocked`, `clearerr_unlocked`.
+ * <stdio_ext.h> `__flbf`, `__freadable`, `__fsetlocking`, `__fwritable`, `__fbufsize`, `__fpending`, `_flushlbf`, `__fpurge`.
+ * <stdlib.h> `mkostemp`/`mkostemps`, `lcong48`.
+ * <string.h> `basename`, `strerror_l`, `strerror_r`, `mempcpy`.
+ * <sys/sysinfo.h> `get_nprocs_conf`/`get_nprocs`, `get_phys_pages`, `get_avphys_pages`.
+ * <sys/uio.h> `process_vm_readv`/`process_vm_writev`.
+ * `clock_getcpuclockid`, `login_tty`, `mkfifoat`, `posix_madvise`, `sethostname`, `strcasecmp_l`/`strncasecmp_l`.
+ * <wchar.h> `open_wmemstream`, `wcscasecmp_l`/`wcsncasecmp_l`, `wmempcpy`.
+ * all of <error.h>.
+ * re-introduced various <resolv.h> functions: `ns_format_ttl`, `ns_get16`, `ns_get32`, `ns_initparse`, `ns_makecanon`, `ns_msg_getflag`, `ns_name_compress`, `ns_name_ntol`, `ns_name_ntop`, `ns_name_pack`, `ns_name_pton`, `ns_name_rollback`, `ns_name_skip`, `ns_name_uncompress`, `ns_name_unpack`, `ns_parserr`, `ns_put16`, `ns_put32`, `ns_samename`, `ns_skiprr`, `ns_sprintrr`, and `ns_sprintrrf`.
+
+New libc functions in L (API level 21):
+ * <android/dlext.h>.
+ * <android/set_abort_message.h>.
+ * <arpa/inet.h> `inet_lnaof`, `inet_netof`, `inet_network`, `inet_makeaddr`.
+ * <wctype.h> `iswblank`.
+ * <ctype.h> `isalnum_l`, `isalpha_l`, `isblank_l`, `icntrl_l`, `isdigit_l`, `isgraph_l`, `islower_l`, `isprint_l`, `ispunct_l`, `isspace_l`, `isupper_l`, `isxdigit_l`, `_tolower`, `tolower_l`, `_toupper`, `toupper_l`.
+ * <fcntl.h> `fallocate`, `posix_fadvise`, `posix_fallocate`, `splice`, `tee`, `vmsplice`.
+ * <inttypes.h> `wcstoimax`, `wcstoumax`.
+ * <link.h> `dl_iterate_phdr`.
+ * <mntent.h> `setmntent`, `endmntent`, `getmntent_r`.
+ * <poll.h> `ppoll`.
+ * <pthread.h> `pthread_condattr_getclock`, `pthread_condattr_setclock`, `pthread_mutex_timedlock`, `pthread_gettid_np`.
+ * <sched.h> `setns`.
+ * <search.h> `insque`, `remque`, `lfind`, `lsearch`, `twalk`.
+ * <stdio.h> `dprintf`, `vdprintf`.
+ * <stdlib.h> `initstate`, `setstate`, `getprogname`/`setprogname`, `atof`/`strtof`, `at_quick_exit`/`_Exit`/`quick_exit`, `grantpt`, `mbtowc`/`wctomb`, `posix_openpt`, `rand_r`/`rand`/`random`/`srand`/`srandom`, `strtold_l`/`strtoll_l`/`strtoull_l`.
+ * <string.h> `strcoll_l`/`strxfrm_l`, `stpcpy`/`stpncpy`.
+ * <sys/resource.h> `prlimit`.
+ * <sys/socket.h> `accept4`, `sendmmsg`.
+ * <sys/stat.h> `mkfifo`/`mknodat`.
+ * <time.h> `strftime_l`.
+ * <unistd.h> `dup3`, `execvpe`, `getpagesize`, `linkat`/`symlinkat`/`readlinkat`, `truncate`.
+ * <wchar.h> `wcstof`, `vfwscanf`/`vswscanf`/`vwscanf`, `wcstold_l`/`wcstoll`/`wcstoll_l`/`wcstoull`/`wcstoull_l`, `mbsnrtowcs`/`wcsnrtombs`, `wcscoll_l`/`wcsxfrm_l`.
+ * <wctype.h> `iswalnum_l`/`iswalpha_l`/`iswblank_l`/`iswcntrl_l`/`iswctype_l`/`iswdigit_l`/`iswgraph_l`/`iswlower_l`/`iswprint_l`/`iswpunct_l`/`iswspace_l`/`iswupper_l`/`iswxdigit_l`, `wctype_l`, `towlower_l`/`towupper_l`.
+ * all of <fts.h>.
+ * all of <locale.h>.
+ * all of <sys/epoll.h>.
+ * all of <sys/fsuid.h>.
+ * all of <sys/inotify.h>.
+ * all of <uchar.h>.
+
+New libc functions in K (API level 19):
+ * <inttypes.h> `imaxabs`, `imaxdiv`.
+ * <stdlib.h> `abs`, `labs`, `llabs`.
+ * <sys/stat.h> `futimens`.
+ * all of <sys/statvfs.h>.
+ * all of <sys/swap.h>.
+ * all of <sys/timerfd.h>.
+
+New libc functions in J-MR2 (API level 18):
+ * <stdio.h> `getdelim` and `getline`.
+ * <sys/auxv.h> `getauxval`.
+ * <sys/signalfd.h> `signalfd`.
+
+New libc functions in J-MR1 (API level 17):
+ * <ftw.h>.
+ * <signal.h> `psiginfo` and `psignal`.
+ * `getsid`, `malloc_usable_size`, `mlockall`/`munlockall`, `posix_memalign`, `unshare`.
+
+New libc functions in J (API level 16):
+ * the <search.h> tree functions `tdelete`, `tdestroy`, `tfind`, and `tsearch`.
+ * `faccessat`, `readahead`, `tgkill`.
+ * all of <sys/xattr.h>.
+
libc function count over time:
G 803, H 825, I 826, J 846, J-MR1 873, J-MR2 881, K 896, L 1116, M 1181, N 1226, O 1278
@@ -112,7 +184,19 @@
0 remaining missing POSIX libm functions.
-19 new libm functions in O: complex trig/exp/log functions.
+New libm functions in O (API level 26):
+ * <complex.h> `clog`/`clogf`, `cpow`/`cpowf` functions.
+
+New libm functions in M (API level 23):
+ * <complex.h> `cabs`, `carg`, `cimag`, `cacos`, `cacosh`, `casin`, `casinh`, `catan`, `catanh`, `ccos`, `ccosh`, `cexp`, `conj`, `cproj`, `csin`, `csinh`, `csqrt`, `ctan`, `ctanh`, `creal`, `cabsf`, `cargf`, `cimagf`, `cacosf`, `cacoshf`, `casinf`, `casinhf`, `catanf`, `catanhf`, `ccosf`, `ccoshf`, `cexpf`, `conjf`, `cprojf`, `csinf`, `csinhf`, `csqrtf`, `ctanf`, `ctanhf`, `crealf`, `cabsl`, `cprojl`, `csqrtl`.
+ * <math.h> `lgammal_r`.
+
+New libm functions in L (API level 21):
+ * <complex.h> `cabsl`, `cprojl`, `csqrtl`.
+ * <math.h> `isinf`, `significandl`.
+
+New libm functions in J-MR2 (API level 18):
+ * <math.h> `log2`, `log2f`.
libm function count over time:
G 158, J-MR2 164, L 220, M 265, O 284
diff --git a/libc/arch-arm64/generic/bionic/__memcpy_chk.S b/libc/arch-arm64/generic/bionic/__memcpy_chk.S
index 4217775..a6eeca4 100644
--- a/libc/arch-arm64/generic/bionic/__memcpy_chk.S
+++ b/libc/arch-arm64/generic/bionic/__memcpy_chk.S
@@ -30,8 +30,11 @@
ENTRY(__memcpy_chk)
cmp x2, x3
- bls memcpy
+ // Direct b.ls memcpy may not have enough range
+ b.hi .L_memcpy_chk_fail
+ b memcpy
+.L_memcpy_chk_fail:
// Preserve for accurate backtrace.
stp x29, x30, [sp, -16]!
.cfi_def_cfa_offset 16
diff --git a/libc/bionic/NetdClient.cpp b/libc/bionic/NetdClient.cpp
index a1071d2..966cbcc 100644
--- a/libc/bionic/NetdClient.cpp
+++ b/libc/bionic/NetdClient.cpp
@@ -24,6 +24,8 @@
#include <dlfcn.h>
#include <pthread.h>
+#include <string.h>
+#include <unistd.h>
template <typename FunctionType>
static void netdClientInitFunction(void* handle, const char* symbol, FunctionType* function) {
@@ -35,6 +37,14 @@
}
static void netdClientInitImpl() {
+ // Prevent netd from looping back fwmarkd connections to itself. It would work, but it's
+ // a deadlock hazard and unnecessary overhead for the resolver.
+ if (getuid() == 0 && strcmp(getprogname(), "netd") == 0) {
+ async_safe_format_log(ANDROID_LOG_INFO, "netdClient",
+ "Skipping libnetd_client init since *we* are netd");
+ return;
+ }
+
void* netdClientHandle = dlopen("libnetd_client.so", RTLD_NOW);
if (netdClientHandle == NULL) {
// If the library is not available, it's not an error. We'll just use
@@ -54,6 +64,6 @@
extern "C" __LIBC_HIDDEN__ void netdClientInit() {
if (pthread_once(&netdClientInitOnce, netdClientInitImpl)) {
- async_safe_format_log(ANDROID_LOG_ERROR, "netdClient", "Failed to initialize netd_client");
+ async_safe_format_log(ANDROID_LOG_ERROR, "netdClient", "Failed to initialize libnetd_client");
}
}
diff --git a/libc/bionic/abort.cpp b/libc/bionic/abort.cpp
index d2c99a5..c8bba01 100644
--- a/libc/bionic/abort.cpp
+++ b/libc/bionic/abort.cpp
@@ -32,32 +32,9 @@
#include <sys/syscall.h>
#include <unistd.h>
-// We call tgkill(2) directly instead of raise (or even the libc tgkill wrapper), to reduce the
-// number of uninteresting stack frames at the top of a crash.
-static inline __always_inline void inline_tgkill(pid_t pid, pid_t tid, int sig) {
-#if defined(__arm__)
- register int r0 __asm__("r0") = pid;
- register int r1 __asm__("r1") = tid;
- register int r2 __asm__("r2") = sig;
- register int r7 __asm__("r7") = __NR_tgkill;
- __asm__("swi #0" : "=r"(r0) : "r"(r0), "r"(r1), "r"(r2), "r"(r7) : "memory");
-#elif defined(__aarch64__)
- register long x0 __asm__("x0") = pid;
- register long x1 __asm__("x1") = tid;
- register long x2 __asm__("x2") = sig;
- register long x8 __asm__("x8") = __NR_tgkill;
- __asm__("svc #0" : "=r"(x0) : "r"(x0), "r"(x1), "r"(x2), "r"(x8) : "memory");
-#else
- syscall(__NR_tgkill, pid, tid, sig);
-#endif
-}
+#include "private/bionic_inline_raise.h"
void abort() {
- // Protect ourselves against stale cached PID/TID values by fetching them via syscall.
- // http://b/37769298
- pid_t pid = syscall(__NR_getpid);
- pid_t tid = syscall(__NR_gettid);
-
// Don't block SIGABRT to give any signal handler a chance; we ignore
// any errors -- X311J doesn't allow abort to return anyway.
sigset64_t mask;
@@ -65,7 +42,7 @@
sigdelset64(&mask, SIGABRT);
sigprocmask64(SIG_SETMASK, &mask, nullptr);
- inline_tgkill(pid, tid, SIGABRT);
+ inline_raise(SIGABRT);
// If SIGABRT is ignored or it's caught and the handler returns,
// remove the SIGABRT signal handler and raise SIGABRT again.
@@ -73,7 +50,7 @@
sigaction64(SIGABRT, &sa, nullptr);
sigprocmask64(SIG_SETMASK, &mask, nullptr);
- inline_tgkill(pid, tid, SIGABRT);
+ inline_raise(SIGABRT);
// If we get this far, just exit.
_exit(127);
diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp
index ad1ddee..31ffa96 100644
--- a/libc/bionic/fdsan.cpp
+++ b/libc/bionic/fdsan.cpp
@@ -43,6 +43,7 @@
#include <sys/system_properties.h>
#include "private/bionic_globals.h"
+#include "private/bionic_inline_raise.h"
#include "pthread_internal.h"
extern "C" int ___close(int fd);
@@ -200,12 +201,11 @@
__BIONIC_FALLTHROUGH;
case ANDROID_FDSAN_ERROR_LEVEL_WARN_ALWAYS:
// DEBUGGER_SIGNAL
- sigval abort_msg;
- abort_msg.sival_ptr = &abort_message;
- pthread_sigqueue(pthread_self(), __SIGRTMIN + 3, abort_msg);
+ inline_raise(__SIGRTMIN + 3, &abort_message);
break;
case ANDROID_FDSAN_ERROR_LEVEL_FATAL:
+ inline_raise(SIGABRT);
abort();
case ANDROID_FDSAN_ERROR_LEVEL_DISABLED:
@@ -247,6 +247,8 @@
return "ParcelFileDescriptor";
case ANDROID_FDSAN_OWNER_TYPE_SQLITE:
return "sqlite";
+ case ANDROID_FDSAN_OWNER_TYPE_ART_FDFILE:
+ return "ART FdFile";
case ANDROID_FDSAN_OWNER_TYPE_GENERIC_00:
default:
diff --git a/libc/include/android/fdsan.h b/libc/include/android/fdsan.h
index cbea460..dc2bbd5 100644
--- a/libc/include/android/fdsan.h
+++ b/libc/include/android/fdsan.h
@@ -111,6 +111,9 @@
/* android.os.ParcelFileDescriptor */
ANDROID_FDSAN_OWNER_TYPE_PARCELFILEDESCRIPTOR = 8,
+
+ /* ART FdFile */
+ ANDROID_FDSAN_OWNER_TYPE_ART_FDFILE = 9,
};
/*
diff --git a/libc/include/android/legacy_fenv_inlines_arm.h b/libc/include/android/legacy_fenv_inlines_arm.h
index 6f2c959..5ec5582 100644
--- a/libc/include/android/legacy_fenv_inlines_arm.h
+++ b/libc/include/android/legacy_fenv_inlines_arm.h
@@ -1,141 +1,43 @@
-/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+/*
+ * Copyright (C) 2018 The Android Open Source Project
* 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
+ * * 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.
+ * * 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
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
- *
- * $FreeBSD: src/lib/msun/arm/fenv.c,v 1.1 2004/06/06 10:03:59 das Exp $
*/
-#ifndef ANDROID_LEGACY_FENV_INLINES_ARM_H
-#define ANDROID_LEGACY_FENV_INLINES_ARM_H
+#pragma once
+
+/**
+ * @file legacy_fenv_inlines_arm.h
+ * @brief Inline ARM-specific definitions of fenv for old API levels.
+ */
#include <sys/cdefs.h>
#if __ANDROID_API__ < __ANDROID_API_L__ && defined(__arm__)
-#include <fenv.h>
+#define __BIONIC_FENV_INLINE static __inline
+#include <bits/fenv_inlines_arm.h>
-__BEGIN_DECLS
-
-#define FPSCR_RMODE_SHIFT 22
-
-static __inline int fegetenv(fenv_t* __envp) {
- fenv_t _fpscr;
- __asm__ __volatile__("vmrs %0,fpscr" : "=r" (_fpscr));
- *__envp = _fpscr;
- return 0;
-}
-
-static __inline int fesetenv(const fenv_t* __envp) {
- fenv_t _fpscr = *__envp;
- __asm__ __volatile__("vmsr fpscr,%0" : :"ri" (_fpscr));
- return 0;
-}
-
-static __inline int feclearexcept(int __excepts) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- __fpscr &= ~__excepts;
- fesetenv(&__fpscr);
- return 0;
-}
-
-static __inline int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- *__flagp = __fpscr & __excepts;
- return 0;
-}
-
-static __inline int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- __fpscr &= ~__excepts;
- __fpscr |= *__flagp & __excepts;
- fesetenv(&__fpscr);
- return 0;
-}
-
-static __inline int feraiseexcept(int __excepts) {
- fexcept_t __ex = __excepts;
- fesetexceptflag(&__ex, __excepts);
- return 0;
-}
-
-static __inline int fetestexcept(int __excepts) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- return (__fpscr & __excepts);
-}
-
-static __inline int fegetround(void) {
- fenv_t _fpscr;
- fegetenv(&_fpscr);
- return ((_fpscr >> FPSCR_RMODE_SHIFT) & 0x3);
-}
-
-static __inline int fesetround(int __round) {
- fenv_t _fpscr;
- fegetenv(&_fpscr);
- _fpscr &= ~(0x3 << FPSCR_RMODE_SHIFT);
- _fpscr |= (__round << FPSCR_RMODE_SHIFT);
- fesetenv(&_fpscr);
- return 0;
-}
-
-static __inline int feholdexcept(fenv_t* __envp) {
- fenv_t __env;
- fegetenv(&__env);
- *__envp = __env;
- __env &= ~FE_ALL_EXCEPT;
- fesetenv(&__env);
- return 0;
-}
-
-static __inline int feupdateenv(const fenv_t* __envp) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- fesetenv(__envp);
- feraiseexcept(__fpscr & FE_ALL_EXCEPT);
- return 0;
-}
-
-static __inline int feenableexcept(int __mask __unused) {
- return -1;
-}
-
-static __inline int fedisableexcept(int __mask __unused) {
- return 0;
-}
-
-static __inline int fegetexcept(void) {
- return 0;
-}
-
-#undef FPSCR_RMODE_SHIFT
-
-__END_DECLS
-
-#endif /* __ANDROID_API__ < __ANDROID_API_L__ && defined(__arm__) */
-
-#endif /* ANDROID_LEGACY_FENV_INLINES_ARM_H */
+#endif
diff --git a/libc/include/android/legacy_fenv_inlines_mips.h b/libc/include/android/legacy_fenv_inlines_mips.h
index 43ad360..ccc824c 100644
--- a/libc/include/android/legacy_fenv_inlines_mips.h
+++ b/libc/include/android/legacy_fenv_inlines_mips.h
@@ -1,170 +1,43 @@
-/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+/*
+ * Copyright (C) 2018 The Android Open Source Project
* 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
+ * * 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.
+ * * 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
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
- *
- * $FreeBSD: src/lib/msun/mips/fenv.c,v 1.1 2008/04/26 12:20:29 imp Exp $
*/
-#ifndef ANDROID_LEGACY_FENV_INLINES_MIPS_H
-#define ANDROID_LEGACY_FENV_INLINES_MIPS_H
+#pragma once
+
+/**
+ * @file legacy_fenv_inlines_mips.h
+ * @brief Inline MIPS-specific definitions of fenv for old API levels.
+ */
#include <sys/cdefs.h>
#if __ANDROID_API__ < __ANDROID_API_L__ && (defined(__mips__) && !defined(__LP64__))
-#include <fenv.h>
+#define __BIONIC_FENV_INLINE static __inline
+#include <bits/fenv_inlines_mips.h>
-__BEGIN_DECLS
-
-#define FCSR_CAUSE_SHIFT 10
-#define FCSR_ENABLE_SHIFT 5
-#define FCSR_ENABLE_MASK (FE_ALL_EXCEPT << FCSR_ENABLE_SHIFT)
-
-#define FCSR_RMASK 0x3
-
-static __inline int fegetenv(fenv_t* __envp) {
- fenv_t _fcsr = 0;
-#ifdef __mips_hard_float
- __asm__ __volatile__("cfc1 %0,$31" : "=r" (_fcsr));
#endif
- *__envp = _fcsr;
- return 0;
-}
-
-static __inline int fesetenv(const fenv_t* __envp) {
- fenv_t _fcsr = *__envp;
-#ifdef __mips_hard_float
- __asm__ __volatile__("ctc1 %0,$31" : : "r" (_fcsr));
-#endif
- return 0;
-}
-
-static __inline int feclearexcept(int __excepts) {
- fexcept_t __fcsr;
- fegetenv(&__fcsr);
- __excepts &= FE_ALL_EXCEPT;
- __fcsr &= ~(__excepts | (__excepts << FCSR_CAUSE_SHIFT));
- fesetenv(&__fcsr);
- return 0;
-}
-
-static __inline int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
- fexcept_t __fcsr;
- fegetenv(&__fcsr);
- *__flagp = __fcsr & __excepts & FE_ALL_EXCEPT;
- return 0;
-}
-
-static __inline int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
- fexcept_t __fcsr;
- fegetenv(&__fcsr);
- /* Ensure that flags are all legal */
- __excepts &= FE_ALL_EXCEPT;
- __fcsr &= ~__excepts;
- __fcsr |= *__flagp & __excepts;
- fesetenv(&__fcsr);
- return 0;
-}
-
-static __inline int feraiseexcept(int __excepts) {
- fexcept_t __fcsr;
- fegetenv(&__fcsr);
- /* Ensure that flags are all legal */
- __excepts &= FE_ALL_EXCEPT;
- /* Cause bit needs to be set as well for generating the exception*/
- __fcsr |= __excepts | (__excepts << FCSR_CAUSE_SHIFT);
- fesetenv(&__fcsr);
- return 0;
-}
-
-static __inline int fetestexcept(int __excepts) {
- fexcept_t __FCSR;
- fegetenv(&__FCSR);
- return (__FCSR & __excepts & FE_ALL_EXCEPT);
-}
-
-static __inline int fegetround(void) {
- fenv_t _fcsr;
- fegetenv(&_fcsr);
- return (_fcsr & FCSR_RMASK);
-}
-
-static __inline int fesetround(int __round) {
- fenv_t _fcsr;
- fegetenv(&_fcsr);
- _fcsr &= ~FCSR_RMASK;
- _fcsr |= (__round & FCSR_RMASK);
- fesetenv(&_fcsr);
- return 0;
-}
-
-static __inline int feholdexcept(fenv_t* __envp) {
- fenv_t __env;
- fegetenv(&__env);
- *__envp = __env;
- __env &= ~(FE_ALL_EXCEPT | FCSR_ENABLE_MASK);
- fesetenv(&__env);
- return 0;
-}
-
-static __inline int feupdateenv(const fenv_t* __envp) {
- fexcept_t __fcsr;
- fegetenv(&__fcsr);
- fesetenv(__envp);
- feraiseexcept(__fcsr & FE_ALL_EXCEPT);
- return 0;
-}
-
-static __inline int feenableexcept(int __mask) {
- fenv_t __old_fcsr, __new_fcsr;
- fegetenv(&__old_fcsr);
- __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << FCSR_ENABLE_SHIFT;
- fesetenv(&__new_fcsr);
- return ((__old_fcsr >> FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
-}
-
-static __inline int fedisableexcept(int __mask) {
- fenv_t __old_fcsr, __new_fcsr;
- fegetenv(&__old_fcsr);
- __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << FCSR_ENABLE_SHIFT);
- fesetenv(&__new_fcsr);
- return ((__old_fcsr >> FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
-}
-
-static __inline int fegetexcept(void) {
- fenv_t __fcsr;
- fegetenv(&__fcsr);
- return ((__fcsr & FCSR_ENABLE_MASK) >> FCSR_ENABLE_SHIFT);
-}
-
-#undef FCSR_CAUSE_SHIFT
-#undef FCSR_ENABLE_SHIFT
-#undef FCSR_ENABLE_MASK
-#undef FCSR_RMASK
-
-__END_DECLS
-
-#endif /* __ANDROID_API__ < __ANDROID_API_L__ && (defined(__mips__) && !defined(__LP64__)) */
-
-#endif /* ANDROID_LEGACY_FENV_INLINES_MIPS_H */
diff --git a/libc/include/bits/fenv_arm.h b/libc/include/bits/fenv_arm.h
index 042fec3..0cd4844 100644
--- a/libc/include/bits/fenv_arm.h
+++ b/libc/include/bits/fenv_arm.h
@@ -26,8 +26,7 @@
* $FreeBSD: src/lib/msun/arm/fenv.h,v 1.5 2005/03/16 19:03:45 das Exp $
*/
-#ifndef _BITS_FENV_ARM_H_
-#define _BITS_FENV_ARM_H_
+#pragma once
#include <sys/types.h>
@@ -73,5 +72,3 @@
#define FE_TOWARDZERO 0x3
__END_DECLS
-
-#endif
diff --git a/libc/include/bits/fenv_inlines_arm.h b/libc/include/bits/fenv_inlines_arm.h
new file mode 100644
index 0000000..e8b89ea
--- /dev/null
+++ b/libc/include/bits/fenv_inlines_arm.h
@@ -0,0 +1,142 @@
+/*-
+ * 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.
+ *
+ * $FreeBSD: src/lib/msun/arm/fenv.c,v 1.1 2004/06/06 10:03:59 das Exp $
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+
+#if defined(__arm__)
+
+#if !defined(__BIONIC_FENV_INLINE)
+#define __BIONIC_FENV_INLINE static __inline
+#endif
+
+#include <bits/fenv_arm.h>
+
+__BEGIN_DECLS
+
+#define FPSCR_RMODE_SHIFT 22
+
+__BIONIC_FENV_INLINE int fegetenv(fenv_t* __envp) {
+ fenv_t _fpscr;
+ __asm__ __volatile__("vmrs %0,fpscr" : "=r" (_fpscr));
+ *__envp = _fpscr;
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int fesetenv(const fenv_t* __envp) {
+ fenv_t _fpscr = *__envp;
+ __asm__ __volatile__("vmsr fpscr,%0" : :"ri" (_fpscr));
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int feclearexcept(int __excepts) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ __fpscr &= ~__excepts;
+ fesetenv(&__fpscr);
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ *__flagp = __fpscr & __excepts;
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ __fpscr &= ~__excepts;
+ __fpscr |= *__flagp & __excepts;
+ fesetenv(&__fpscr);
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int feraiseexcept(int __excepts) {
+ fexcept_t __ex = __excepts;
+ fesetexceptflag(&__ex, __excepts);
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int fetestexcept(int __excepts) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ return (__fpscr & __excepts);
+}
+
+__BIONIC_FENV_INLINE int fegetround(void) {
+ fenv_t _fpscr;
+ fegetenv(&_fpscr);
+ return ((_fpscr >> FPSCR_RMODE_SHIFT) & 0x3);
+}
+
+__BIONIC_FENV_INLINE int fesetround(int __round) {
+ fenv_t _fpscr;
+ fegetenv(&_fpscr);
+ _fpscr &= ~(0x3 << FPSCR_RMODE_SHIFT);
+ _fpscr |= (__round << FPSCR_RMODE_SHIFT);
+ fesetenv(&_fpscr);
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int feholdexcept(fenv_t* __envp) {
+ fenv_t __env;
+ fegetenv(&__env);
+ *__envp = __env;
+ __env &= ~FE_ALL_EXCEPT;
+ fesetenv(&__env);
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int feupdateenv(const fenv_t* __envp) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ fesetenv(__envp);
+ feraiseexcept(__fpscr & FE_ALL_EXCEPT);
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int feenableexcept(int __mask __unused) {
+ return -1;
+}
+
+__BIONIC_FENV_INLINE int fedisableexcept(int __mask __unused) {
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int fegetexcept(void) {
+ return 0;
+}
+
+#undef FPSCR_RMODE_SHIFT
+
+__END_DECLS
+
+#endif
diff --git a/libc/include/bits/fenv_inlines_mips.h b/libc/include/bits/fenv_inlines_mips.h
new file mode 100644
index 0000000..dc7f707
--- /dev/null
+++ b/libc/include/bits/fenv_inlines_mips.h
@@ -0,0 +1,171 @@
+/*-
+ * 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.
+ *
+ * $FreeBSD: src/lib/msun/mips/fenv.c,v 1.1 2008/04/26 12:20:29 imp Exp $
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+
+#if defined(__mips__)
+
+#if !defined(__BIONIC_FENV_INLINE)
+#define __BIONIC_FENV_INLINE static __inline
+#endif
+
+#include <bits/fenv_mips.h>
+
+__BEGIN_DECLS
+
+#define FCSR_CAUSE_SHIFT 10
+#define FCSR_ENABLE_SHIFT 5
+#define FCSR_ENABLE_MASK (FE_ALL_EXCEPT << FCSR_ENABLE_SHIFT)
+
+#define FCSR_RMASK 0x3
+
+__BIONIC_FENV_INLINE int fegetenv(fenv_t* __envp) {
+ fenv_t _fcsr = 0;
+#ifdef __mips_hard_float
+ __asm__ __volatile__("cfc1 %0,$31" : "=r" (_fcsr));
+#endif
+ *__envp = _fcsr;
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int fesetenv(const fenv_t* __envp) {
+ fenv_t _fcsr = *__envp;
+#ifdef __mips_hard_float
+ __asm__ __volatile__("ctc1 %0,$31" : : "r" (_fcsr));
+#endif
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int feclearexcept(int __excepts) {
+ fexcept_t __fcsr;
+ fegetenv(&__fcsr);
+ __excepts &= FE_ALL_EXCEPT;
+ __fcsr &= ~(__excepts | (__excepts << FCSR_CAUSE_SHIFT));
+ fesetenv(&__fcsr);
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
+ fexcept_t __fcsr;
+ fegetenv(&__fcsr);
+ *__flagp = __fcsr & __excepts & FE_ALL_EXCEPT;
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
+ fexcept_t __fcsr;
+ fegetenv(&__fcsr);
+ /* Ensure that flags are all legal */
+ __excepts &= FE_ALL_EXCEPT;
+ __fcsr &= ~__excepts;
+ __fcsr |= *__flagp & __excepts;
+ fesetenv(&__fcsr);
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int feraiseexcept(int __excepts) {
+ fexcept_t __fcsr;
+ fegetenv(&__fcsr);
+ /* Ensure that flags are all legal */
+ __excepts &= FE_ALL_EXCEPT;
+ /* Cause bit needs to be set as well for generating the exception*/
+ __fcsr |= __excepts | (__excepts << FCSR_CAUSE_SHIFT);
+ fesetenv(&__fcsr);
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int fetestexcept(int __excepts) {
+ fexcept_t __FCSR;
+ fegetenv(&__FCSR);
+ return (__FCSR & __excepts & FE_ALL_EXCEPT);
+}
+
+__BIONIC_FENV_INLINE int fegetround(void) {
+ fenv_t _fcsr;
+ fegetenv(&_fcsr);
+ return (_fcsr & FCSR_RMASK);
+}
+
+__BIONIC_FENV_INLINE int fesetround(int __round) {
+ fenv_t _fcsr;
+ fegetenv(&_fcsr);
+ _fcsr &= ~FCSR_RMASK;
+ _fcsr |= (__round & FCSR_RMASK);
+ fesetenv(&_fcsr);
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int feholdexcept(fenv_t* __envp) {
+ fenv_t __env;
+ fegetenv(&__env);
+ *__envp = __env;
+ __env &= ~(FE_ALL_EXCEPT | FCSR_ENABLE_MASK);
+ fesetenv(&__env);
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int feupdateenv(const fenv_t* __envp) {
+ fexcept_t __fcsr;
+ fegetenv(&__fcsr);
+ fesetenv(__envp);
+ feraiseexcept(__fcsr & FE_ALL_EXCEPT);
+ return 0;
+}
+
+__BIONIC_FENV_INLINE int feenableexcept(int __mask) {
+ fenv_t __old_fcsr, __new_fcsr;
+ fegetenv(&__old_fcsr);
+ __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << FCSR_ENABLE_SHIFT;
+ fesetenv(&__new_fcsr);
+ return ((__old_fcsr >> FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
+}
+
+__BIONIC_FENV_INLINE int fedisableexcept(int __mask) {
+ fenv_t __old_fcsr, __new_fcsr;
+ fegetenv(&__old_fcsr);
+ __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << FCSR_ENABLE_SHIFT);
+ fesetenv(&__new_fcsr);
+ return ((__old_fcsr >> FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
+}
+
+__BIONIC_FENV_INLINE int fegetexcept(void) {
+ fenv_t __fcsr;
+ fegetenv(&__fcsr);
+ return ((__fcsr & FCSR_ENABLE_MASK) >> FCSR_ENABLE_SHIFT);
+}
+
+#undef FCSR_CAUSE_SHIFT
+#undef FCSR_ENABLE_SHIFT
+#undef FCSR_ENABLE_MASK
+#undef FCSR_RMASK
+
+__END_DECLS
+
+#endif
diff --git a/libc/include/bits/fenv_mips.h b/libc/include/bits/fenv_mips.h
index 9298e86..dafccac 100644
--- a/libc/include/bits/fenv_mips.h
+++ b/libc/include/bits/fenv_mips.h
@@ -68,8 +68,7 @@
* 11 - rounding (down)toward minus infinity (RM)
*/
-#ifndef _BITS_FENV_MIPS_H_
-#define _BITS_FENV_MIPS_H_
+#pragma once
#include <sys/types.h>
@@ -94,5 +93,3 @@
#define FE_DOWNWARD 0x0003
__END_DECLS
-
-#endif
diff --git a/libc/include/bits/fenv_x86.h b/libc/include/bits/fenv_x86.h
index 75b109b..3381cea 100644
--- a/libc/include/bits/fenv_x86.h
+++ b/libc/include/bits/fenv_x86.h
@@ -26,8 +26,7 @@
* $FreeBSD: src/lib/msun/i387/fenv.h,v 1.4 2005/03/17 22:21:46 das Exp $
*/
-#ifndef _BITS_FENV_X86_H_
-#define _BITS_FENV_X86_H_
+#pragma once
#include <sys/types.h>
@@ -65,5 +64,3 @@
#define FE_TOWARDZERO 0x0c00
__END_DECLS
-
-#endif
diff --git a/libc/include/bits/fenv_x86_64.h b/libc/include/bits/fenv_x86_64.h
index 006d19e..ddb6a5c 100644
--- a/libc/include/bits/fenv_x86_64.h
+++ b/libc/include/bits/fenv_x86_64.h
@@ -24,8 +24,7 @@
* SUCH DAMAGE.
*/
-#ifndef _BITS_FENV_X86_64_H_
-#define _BITS_FENV_X86_64_H_
+#pragma once
#include <sys/types.h>
@@ -91,5 +90,3 @@
typedef __uint32_t fexcept_t;
__END_DECLS
-
-#endif
diff --git a/libc/include/fenv.h b/libc/include/fenv.h
index 2b607f5..886612e 100644
--- a/libc/include/fenv.h
+++ b/libc/include/fenv.h
@@ -27,8 +27,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _FENV_H_
-#define _FENV_H_
+#pragma once
#include <sys/cdefs.h>
@@ -79,11 +78,12 @@
* environment, namely fesetenv() and feupdateenv().
*/
extern const fenv_t __fe_dfl_env;
-#define FE_DFL_ENV (&__fe_dfl_env)
+#define FE_DFL_ENV (&__fe_dfl_env)
__END_DECLS
+#if defined(__arm__)
#include <android/legacy_fenv_inlines_arm.h>
+#elif defined(__mips__)
#include <android/legacy_fenv_inlines_mips.h>
-
-#endif /* ! _FENV_H_ */
+#endif
diff --git a/libc/private/bionic_inline_raise.h b/libc/private/bionic_inline_raise.h
new file mode 100644
index 0000000..7223b4e
--- /dev/null
+++ b/libc/private/bionic_inline_raise.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+// An inline version of pthread_sigqueue(pthread_self(), ...), to reduce the number of
+// uninteresting stack frames at the top of a crash.
+static inline __always_inline void inline_raise(int sig, void* value = nullptr) {
+ // Protect ourselves against stale cached PID/TID values by fetching them via syscall.
+ // http://b/37769298
+ pid_t pid = syscall(__NR_getpid);
+ pid_t tid = syscall(__NR_gettid);
+ siginfo_t info = {};
+ info.si_code = SI_QUEUE;
+ info.si_pid = pid;
+ info.si_uid = getuid();
+ info.si_value.sival_ptr = value;
+
+#if defined(__arm__)
+ register long r0 __asm__("r0") = pid;
+ register long r1 __asm__("r1") = tid;
+ register long r2 __asm__("r2") = sig;
+ register long r3 __asm__("r3") = reinterpret_cast<long>(&info);
+ register long r7 __asm__("r7") = __NR_rt_tgsigqueueinfo;
+ __asm__("swi #0" : "=r"(r0) : "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r7) : "memory");
+#elif defined(__aarch64__)
+ register long x0 __asm__("x0") = pid;
+ register long x1 __asm__("x1") = tid;
+ register long x2 __asm__("x2") = sig;
+ register long x3 __asm__("x3") = reinterpret_cast<long>(&info);
+ register long x8 __asm__("x8") = __NR_rt_tgsigqueueinfo;
+ __asm__("svc #0" : "=r"(x0) : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8) : "memory");
+#else
+ syscall(__NR_rt_tgsigqueueinfo, pid, tid, sig, &info);
+#endif
+}
+
diff --git a/libm/Android.bp b/libm/Android.bp
index 3b88fa3..c0862c8 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -315,6 +315,8 @@
"upstream-freebsd/lib/msun/src/s_llrintf.c",
"upstream-freebsd/lib/msun/src/s_lrint.c",
"upstream-freebsd/lib/msun/src/s_lrintf.c",
+ "upstream-freebsd/lib/msun/src/s_nearbyintf.c",
+ "upstream-freebsd/lib/msun/src/s_nearbyint.c",
"upstream-freebsd/lib/msun/src/s_rint.c",
"upstream-freebsd/lib/msun/src/s_rintf.c",
"upstream-freebsd/lib/msun/src/s_round.c",
diff --git a/libm/arm/fenv.c b/libm/arm/fenv.c
index c988e4f..67c6456 100644
--- a/libm/arm/fenv.c
+++ b/libm/arm/fenv.c
@@ -1,126 +1,34 @@
-/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+/*
+ * Copyright (C) 2018 The Android Open Source Project
* 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
+ * * 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.
+ * * 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
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
- *
- * $FreeBSD: src/lib/msun/arm/fenv.c,v 1.1 2004/06/06 10:03:59 das Exp $
*/
#include <fenv.h>
-#define FPSCR_RMODE_SHIFT 22
+#define __BIONIC_FENV_INLINE /* Out of line. */
+#include <bits/fenv_inlines_arm.h>
const fenv_t __fe_dfl_env = 0;
-
-int fegetenv(fenv_t* __envp) {
- fenv_t _fpscr;
- __asm__ __volatile__("vmrs %0,fpscr" : "=r" (_fpscr));
- *__envp = _fpscr;
- return 0;
-}
-
-int fesetenv(const fenv_t* __envp) {
- fenv_t _fpscr = *__envp;
- __asm__ __volatile__("vmsr fpscr,%0" : :"ri" (_fpscr));
- return 0;
-}
-
-int feclearexcept(int __excepts) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- __fpscr &= ~__excepts;
- fesetenv(&__fpscr);
- return 0;
-}
-
-int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- *__flagp = __fpscr & __excepts;
- return 0;
-}
-
-int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- __fpscr &= ~__excepts;
- __fpscr |= *__flagp & __excepts;
- fesetenv(&__fpscr);
- return 0;
-}
-
-int feraiseexcept(int __excepts) {
- fexcept_t __ex = __excepts;
- fesetexceptflag(&__ex, __excepts);
- return 0;
-}
-
-int fetestexcept(int __excepts) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- return (__fpscr & __excepts);
-}
-
-int fegetround(void) {
- fenv_t _fpscr;
- fegetenv(&_fpscr);
- return ((_fpscr >> FPSCR_RMODE_SHIFT) & 0x3);
-}
-
-int fesetround(int __round) {
- fenv_t _fpscr;
- fegetenv(&_fpscr);
- _fpscr &= ~(0x3 << FPSCR_RMODE_SHIFT);
- _fpscr |= (__round << FPSCR_RMODE_SHIFT);
- fesetenv(&_fpscr);
- return 0;
-}
-
-int feholdexcept(fenv_t* __envp) {
- fenv_t __env;
- fegetenv(&__env);
- *__envp = __env;
- __env &= ~FE_ALL_EXCEPT;
- fesetenv(&__env);
- return 0;
-}
-
-int feupdateenv(const fenv_t* __envp) {
- fexcept_t __fpscr;
- fegetenv(&__fpscr);
- fesetenv(__envp);
- feraiseexcept(__fpscr & FE_ALL_EXCEPT);
- return 0;
-}
-
-int feenableexcept(int __mask __unused) {
- return -1;
-}
-
-int fedisableexcept(int __mask __unused) {
- return 0;
-}
-
-int fegetexcept(void) {
- return 0;
-}
diff --git a/libm/builtins.cpp b/libm/builtins.cpp
index 2ea6305..515b68a 100644
--- a/libm/builtins.cpp
+++ b/libm/builtins.cpp
@@ -57,4 +57,12 @@
float roundf(float x) { return __builtin_roundf(x); }
double round(double x) { return __builtin_round(x); }
+
+float nearbyintf(float x) { return __builtin_nearbyintf(x); }
+double nearbyint(double x) { return __builtin_nearbyint(x); }
+// msun s_nearbyint.c defines all floating-point version, so we need to
+// redefine the long double one here. For aarch64, clang/compiler-rt
+// soft-float routines does not use single/double floating-point operation,
+// so it should be safe to call rintl directly.
+long double nearbyintl(long double x) { return rintl(x); }
#endif
diff --git a/libm/mips/fenv.c b/libm/mips/fenv.c
index aacd526..f380b74 100644
--- a/libm/mips/fenv.c
+++ b/libm/mips/fenv.c
@@ -1,156 +1,34 @@
-/*-
- * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+/*
+ * Copyright (C) 2018 The Android Open Source Project
* 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
+ * * 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.
+ * * 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
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
- *
- * $FreeBSD: src/lib/msun/mips/fenv.c,v 1.1 2008/04/26 12:20:29 imp Exp $
*/
#include <fenv.h>
-#define FCSR_CAUSE_SHIFT 10
-#define FCSR_ENABLE_SHIFT 5
-#define FCSR_ENABLE_MASK (FE_ALL_EXCEPT << FCSR_ENABLE_SHIFT)
+#define __BIONIC_FENV_INLINE /* Out of line. */
+#include <bits/fenv_inlines_mips.h>
-#define FCSR_RMASK 0x3
-
-/*
- * Hopefully the system ID byte is immutable, so it's valid to use
- * this as a default environment.
- */
const fenv_t __fe_dfl_env = 0;
-
-int fegetenv(fenv_t* __envp) {
- fenv_t _fcsr = 0;
-#ifdef __mips_hard_float
- __asm__ __volatile__("cfc1 %0,$31" : "=r" (_fcsr));
-#endif
- *__envp = _fcsr;
- return 0;
-}
-
-int fesetenv(const fenv_t* __envp) {
- fenv_t _fcsr = *__envp;
-#ifdef __mips_hard_float
- __asm__ __volatile__("ctc1 %0,$31" : : "r" (_fcsr));
-#endif
- return 0;
-}
-
-int feclearexcept(int __excepts) {
- fexcept_t __fcsr;
- fegetenv(&__fcsr);
- __excepts &= FE_ALL_EXCEPT;
- __fcsr &= ~(__excepts | (__excepts << FCSR_CAUSE_SHIFT));
- fesetenv(&__fcsr);
- return 0;
-}
-
-int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
- fexcept_t __fcsr;
- fegetenv(&__fcsr);
- *__flagp = __fcsr & __excepts & FE_ALL_EXCEPT;
- return 0;
-}
-
-int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
- fexcept_t __fcsr;
- fegetenv(&__fcsr);
- /* Ensure that flags are all legal */
- __excepts &= FE_ALL_EXCEPT;
- __fcsr &= ~__excepts;
- __fcsr |= *__flagp & __excepts;
- fesetenv(&__fcsr);
- return 0;
-}
-
-int feraiseexcept(int __excepts) {
- fexcept_t __fcsr;
- fegetenv(&__fcsr);
- /* Ensure that flags are all legal */
- __excepts &= FE_ALL_EXCEPT;
- /* Cause bit needs to be set as well for generating the exception*/
- __fcsr |= __excepts | (__excepts << FCSR_CAUSE_SHIFT);
- fesetenv(&__fcsr);
- return 0;
-}
-
-int fetestexcept(int __excepts) {
- fexcept_t __FCSR;
- fegetenv(&__FCSR);
- return (__FCSR & __excepts & FE_ALL_EXCEPT);
-}
-
-int fegetround(void) {
- fenv_t _fcsr;
- fegetenv(&_fcsr);
- return (_fcsr & FCSR_RMASK);
-}
-
-int fesetround(int __round) {
- fenv_t _fcsr;
- fegetenv(&_fcsr);
- _fcsr &= ~FCSR_RMASK;
- _fcsr |= (__round & FCSR_RMASK);
- fesetenv(&_fcsr);
- return 0;
-}
-
-int feholdexcept(fenv_t* __envp) {
- fenv_t __env;
- fegetenv(&__env);
- *__envp = __env;
- __env &= ~(FE_ALL_EXCEPT | FCSR_ENABLE_MASK);
- fesetenv(&__env);
- return 0;
-}
-
-int feupdateenv(const fenv_t* __envp) {
- fexcept_t __fcsr;
- fegetenv(&__fcsr);
- fesetenv(__envp);
- feraiseexcept(__fcsr & FE_ALL_EXCEPT);
- return 0;
-}
-
-int feenableexcept(int __mask) {
- fenv_t __old_fcsr, __new_fcsr;
- fegetenv(&__old_fcsr);
- __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << FCSR_ENABLE_SHIFT;
- fesetenv(&__new_fcsr);
- return ((__old_fcsr >> FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
-}
-
-int fedisableexcept(int __mask) {
- fenv_t __old_fcsr, __new_fcsr;
- fegetenv(&__old_fcsr);
- __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << FCSR_ENABLE_SHIFT);
- fesetenv(&__new_fcsr);
- return ((__old_fcsr >> FCSR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
-}
-
-int fegetexcept(void) {
- fenv_t __fcsr;
- fegetenv(&__fcsr);
- return ((__fcsr & FCSR_ENABLE_MASK) >> FCSR_ENABLE_SHIFT);
-}
diff --git a/tests/Android.bp b/tests/Android.bp
index ccd1126..fa66f93 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -112,6 +112,7 @@
"netinet_ip_icmp_test.cpp",
"netinet_udp_test.cpp",
"nl_types_test.cpp",
+ "poll_test.cpp",
"pthread_test.cpp",
"pty_test.cpp",
"regex_test.cpp",
diff --git a/tests/poll_test.cpp b/tests/poll_test.cpp
new file mode 100644
index 0000000..2a3e5e0
--- /dev/null
+++ b/tests/poll_test.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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 <gtest/gtest.h>
+
+#include <errno.h>
+#include <poll.h>
+
+TEST(poll, poll_null_fds) {
+ // Because nanosleep(2) is relatively new to POSIX, code sometimes abuses poll.
+ errno = 0;
+ ASSERT_EQ(0, poll(nullptr, 0, 1));
+ ASSERT_EQ(0, errno);
+}
+
+TEST(poll, ppoll_null_fds) {
+ // Because nanosleep(2) is relatively new to POSIX, code sometimes abuses poll.
+ errno = 0;
+ timespec ts = { .tv_nsec = 100 };
+ ASSERT_EQ(0, ppoll(nullptr, 0, &ts, nullptr));
+ ASSERT_EQ(0, errno);
+}
+
+TEST(poll, ppoll64_null_fds) {
+#if __BIONIC__
+ // Because nanosleep(2) is relatively new to POSIX, code sometimes abuses poll.
+ errno = 0;
+ timespec ts = { .tv_nsec = 100 };
+ ASSERT_EQ(0, ppoll64(nullptr, 0, &ts, nullptr));
+ ASSERT_EQ(0, errno);
+#endif
+}