From d3b94042418ed7561efca31d2a460588ab1fc161 Mon Sep 17 00:00:00 2001 From: yusukes Date: Tue, 13 Feb 2018 18:28:50 -0800 Subject: [PATCH] Prevent WaitForProperty() from using ~100% of CPU time on 32bit builds Since 'struct timespec' members (time_t and long) are both 32bit on 32bit systems, and std::chrono::{seconds,nanoseconds}::rep are both >32bit, timespec members assigned in DurationToTimeSpec() can have a negative value, especially when WaitForProperty() is called with the default timeout value which is std::chrono::milliseconds::max(). Regarding functionality, passing a negative value to __system_property_wait() is okay because WaitForProperty() still waits for the property value (so unit tests are passing), but while WaitForProperty() does that, the function, to be more exact, SystemProperties::Wait() in bionic/, consumes ~100% of CPU time. This happens because SystemProperties::Wait() which implements __system_property_wait() has a tight while-loop with a __futex_wait() call, and the futex call immediately returns EINVAL when the timespec passed in has a negative value. With this CL, WaitForProperty() will never pass a negative timespec to __system_property_wait(), and therefore the __futex_wait() call in bionic works as expected without consuming too much CPU time even on 32bit systems. Bug: None Test: libbase_test32 still passes Test: strace no longer shows repeated EINVALs from __futex_wait Change-Id: Id1834fac8cd2876b02dbe4479bf3d3eda2fa7da1 --- base/properties.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/properties.cpp b/base/properties.cpp index cde4d69e3..ca8e96fc4 100644 --- a/base/properties.cpp +++ b/base/properties.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -109,7 +110,7 @@ static void WaitForPropertyCallback(void* data_ptr, const char*, const char* val static void DurationToTimeSpec(timespec& ts, const std::chrono::milliseconds d) { auto s = std::chrono::duration_cast(d); auto ns = std::chrono::duration_cast(d - s); - ts.tv_sec = s.count(); + ts.tv_sec = std::min(s.count(), std::numeric_limits::max()); ts.tv_nsec = ns.count(); }