summaryrefslogtreecommitdiff
path: root/libartbase/base/utils.cc
diff options
context:
space:
mode:
author Orion Hodson <oth@google.com> 2018-07-11 15:14:10 +0100
committer Orion Hodson <oth@google.com> 2018-09-06 13:47:10 +0100
commitf233136f2ca25316643b7f409df7af55a762f98a (patch)
treea5aee0db607b4dc4d08e695426ebb74abcaabc35 /libartbase/base/utils.cc
parent9999327c8fbcab1d57f609457d68085ddefb7eb7 (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.cc44
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