Commit 7a4c7813 authored by Delyan Kratunov's avatar Delyan Kratunov Committed by Noam Lerner

Make detail/Futex.cpp bionic-safe

Summary:
The headers that the Android NDK exports are all sorts of screwed up.
In particular, they expose a subset of the `futex.h`, so, even though the
kernel supports newer options, we can't reference them from the NDK headers.

This diff ensures Futex.cpp redefines all the things it uses, if the headers
are lacking.

It also transitions away from `SYS_` to `__NR_` which is apparently the newer
convention.

Lastly, the duration usage is made explicitly `time_t`-safe for use on 32-bit
platforms where `time_t` is `long int` but `std::chrono:seconds` is stored as
`long long int`.

Test Plan:
Existing tests, sample app compiled and ran cleanly on Android as well
(tests not verified on Android due to folly largely being unported to Android yet).

Reviewed By: ngbronson@fb.com

Subscribers: folly-diffs@, yfeldblum, chalfant

FB internal diff: D2069306

Signature: t1:2069306:1431721711:36c77b1afe8dd9259c1050f11a87511dcf7dd25f
parent fff701bf
...@@ -40,8 +40,24 @@ namespace { ...@@ -40,8 +40,24 @@ namespace {
#ifdef __linux__ #ifdef __linux__
/// Certain toolchains (like Android's) don't include the full futex API in
/// their headers even though they support it. Make sure we have our constants
/// even if the headers don't have them.
#ifndef FUTEX_WAIT_BITSET
# define FUTEX_WAIT_BITSET 9
#endif
#ifndef FUTEX_WAKE_BITSET
# define FUTEX_WAKE_BITSET 10
#endif
#ifndef FUTEX_PRIVATE_FLAG
# define FUTEX_PRIVATE_FLAG 128
#endif
#ifndef FUTEX_CLOCK_REALTIME
# define FUTEX_CLOCK_REALTIME 256
#endif
int nativeFutexWake(void* addr, int count, uint32_t wakeMask) { int nativeFutexWake(void* addr, int count, uint32_t wakeMask) {
int rv = syscall(SYS_futex, int rv = syscall(__NR_futex,
addr, /* addr1 */ addr, /* addr1 */
FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG, /* op */ FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG, /* op */
count, /* val */ count, /* val */
...@@ -58,13 +74,20 @@ template <class Clock> ...@@ -58,13 +74,20 @@ template <class Clock>
struct timespec struct timespec
timeSpecFromTimePoint(time_point<Clock> absTime) timeSpecFromTimePoint(time_point<Clock> absTime)
{ {
auto duration = absTime.time_since_epoch(); auto epoch = absTime.time_since_epoch();
if (duration.count() < 0) { if (epoch.count() < 0) {
// kernel timespec_valid requires non-negative seconds and nanos in [0,1G) // kernel timespec_valid requires non-negative seconds and nanos in [0,1G)
duration = Clock::duration::zero(); epoch = Clock::duration::zero();
} }
auto secs = duration_cast<seconds>(duration);
auto nanos = duration_cast<nanoseconds>(duration - secs); // timespec-safe seconds and nanoseconds;
// chrono::{nano,}seconds are `long long int`
// whereas timespec uses smaller types
using time_t_seconds = duration<std::time_t, seconds::period>;
using long_nanos = duration<long int, nanoseconds::period>;
auto secs = duration_cast<time_t_seconds>(epoch);
auto nanos = duration_cast<long_nanos>(epoch - secs);
struct timespec result = { secs.count(), nanos.count() }; struct timespec result = { secs.count(), nanos.count() };
return result; return result;
} }
...@@ -91,7 +114,7 @@ FutexResult nativeFutexWaitImpl(void* addr, ...@@ -91,7 +114,7 @@ FutexResult nativeFutexWaitImpl(void* addr,
// Unlike FUTEX_WAIT, FUTEX_WAIT_BITSET requires an absolute timeout // Unlike FUTEX_WAIT, FUTEX_WAIT_BITSET requires an absolute timeout
// value - http://locklessinc.com/articles/futex_cheat_sheet/ // value - http://locklessinc.com/articles/futex_cheat_sheet/
int rv = syscall(SYS_futex, int rv = syscall(__NR_futex,
addr, /* addr1 */ addr, /* addr1 */
op, /* op */ op, /* op */
expected, /* val */ expected, /* val */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment