[compiler-rt] r355416 - [scudo][standalone] Add bytemap classes
Kostya Kortchinsky via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 5 09:36:11 PST 2019
Author: cryptoad
Date: Tue Mar 5 09:36:11 2019
New Revision: 355416
URL: http://llvm.org/viewvc/llvm-project?rev=355416&view=rev
Log:
[scudo][standalone] Add bytemap classes
Summary:
The bytemap classes will be used by the primary32 allocator to associate
classes with memory regions. It's similar to the sanitizer_common one
except for the fact that the base (level1) maps are mapped instead of
being static to reduce the memory footprint of an uninitialized allocator.
Reviewers: vitalybuka, eugenis, morehouse, flowerhack, dmmoore415, mcgrathr
Reviewed By: vitalybuka, morehouse
Subscribers: mgorny, delcypher, jfb, #sanitizers, llvm-commits
Tags: #llvm, #sanitizers
Differential Revision: https://reviews.llvm.org/D58723
Added:
compiler-rt/trunk/lib/scudo/standalone/bytemap.h
compiler-rt/trunk/lib/scudo/standalone/tests/bytemap_test.cc
Modified:
compiler-rt/trunk/lib/scudo/standalone/CMakeLists.txt
compiler-rt/trunk/lib/scudo/standalone/tests/CMakeLists.txt
Modified: compiler-rt/trunk/lib/scudo/standalone/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/standalone/CMakeLists.txt?rev=355416&r1=355415&r2=355416&view=diff
==============================================================================
--- compiler-rt/trunk/lib/scudo/standalone/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/scudo/standalone/CMakeLists.txt Tue Mar 5 09:36:11 2019
@@ -40,6 +40,7 @@ set(SCUDO_SOURCES
set(SCUDO_HEADERS
atomic_helpers.h
+ bytemap.h
internal_defs.h
linux.h
list.h
Added: compiler-rt/trunk/lib/scudo/standalone/bytemap.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/standalone/bytemap.h?rev=355416&view=auto
==============================================================================
--- compiler-rt/trunk/lib/scudo/standalone/bytemap.h (added)
+++ compiler-rt/trunk/lib/scudo/standalone/bytemap.h Tue Mar 5 09:36:11 2019
@@ -0,0 +1,103 @@
+//===-- bytemap.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SCUDO_BYTEMAP_H_
+#define SCUDO_BYTEMAP_H_
+
+#include "atomic_helpers.h"
+#include "common.h"
+#include "mutex.h"
+
+namespace scudo {
+
+template <uptr Size> class FlatByteMap {
+public:
+ void initLinkerInitialized() {
+ Map = reinterpret_cast<u8 *>(map(nullptr, Size, "scudo:bytemap"));
+ }
+ void init() { initLinkerInitialized(); }
+
+ void set(uptr Index, u8 Value) {
+ DCHECK_LT(Index, Size);
+ DCHECK_EQ(0U, Map[Index]);
+ Map[Index] = Value;
+ }
+ u8 operator[](uptr Index) {
+ DCHECK_LT(Index, Size);
+ return Map[Index];
+ }
+
+private:
+ u8 *Map;
+};
+
+template <uptr Level1Size, uptr Level2Size> class TwoLevelByteMap {
+public:
+ void initLinkerInitialized() {
+ Level1Map = reinterpret_cast<atomic_uptr *>(
+ map(nullptr, sizeof(atomic_uptr) * Level1Size, "scudo:bytemap"));
+ }
+ void init() {
+ initLinkerInitialized();
+ Mutex.init();
+ }
+
+ void reset() {
+ for (uptr I = 0; I < Level1Size; I++) {
+ u8 *P = get(I);
+ if (!P)
+ continue;
+ unmap(P, Level2Size);
+ }
+ memset(Level1Map, 0, sizeof(atomic_uptr) * Level1Size);
+ }
+
+ uptr size() const { return Level1Size * Level2Size; }
+
+ void set(uptr Index, u8 Value) {
+ DCHECK_LT(Index, Level1Size * Level2Size);
+ u8 *Level2Map = getOrCreate(Index / Level2Size);
+ DCHECK_EQ(0U, Level2Map[Index % Level2Size]);
+ Level2Map[Index % Level2Size] = Value;
+ }
+
+ u8 operator[](uptr Index) const {
+ DCHECK_LT(Index, Level1Size * Level2Size);
+ u8 *Level2Map = get(Index / Level2Size);
+ if (!Level2Map)
+ return 0;
+ return Level2Map[Index % Level2Size];
+ }
+
+private:
+ u8 *get(uptr Index) const {
+ DCHECK_LT(Index, Level1Size);
+ return reinterpret_cast<u8 *>(
+ atomic_load(&Level1Map[Index], memory_order_acquire));
+ }
+
+ u8 *getOrCreate(uptr Index) {
+ u8 *Res = get(Index);
+ if (!Res) {
+ SpinMutexLock L(&Mutex);
+ if (!(Res = get(Index))) {
+ Res = reinterpret_cast<u8 *>(map(nullptr, Level2Size, "scudo:bytemap"));
+ atomic_store(&Level1Map[Index], reinterpret_cast<uptr>(Res),
+ memory_order_release);
+ }
+ }
+ return Res;
+ }
+
+ atomic_uptr *Level1Map;
+ StaticSpinMutex Mutex;
+};
+
+} // namespace scudo
+
+#endif // SCUDO_BYTEMAP_H_
Modified: compiler-rt/trunk/lib/scudo/standalone/tests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/standalone/tests/CMakeLists.txt?rev=355416&r1=355415&r2=355416&view=diff
==============================================================================
--- compiler-rt/trunk/lib/scudo/standalone/tests/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/scudo/standalone/tests/CMakeLists.txt Tue Mar 5 09:36:11 2019
@@ -50,6 +50,7 @@ endmacro()
set(SCUDO_UNIT_TEST_SOURCES
atomic_test.cc
+ bytemap_test.cc
list_test.cc
map_test.cc
mutex_test.cc
Added: compiler-rt/trunk/lib/scudo/standalone/tests/bytemap_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/standalone/tests/bytemap_test.cc?rev=355416&view=auto
==============================================================================
--- compiler-rt/trunk/lib/scudo/standalone/tests/bytemap_test.cc (added)
+++ compiler-rt/trunk/lib/scudo/standalone/tests/bytemap_test.cc Tue Mar 5 09:36:11 2019
@@ -0,0 +1,73 @@
+//===-- bytemap_test.cc------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "bytemap.h"
+
+#include "gtest/gtest.h"
+
+#include <string.h>
+
+template <typename T> void testMap(T &Map, scudo::uptr Size) {
+ Map.init();
+ for (scudo::uptr I = 0; I < Size; I += 7)
+ Map.set(I, (I % 100) + 1);
+ for (scudo::uptr J = 0; J < Size; J++) {
+ if (J % 7)
+ EXPECT_EQ(Map[J], 0);
+ else
+ EXPECT_EQ(Map[J], (J % 100) + 1);
+ }
+}
+
+TEST(ScudoByteMapTest, FlatByteMap) {
+ const scudo::uptr Size = 1U << 10;
+ scudo::FlatByteMap<Size> Map;
+ testMap(Map, Size);
+}
+
+TEST(ScudoByteMapTest, TwoLevelByteMap) {
+ const scudo::uptr Size1 = 1U << 6, Size2 = 1U << 12;
+ scudo::TwoLevelByteMap<Size1, Size2> Map;
+ testMap(Map, Size1 * Size2);
+ Map.reset();
+}
+
+using TestByteMap = scudo::TwoLevelByteMap<1U << 12, 1U << 13>;
+
+struct TestByteMapParam {
+ TestByteMap *Map;
+ scudo::uptr Shard;
+ scudo::uptr NumberOfShards;
+};
+
+void *populateByteMap(void *Param) {
+ TestByteMapParam *P = reinterpret_cast<TestByteMapParam *>(Param);
+ for (scudo::uptr I = P->Shard; I < P->Map->size(); I += P->NumberOfShards) {
+ scudo::u8 V = static_cast<scudo::u8>((I % 100) + 1);
+ P->Map->set(I, V);
+ EXPECT_EQ((*P->Map)[I], V);
+ }
+ return 0;
+}
+
+TEST(ScudoByteMapTest, ThreadedTwoLevelByteMap) {
+ TestByteMap Map;
+ Map.init();
+ static const scudo::uptr NumberOfThreads = 16U;
+ pthread_t T[NumberOfThreads];
+ TestByteMapParam P[NumberOfThreads];
+ for (scudo::uptr I = 0; I < NumberOfThreads; I++) {
+ P[I].Map = ⤅
+ P[I].Shard = I;
+ P[I].NumberOfShards = NumberOfThreads;
+ pthread_create(&T[I], 0, populateByteMap, &P[I]);
+ }
+ for (scudo::uptr I = 0; I < NumberOfThreads; I++)
+ pthread_join(T[I], 0);
+ Map.reset();
+}
More information about the llvm-commits
mailing list