diff options
Diffstat (limited to 'libartbase')
| -rw-r--r-- | libartbase/base/utils.cc | 44 | ||||
| -rw-r--r-- | libartbase/base/utils.h | 11 |
2 files changed, 51 insertions, 4 deletions
diff --git a/libartbase/base/utils.cc b/libartbase/base/utils.cc index 761c6113d6..74cc5b97b2 100644 --- a/libartbase/base/utils.cc +++ b/libartbase/base/utils.cc @@ -38,6 +38,12 @@ #include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED #endif +#if defined(__BIONIC__) +// membarrier(2) is only supported for target builds (b/111199492). +#include <linux/membarrier.h> +#include <sys/syscall.h> +#endif + #if defined(__linux__) #include <linux/unistd.h> #endif @@ -207,4 +213,42 @@ void SleepForever() { } } +bool FlushInstructionPipeline() { + // membarrier(2) is only supported for target builds (b/111199492). +#if defined(__BIONIC__) + static constexpr int kSyncCoreMask = + MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE | + MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE; + static bool have_probed = false; + static bool have_sync_core = false; + + if (UNLIKELY(!have_probed)) { + // Probe membarrier(2) commands supported by kernel. + int commands = syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0); + if (commands >= 0) { + have_sync_core = (commands & kSyncCoreMask) == kSyncCoreMask; + if (have_sync_core) { + // Register with kernel that we'll be using the private expedited sync core command. + CheckedCall(syscall, + "membarrier register sync core", + __NR_membarrier, + MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE, + 0); + } + } + have_probed = true; + } + + if (have_sync_core) { + CheckedCall(syscall, + "membarrier sync core", + __NR_membarrier, + MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE, + 0); + return true; + } +#endif // defined(__BIONIC__) + return false; +} + } // namespace art diff --git a/libartbase/base/utils.h b/libartbase/base/utils.h index ba61e1b0a3..44499415f8 100644 --- a/libartbase/base/utils.h +++ b/libartbase/base/utils.h @@ -179,16 +179,19 @@ static T GetRandomNumber(T min, T max) { // Sleep forever and never come back. NO_RETURN void SleepForever(); -inline void FlushInstructionCache(char* begin, char* end) { - __builtin___clear_cache(begin, end); -} - inline void FlushDataCache(char* begin, char* end) { // Same as FlushInstructionCache for lack of other builtin. __builtin___clear_cache // flushes both caches. __builtin___clear_cache(begin, end); } +inline void FlushInstructionCache(char* begin, char* end) { + __builtin___clear_cache(begin, end); +} + +// Flush instruction pipeline. Returns true on success, false if feature is unsupported. +bool FlushInstructionPipeline(); + template <typename T> constexpr PointerSize ConvertToPointerSize(T any) { if (any == 4 || any == 8) { |