diff options
| author | 2018-07-11 15:14:10 +0100 | |
|---|---|---|
| committer | 2018-09-06 13:47:10 +0100 | |
| commit | f233136f2ca25316643b7f409df7af55a762f98a (patch) | |
| tree | a5aee0db607b4dc4d08e695426ebb74abcaabc35 /libartbase/base/utils.cc | |
| parent | 9999327c8fbcab1d57f609457d68085ddefb7eb7 (diff) | |
ART: Add FlushInstructionPipeline()
Use membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED), where available, to
flush CPU instruction pipelines after JIT code cache updates. This is
needed on architectures where TLB updates do not require a TLB
shootdown.
Bug: 65312375
Bug: 66095511
Bug: 111199492
Test: manual (requires kernel >= 4.16).
Change-Id: I96811c611133ba765a546a09432c0c951ad39e10
Diffstat (limited to 'libartbase/base/utils.cc')
| -rw-r--r-- | libartbase/base/utils.cc | 44 |
1 files changed, 44 insertions, 0 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 |