Merge "Name function arguments in libc headers for Studio."
diff --git a/libc/Android.bp b/libc/Android.bp
index b0e0d8c..42d0914 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1399,6 +1399,7 @@
"bionic/assert.cpp",
"bionic/atof.cpp",
"bionic/bionic_arc4random.cpp",
+ "bionic/bionic_futex.cpp",
"bionic/bionic_netlink.cpp",
"bionic/bionic_systrace.cpp",
"bionic/bionic_time_conversions.cpp",
diff --git a/libc/bionic/__cxa_guard.cpp b/libc/bionic/__cxa_guard.cpp
index 06926df..30b5f41 100644
--- a/libc/bionic/__cxa_guard.cpp
+++ b/libc/bionic/__cxa_guard.cpp
@@ -104,7 +104,7 @@
}
}
- __futex_wait_ex(&gv->state, false, CONSTRUCTION_UNDERWAY_WITH_WAITER, false, nullptr);
+ __futex_wait_ex(&gv->state, false, CONSTRUCTION_UNDERWAY_WITH_WAITER);
old_value = atomic_load_explicit(&gv->state, memory_order_acquire);
}
}
diff --git a/libc/bionic/bionic_futex.cpp b/libc/bionic/bionic_futex.cpp
new file mode 100644
index 0000000..dd66e40
--- /dev/null
+++ b/libc/bionic/bionic_futex.cpp
@@ -0,0 +1,59 @@
+/*
+ * 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 "private/bionic_futex.h"
+
+#include <time.h>
+
+#include "private/bionic_time_conversions.h"
+
+int __futex_wait_ex(volatile void* ftx, bool shared, int value, bool use_realtime_clock,
+ const timespec* abs_timeout) {
+ const timespec* futex_abs_timeout = abs_timeout;
+ // pthread's and semaphore's default behavior is to use CLOCK_REALTIME, however this behavior is
+ // essentially never intended, as that clock is prone to change discontinuously.
+ //
+ // What users really intend is to use CLOCK_MONOTONIC, however only pthread_cond_timedwait()
+ // provides this as an option and even there, a large amount of existing code does not opt into
+ // CLOCK_MONOTONIC.
+ //
+ // We have seen numerous bugs directly attributable to this difference. Therefore, we provide
+ // this general workaround to always use CLOCK_MONOTONIC for waiting, regardless of what the input
+ // timespec is.
+ timespec converted_monotonic_abs_timeout;
+ if (abs_timeout && use_realtime_clock) {
+ monotonic_time_from_realtime_time(converted_monotonic_abs_timeout, *abs_timeout);
+ if (converted_monotonic_abs_timeout.tv_sec < 0) {
+ return -ETIMEDOUT;
+ }
+ futex_abs_timeout = &converted_monotonic_abs_timeout;
+ }
+
+ return __futex(ftx, (shared ? FUTEX_WAIT_BITSET : FUTEX_WAIT_BITSET_PRIVATE), value,
+ futex_abs_timeout, FUTEX_BITSET_MATCH_ANY);
+}
diff --git a/libc/bionic/bionic_time_conversions.cpp b/libc/bionic/bionic_time_conversions.cpp
index ade3a55..d21e12e 100644
--- a/libc/bionic/bionic_time_conversions.cpp
+++ b/libc/bionic/bionic_time_conversions.cpp
@@ -51,3 +51,24 @@
tv.tv_sec = ts.tv_sec;
tv.tv_usec = ts.tv_nsec / 1000;
}
+
+void monotonic_time_from_realtime_time(timespec& monotonic_time, const timespec& realtime_time) {
+ monotonic_time = realtime_time;
+
+ timespec cur_monotonic_time;
+ clock_gettime(CLOCK_MONOTONIC, &cur_monotonic_time);
+ timespec cur_realtime_time;
+ clock_gettime(CLOCK_REALTIME, &cur_realtime_time);
+
+ monotonic_time.tv_nsec -= cur_realtime_time.tv_nsec;
+ monotonic_time.tv_nsec += cur_monotonic_time.tv_nsec;
+ if (monotonic_time.tv_nsec >= NS_PER_S) {
+ monotonic_time.tv_nsec -= NS_PER_S;
+ monotonic_time.tv_sec += 1;
+ } else if (monotonic_time.tv_nsec < 0) {
+ monotonic_time.tv_nsec += NS_PER_S;
+ monotonic_time.tv_sec -= 1;
+ }
+ monotonic_time.tv_sec -= cur_realtime_time.tv_sec;
+ monotonic_time.tv_sec += cur_monotonic_time.tv_sec;
+}
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 71d8426..58eebc5 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -239,9 +239,18 @@
#define __BIONIC_FORTIFY_UNKNOWN_SIZE ((size_t) -1)
-#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && \
- (defined(__clang__) || (defined(__OPTIMIZE__) && __OPTIMIZE__ > 0))
-# define __BIONIC_FORTIFY 1
+#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
+# if defined(__clang__)
+/* FORTIFY's _chk functions effectively disable ASAN's stdlib interceptors. */
+# if !__has_feature(address_sanitizer)
+# define __BIONIC_FORTIFY 1
+# endif
+# elif defined(__OPTIMIZE__) && __OPTIMIZE__ > 0
+# define __BIONIC_FORTIFY 1
+# endif
+#endif
+
+#if defined(__BIONIC_FORTIFY)
# if _FORTIFY_SOURCE == 2
# define __bos_level 1
# else
diff --git a/libc/private/bionic_futex.h b/libc/private/bionic_futex.h
index 946d9dd..9b89131 100644
--- a/libc/private/bionic_futex.h
+++ b/libc/private/bionic_futex.h
@@ -36,13 +36,10 @@
#include <sys/syscall.h>
#include <unistd.h>
-__BEGIN_DECLS
-
struct timespec;
static inline __always_inline int __futex(volatile void* ftx, int op, int value,
- const struct timespec* timeout,
- int bitset) {
+ const timespec* timeout, int bitset) {
// Our generated syscall assembler sets errno, but our callers (pthread functions) don't want to.
int saved_errno = errno;
int result = syscall(__NR_futex, ftx, op, value, timeout, NULL, bitset);
@@ -61,17 +58,16 @@
return __futex(ftx, shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, count, NULL, 0);
}
-static inline int __futex_wait(volatile void* ftx, int value, const struct timespec* timeout) {
+static inline int __futex_wait(volatile void* ftx, int value, const timespec* timeout) {
return __futex(ftx, FUTEX_WAIT, value, timeout, 0);
}
-static inline int __futex_wait_ex(volatile void* ftx, bool shared, int value,
- bool use_realtime_clock, const struct timespec* abs_timeout) {
- return __futex(ftx, (shared ? FUTEX_WAIT_BITSET : FUTEX_WAIT_BITSET_PRIVATE) |
- (use_realtime_clock ? FUTEX_CLOCK_REALTIME : 0), value, abs_timeout,
+static inline int __futex_wait_ex(volatile void* ftx, bool shared, int value) {
+ return __futex(ftx, (shared ? FUTEX_WAIT_BITSET : FUTEX_WAIT_BITSET_PRIVATE), value, nullptr,
FUTEX_BITSET_MATCH_ANY);
}
-__END_DECLS
+__LIBC_HIDDEN__ int __futex_wait_ex(volatile void* ftx, bool shared, int value,
+ bool use_realtime_clock, const timespec* abs_timeout);
#endif /* _BIONIC_FUTEX_H */
diff --git a/libc/private/bionic_lock.h b/libc/private/bionic_lock.h
index 3dbafe0..b389247 100644
--- a/libc/private/bionic_lock.h
+++ b/libc/private/bionic_lock.h
@@ -64,7 +64,7 @@
}
while (atomic_exchange_explicit(&state, LockedWithWaiter, memory_order_acquire) != Unlocked) {
// TODO: As the critical section is brief, it is a better choice to spin a few times befor sleeping.
- __futex_wait_ex(&state, process_shared, LockedWithWaiter, false, nullptr);
+ __futex_wait_ex(&state, process_shared, LockedWithWaiter);
}
return;
}
diff --git a/libc/private/bionic_time_conversions.h b/libc/private/bionic_time_conversions.h
index b9eaad2..fb049f2 100644
--- a/libc/private/bionic_time_conversions.h
+++ b/libc/private/bionic_time_conversions.h
@@ -42,6 +42,9 @@
__LIBC_HIDDEN__ void timeval_from_timespec(timeval& tv, const timespec& ts);
+__LIBC_HIDDEN__ void monotonic_time_from_realtime_time(timespec& monotonic_time,
+ const timespec& realtime_time);
+
__END_DECLS
static inline int check_timespec(const timespec* ts, bool null_allowed) {
diff --git a/tests/Android.bp b/tests/Android.bp
index 084d393..ea3f39f 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -192,6 +192,26 @@
},
}
+// If building this fails, then we have both FORTIFY and ASAN enabled, which
+// isn't desirable. (Ideally, we'd emit FORTIFY diagnostics even with ASAN
+// enabled, but that's not a reality today.) This is meant to be otherwise
+// unused.
+cc_test_library {
+ name: "fortify_disabled_for_asan",
+ cflags: [
+ "-Werror",
+ "-D_FORTIFY_SOURCE=2",
+ // "sanitize: address" doesn't work on platforms where libasan isn't
+ // enabled. Since the intent is just to build this, we can get away with
+ // passing this flag on its own.
+ "-fsanitize=address",
+ ],
+ // Ignore that we don't have ASAN symbols linked in.
+ allow_undefined_symbols: true,
+ srcs: ["fortify_compilation_test.cpp"],
+ clang: true,
+}
+
cc_test_library {
name: "libfortify1-tests-clang",
defaults: ["bionic_fortify_tests_defaults", "bionic_tests_defaults"],