summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/sanitizer_common/sanitizer_runtime_select_allocator.h
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt/lib/sanitizer_common/sanitizer_runtime_select_allocator.h')
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_runtime_select_allocator.h179
1 files changed, 179 insertions, 0 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_runtime_select_allocator.h b/compiler-rt/lib/sanitizer_common/sanitizer_runtime_select_allocator.h
new file mode 100644
index 00000000000..3b9e3544598
--- /dev/null
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_runtime_select_allocator.h
@@ -0,0 +1,179 @@
+//===-- sanitizer_runtime_select_allocator.h --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Select one of the two allocators at runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SANITIZER_RUNTIME_SELECT_ALLOCATOR_H
+#define SANITIZER_RUNTIME_SELECT_ALLOCATOR_H
+
+template <class Allocator1, class Allocator2>
+class RuntimeSelectAllocator {
+ Allocator1 a1;
+ Allocator2 a2;
+
+ public:
+ bool use_first_allocator;
+
+ class RuntimeSelectAllocatorCache {
+ typename Allocator1::AllocatorCache a1;
+ typename Allocator2::AllocatorCache a2;
+
+ public:
+ void Init(AllocatorGlobalStats *s) {
+ if (this->use_first_allocator)
+ a1.Init(s);
+ else
+ a2.Init(s);
+ }
+ void *Allocate(RuntimeSelectAllocator *allocator, uptr class_id) {
+ if (allocator->use_first_allocator)
+ return a1.Allocate(&allocator->a1, class_id);
+ return a2.Allocate(&allocator->a2, class_id);
+ }
+
+ void Deallocate(RuntimeSelectAllocator *allocator, uptr class_id, void *p) {
+ if (allocator->use_first_allocator)
+ a1.Deallocate(&allocator->a1, class_id, p);
+ else
+ a2.Deallocate(&allocator->a2, class_id, p);
+ }
+
+ void Drain(RuntimeSelectAllocator *allocator) {
+ if (allocator->use_first_allocator)
+ a1.Drain(&allocator->a1);
+ else
+ a2.Drain(&allocator->a2);
+ }
+
+ void Destroy(RuntimeSelectAllocator *allocator, AllocatorGlobalStats *s) {
+ if (allocator->use_first_allocator)
+ a1.Destroy(&allocator->a1, s);
+ else
+ a2.Destroy(&allocator->a2, s);
+ }
+ };
+
+ using MapUnmapCallback = typename Allocator1::MapUnmapCallback;
+ using AddressSpaceView = typename Allocator1::AddressSpaceView;
+ using AllocatorCache = RuntimeSelectAllocatorCache;
+
+ void Init(s32 release_to_os_interval_ms) {
+ // Use the first allocator when the address
+ // space is too small for the 64-bit allocator.
+ use_first_allocator = GetMaxVirtualAddress() < (((uptr)1ULL << 48) - 1);
+ if (use_first_allocator)
+ a1.Init(release_to_os_interval_ms);
+ else
+ a2.Init(release_to_os_interval_ms);
+ }
+
+ bool CanAllocate(uptr size, uptr alignment) {
+ if (use_first_allocator)
+ return Allocator1::CanAllocate(size, alignment);
+ return Allocator2::CanAllocate(size, alignment);
+ }
+
+ uptr ClassID(uptr size) {
+ if (use_first_allocator)
+ return Allocator1::ClassID(size);
+ return Allocator2::ClassID(size);
+ }
+
+ uptr KNumClasses() {
+ if (use_first_allocator)
+ return Allocator1::KNumClasses();
+ return Allocator2::KNumClasses();
+ }
+
+ uptr KMaxSize() {
+ if (use_first_allocator)
+ return Allocator1::KMaxSize();
+ return Allocator2::KMaxSize();
+ }
+
+ bool PointerIsMine(const void *p) {
+ if (use_first_allocator)
+ return a1.PointerIsMine(p);
+ return a2.PointerIsMine(p);
+ }
+
+ void *GetMetaData(const void *p) {
+ if (use_first_allocator)
+ return a1.GetMetaData(p);
+ return a2.GetMetaData(p);
+ }
+
+ uptr GetSizeClass(const void *p) {
+ if (use_first_allocator)
+ return a1.GetSizeClass(p);
+ return a2.GetSizeClass(p);
+ }
+
+ void ForEachChunk(ForEachChunkCallback callback, void *arg) {
+ if (use_first_allocator)
+ a1.ForEachChunk(callback, arg);
+ else
+ a2.ForEachChunk(callback, arg);
+ }
+
+ void TestOnlyUnmap() {
+ if (use_first_allocator)
+ a1.TestOnlyUnmap();
+ else
+ a2.TestOnlyUnmap();
+ }
+ void ForceLock() {
+ if (use_first_allocator)
+ a1.ForceLock();
+ else
+ a2.ForceLock();
+ }
+ void ForceUnlock() {
+ if (use_first_allocator)
+ a1.ForceUnlock();
+ else
+ a2.ForceUnlock();
+ }
+ void *GetBlockBegin(const void *p) {
+ if (use_first_allocator)
+ return a1.GetBlockBegin(p);
+ return a2.GetBlockBegin(p);
+ }
+ uptr GetActuallyAllocatedSize(void *p) {
+ if (use_first_allocator)
+ return a1.GetActuallyAllocatedSize(p);
+ return a2.GetActuallyAllocatedSize(p);
+ }
+ void SetReleaseToOSIntervalMs(s32 release_to_os_interval_ms) {
+ if (use_first_allocator)
+ a1.SetReleaseToOSIntervalMs(release_to_os_interval_ms);
+ else
+ a2.SetReleaseToOSIntervalMs(release_to_os_interval_ms);
+ }
+ s32 ReleaseToOSIntervalMs() const {
+ if (use_first_allocator)
+ return a1.ReleaseToOSIntervalMs();
+ return a2.ReleaseToOSIntervalMs();
+ }
+ void ForceReleaseToOS() {
+ if (use_first_allocator)
+ a1.ForceReleaseToOS();
+ else
+ a2.ForceReleaseToOS();
+ }
+ void PrintStats() {
+ if (use_first_allocator)
+ a1.PrintStats();
+ else
+ a2.PrintStats();
+ }
+};
+
+#endif // SANITIZER_RUNTIME_SELECT_ALLOCATOR_H
OpenPOWER on IntegriCloud