Merge "Document how to run the benchmarks."
diff --git a/libc/bionic/pthread_atfork.cpp b/libc/bionic/pthread_atfork.cpp
index 2200a6c..84e511c 100644
--- a/libc/bionic/pthread_atfork.cpp
+++ b/libc/bionic/pthread_atfork.cpp
@@ -130,13 +130,15 @@
}
void __bionic_atfork_run_child() {
+ g_atfork_list_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+
+ pthread_mutex_lock(&g_atfork_list_mutex);
g_atfork_list.walk_forward([](atfork_t* it) {
if (it->child != nullptr) {
it->child();
}
});
-
- g_atfork_list_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+ pthread_mutex_unlock(&g_atfork_list_mutex);
}
void __bionic_atfork_run_parent() {
diff --git a/libc/include/android/legacy_fenv_inlines_arm.h b/libc/include/android/legacy_fenv_inlines_arm.h
new file mode 100644
index 0000000..a5bb26b
--- /dev/null
+++ b/libc/include/android/legacy_fenv_inlines_arm.h
@@ -0,0 +1,154 @@
+/*-
+ * 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 $
+ */
+
+#ifndef ANDROID_LEGACY_FENV_INLINES_ARM_H
+#define ANDROID_LEGACY_FENV_INLINES_ARM_H
+
+#include <fenv.h>
+
+#if __ANDROID_API__ < 21 && defined(__arm__)
+
+__BEGIN_DECLS
+
+#define FPSCR_ENABLE_SHIFT 8
+#define FPSCR_ENABLE_MASK (FE_ALL_EXCEPT << FPSCR_ENABLE_SHIFT)
+
+#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 | FPSCR_ENABLE_MASK);
+ 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) {
+ fenv_t __old_fpscr, __new_fpscr;
+ fegetenv(&__old_fpscr);
+ __new_fpscr = __old_fpscr | (__mask & FE_ALL_EXCEPT) << FPSCR_ENABLE_SHIFT;
+ fesetenv(&__new_fpscr);
+ return ((__old_fpscr >> FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
+}
+
+static __inline int fedisableexcept(int __mask) {
+ fenv_t __old_fpscr, __new_fpscr;
+ fegetenv(&__old_fpscr);
+ __new_fpscr = __old_fpscr & ~((__mask & FE_ALL_EXCEPT) << FPSCR_ENABLE_SHIFT);
+ fesetenv(&__new_fpscr);
+ return ((__old_fpscr >> FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
+}
+
+static __inline int fegetexcept(void) {
+ fenv_t __fpscr;
+ fegetenv(&__fpscr);
+ return ((__fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT);
+}
+
+#undef FPSCR_ENABLE_SHIFT
+#undef FPSCR_ENABLE_MASK
+#undef FPSCR_RMODE_SHIFT
+
+__END_DECLS
+
+#endif /* __ANDROID_API__ < 21 && defined(__arm__) */
+
+#endif /* ANDROID_LEGACY_FENV_INLINES_ARM_H */
diff --git a/libc/include/android/legacy_fenv_inlines_mips.h b/libc/include/android/legacy_fenv_inlines_mips.h
new file mode 100644
index 0000000..ead697c
--- /dev/null
+++ b/libc/include/android/legacy_fenv_inlines_mips.h
@@ -0,0 +1,168 @@
+/*-
+ * 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 $
+ */
+
+#ifndef ANDROID_LEGACY_FENV_INLINES_MIPS_H
+#define ANDROID_LEGACY_FENV_INLINES_MIPS_H
+
+#include <fenv.h>
+
+#if __ANDROID_API__ < 21 && (defined(__mips__) && !defined(__LP64__))
+
+__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__ < 21 && (defined(__mips__) && !defined(__LP64__)) */
+
+#endif /* ANDROID_LEGACY_FENV_INLINES_MIPS_H */
diff --git a/libc/include/fenv.h b/libc/include/fenv.h
index f1b2b25..241e845 100644
--- a/libc/include/fenv.h
+++ b/libc/include/fenv.h
@@ -36,6 +36,7 @@
__BEGIN_DECLS
// fenv was always available on x86.
+#if __ANDROID_API__ >= 21 || defined(__i386__)
int feclearexcept(int) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_MIPS(21) __INTRODUCED_IN_X86(9);
int fegetexceptflag(fexcept_t*, int) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_MIPS(21)
__INTRODUCED_IN_X86(9);
@@ -56,6 +57,9 @@
int feenableexcept(int) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_MIPS(21) __INTRODUCED_IN_X86(9);
int fedisableexcept(int) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_MIPS(21) __INTRODUCED_IN_X86(9);
int fegetexcept(void) __INTRODUCED_IN_ARM(21) __INTRODUCED_IN_MIPS(21) __INTRODUCED_IN_X86(9);
+#else
+/* Defined as inlines for pre-21 ARM and MIPS. */
+#endif
/*
* The following constant represents the default floating-point environment
@@ -70,4 +74,7 @@
__END_DECLS
+#include <android/legacy_fenv_inlines_arm.h>
+#include <android/legacy_fenv_inlines_mips.h>
+
#endif /* ! _FENV_H_ */
diff --git a/libc/include/sys/limits.h b/libc/include/sys/limits.h
index 5aa3d80..60cc7f7 100644
--- a/libc/include/sys/limits.h
+++ b/libc/include/sys/limits.h
@@ -106,18 +106,12 @@
# endif
# endif
-/* Bionic: the following has been optimized out from our processed kernel headers */
-
-#define CHILD_MAX 999
-#define OPEN_MAX 256
-
/* Bionic-specific definitions */
#define _POSIX_VERSION 200809L /* Posix C language bindings version */
#define _POSIX2_VERSION -1 /* we don't support Posix command-line tools */
#define _XOPEN_VERSION 700 /* by Posix definition */
-
/* >= _POSIX_THREAD_DESTRUCTOR_ITERATIONS */
#define PTHREAD_DESTRUCTOR_ITERATIONS 4
/* >= _POSIX_THREAD_KEYS_MAX */
diff --git a/tests/gtest_main.cpp b/tests/gtest_main.cpp
index f2b7edd..aacf9ae 100644
--- a/tests/gtest_main.cpp
+++ b/tests/gtest_main.cpp
@@ -316,7 +316,7 @@
// PrettyUnitTestResultPrinter. The reason for copy is that PrettyUnitTestResultPrinter
// is defined and used in gtest.cc, which is hard to reuse.
static void OnTestIterationStartPrint(const std::vector<TestCase>& testcase_list, size_t iteration,
- int iteration_count) {
+ int iteration_count, size_t job_count) {
if (iteration_count != 1) {
printf("\nRepeating all tests (iteration %zu) . . .\n\n", iteration);
}
@@ -328,9 +328,10 @@
test_count += testcase.TestCount();
}
- printf("Running %zu %s from %zu %s.\n",
+ printf("Running %zu %s from %zu %s (%zu %s).\n",
test_count, (test_count == 1) ? "test" : "tests",
- testcase_count, (testcase_count == 1) ? "test case" : "test cases");
+ testcase_count, (testcase_count == 1) ? "test case" : "test cases",
+ job_count, (job_count == 1) ? "job" : "jobs");
fflush(stdout);
}
@@ -870,7 +871,7 @@
for (size_t iteration = 1;
iteration_count < 0 || iteration <= static_cast<size_t>(iteration_count);
++iteration) {
- OnTestIterationStartPrint(testcase_list, iteration, iteration_count);
+ OnTestIterationStartPrint(testcase_list, iteration, iteration_count, job_count);
int64_t iteration_start_time_ns = NanoTime();
time_t epoch_iteration_start_time = time(NULL);
diff --git a/tests/pthread_dlfcn_test.cpp b/tests/pthread_dlfcn_test.cpp
index 64423da..1c733fe 100644
--- a/tests/pthread_dlfcn_test.cpp
+++ b/tests/pthread_dlfcn_test.cpp
@@ -37,6 +37,11 @@
static void AtForkChild3() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 3; }
static void AtForkChild4() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 4; }
+static void* g_atfork_test_handle = nullptr;
+static void AtForkPrepare() {}
+static void AtForkParent() {}
+static void AtForkChild() { dlclose(g_atfork_test_handle); g_atfork_test_handle = dlopen("libtest_pthread_atfork.so", RTLD_NOW | RTLD_LOCAL); }
+
TEST(pthread, pthread_atfork_with_dlclose) {
ASSERT_EQ(0, pthread_atfork(AtForkPrepare1, AtForkParent1, AtForkChild1));
@@ -82,3 +87,28 @@
AssertChildExited(pid, 0);
}
+
+TEST(pthread, pthread_atfork_child_with_dlclose) {
+
+ g_atfork_test_handle = dlopen("libtest_pthread_atfork.so", RTLD_NOW | RTLD_LOCAL);
+ ASSERT_TRUE(g_atfork_test_handle != nullptr) << dlerror();
+ typedef int (*fn_t)(void (*)(void), void (*)(void), void (*)(void));
+ fn_t fn = reinterpret_cast<fn_t>(dlsym(g_atfork_test_handle, "proxy_pthread_atfork"));
+ ASSERT_TRUE(fn != nullptr) << dlerror();
+ // the library registers 2 additional atfork handlers in a constructor
+
+ ASSERT_EQ(0, pthread_atfork(AtForkPrepare, AtForkParent, AtForkChild));
+
+ pid_t pid = fork();
+
+ ASSERT_NE(-1, pid) << strerror(errno);
+
+ if (pid == 0) {
+ _exit(0);
+ }
+
+ AssertChildExited(pid, 0);
+
+ EXPECT_EQ(0, dlclose(g_atfork_test_handle));
+ g_atfork_test_handle = nullptr;
+}
diff --git a/tests/sys_prctl_test.cpp b/tests/sys_prctl_test.cpp
index 8fdd28f..205db86 100644
--- a/tests/sys_prctl_test.cpp
+++ b/tests/sys_prctl_test.cpp
@@ -53,7 +53,8 @@
ASSERT_EQ(2, sscanf(lines[i].c_str(), "%" SCNxPTR "-%" SCNxPTR " ", &start, &end))
<< "Failed to parse line: " << lines[i];
// This will never fail on the first line, so no need to do any special checking.
- ASSERT_GE(start, last_end) << "Overlapping map detected:\n" << lines[i -1] << lines[i];
+ ASSERT_GE(start, last_end)
+ << "Overlapping map detected:\n" << lines[i -1] << '\n' << lines[i] << '\n';
last_start = start;
last_end = end;
}