summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/scudo
diff options
context:
space:
mode:
authorKostya Kortchinsky <kostyak@google.com>2019-10-28 09:25:04 -0700
committerMitch Phillips <31459023+hctim@users.noreply.github.com>2019-10-28 09:34:36 -0700
commit6f2de9cbb37fa53029ad861204366e87cce8fcb1 (patch)
tree0633f5f63167ea3cd0059c40515c77ff7dada782 /compiler-rt/lib/scudo
parent93a3128a67cc4372696eb3199bed23d7bac4a183 (diff)
downloadbcm5719-llvm-6f2de9cbb37fa53029ad861204366e87cce8fcb1.tar.gz
bcm5719-llvm-6f2de9cbb37fa53029ad861204366e87cce8fcb1.zip
[scudo][standalone] Consolidate lists
Summary: This is a clean patch using the last diff of D69265, but using git instead of svn, since svn went ro and arc was making my life harded than it needed to be. I was going to introduce a couple more lists and realized that our lists are currently a bit all over the place. While we have a singly linked list type relatively well defined, we are using doubly linked lists defined on the fly for the stats and for the secondary blocks. This CL adds a doubly linked list object, reorganizing the singly list one to extract as much of the common code as possible. We use this new type in the stats and the secondary. We also reorganize the list tests to benefit from this consolidation. There are a few side effect changes such as using for iterator loops that are, in my opinion, cleaner in a couple of places. Reviewers: hctim, morehouse, pcc, cferris Reviewed By: hctim Subscribers: jfb, #sanitizers, llvm-commits Tags: #sanitizers, #llvm Differential Revision: https://reviews.llvm.org/D69516
Diffstat (limited to 'compiler-rt/lib/scudo')
-rw-r--r--compiler-rt/lib/scudo/standalone/list.h235
-rw-r--r--compiler-rt/lib/scudo/standalone/primary32.h4
-rw-r--r--compiler-rt/lib/scudo/standalone/primary64.h4
-rw-r--r--compiler-rt/lib/scudo/standalone/quarantine.h2
-rw-r--r--compiler-rt/lib/scudo/standalone/release.h14
-rw-r--r--compiler-rt/lib/scudo/standalone/secondary.cpp23
-rw-r--r--compiler-rt/lib/scudo/standalone/secondary.h7
-rw-r--r--compiler-rt/lib/scudo/standalone/stats.h32
-rw-r--r--compiler-rt/lib/scudo/standalone/tests/list_test.cpp104
-rw-r--r--compiler-rt/lib/scudo/standalone/tests/release_test.cpp4
10 files changed, 243 insertions, 186 deletions
diff --git a/compiler-rt/lib/scudo/standalone/list.h b/compiler-rt/lib/scudo/standalone/list.h
index 6a7b9bd747a..ca5b3167ab0 100644
--- a/compiler-rt/lib/scudo/standalone/list.h
+++ b/compiler-rt/lib/scudo/standalone/list.h
@@ -13,43 +13,93 @@
namespace scudo {
-// Intrusive POD singly-linked list.
+// Intrusive POD singly and doubly linked list.
// An object with all zero fields should represent a valid empty list. clear()
// should be called on all non-zero-initialized objects before using.
-template <class Item> struct IntrusiveList {
- friend class Iterator;
+
+template <class T> class IteratorBase {
+public:
+ explicit IteratorBase(T *CurrentT) : Current(CurrentT) {}
+ IteratorBase &operator++() {
+ Current = Current->Next;
+ return *this;
+ }
+ bool operator!=(IteratorBase Other) const { return Current != Other.Current; }
+ T &operator*() { return *Current; }
+
+private:
+ T *Current;
+};
+
+template <class T> struct IntrusiveList {
+ bool empty() const { return Size == 0; }
+ uptr size() const { return Size; }
+
+ T *front() { return First; }
+ const T *front() const { return First; }
+ T *back() { return Last; }
+ const T *back() const { return Last; }
void clear() {
First = Last = nullptr;
Size = 0;
}
- bool empty() const { return Size == 0; }
- uptr size() const { return Size; }
+ typedef IteratorBase<T> Iterator;
+ typedef IteratorBase<const T> ConstIterator;
- void push_back(Item *X) {
- if (empty()) {
- X->Next = nullptr;
- First = Last = X;
- Size = 1;
- } else {
- X->Next = nullptr;
- Last->Next = X;
- Last = X;
- Size++;
+ Iterator begin() { return Iterator(First); }
+ Iterator end() { return Iterator(nullptr); }
+
+ ConstIterator begin() const { return ConstIterator(First); }
+ ConstIterator end() const { return ConstIterator(nullptr); }
+
+ void checkConsistency() const;
+
+protected:
+ uptr Size;
+ T *First;
+ T *Last;
+};
+
+template <class T> void IntrusiveList<T>::checkConsistency() const {
+ if (Size == 0) {
+ CHECK_EQ(First, nullptr);
+ CHECK_EQ(Last, nullptr);
+ } else {
+ uptr Count = 0;
+ for (T *I = First;; I = I->Next) {
+ Count++;
+ if (I == Last)
+ break;
}
+ CHECK_EQ(this->size(), Count);
+ CHECK_EQ(Last->Next, nullptr);
}
+}
- void push_front(Item *X) {
- if (empty()) {
- X->Next = nullptr;
- First = Last = X;
- Size = 1;
- } else {
- X->Next = First;
+template <class T> struct SinglyLinkedList : public IntrusiveList<T> {
+ using IntrusiveList<T>::First;
+ using IntrusiveList<T>::Last;
+ using IntrusiveList<T>::Size;
+ using IntrusiveList<T>::empty;
+
+ void push_back(T *X) {
+ X->Next = nullptr;
+ if (empty())
First = X;
- Size++;
- }
+ else
+ Last->Next = X;
+ Last = X;
+ Size++;
+ }
+
+ void push_front(T *X) {
+ if (empty())
+ Last = X;
+ X->Next = First;
+ First = X;
+ Size++;
}
void pop_front() {
@@ -60,7 +110,7 @@ template <class Item> struct IntrusiveList {
Size--;
}
- void extract(Item *Prev, Item *X) {
+ void extract(T *Prev, T *X) {
DCHECK(!empty());
DCHECK_NE(Prev, nullptr);
DCHECK_NE(X, nullptr);
@@ -71,84 +121,105 @@ template <class Item> struct IntrusiveList {
Size--;
}
- Item *front() { return First; }
- const Item *front() const { return First; }
- Item *back() { return Last; }
- const Item *back() const { return Last; }
-
- void append_front(IntrusiveList<Item> *L) {
+ void append_back(SinglyLinkedList<T> *L) {
DCHECK_NE(this, L);
if (L->empty())
return;
if (empty()) {
*this = *L;
- } else if (!L->empty()) {
- L->Last->Next = First;
- First = L->First;
+ } else {
+ Last->Next = L->First;
+ Last = L->Last;
Size += L->size();
}
L->clear();
}
+};
- void append_back(IntrusiveList<Item> *L) {
- DCHECK_NE(this, L);
- if (L->empty())
- return;
+template <class T> struct DoublyLinkedList : IntrusiveList<T> {
+ using IntrusiveList<T>::First;
+ using IntrusiveList<T>::Last;
+ using IntrusiveList<T>::Size;
+ using IntrusiveList<T>::empty;
+
+ void push_front(T *X) {
+ X->Prev = nullptr;
if (empty()) {
- *this = *L;
+ Last = X;
} else {
- Last->Next = L->First;
- Last = L->Last;
- Size += L->size();
+ DCHECK_EQ(First->Prev, nullptr);
}
- L->clear();
+ X->Next = First;
+ First = X;
+ Size++;
+ }
+
+ // Inserts X before Y.
+ void insert(T *X, T *Y) {
+ if (Y == First)
+ return push_front(X);
+ T *Prev = Y->Prev;
+ // This is a hard CHECK to ensure consistency in the event of an intentional
+ // corruption of Y->Prev, to prevent a potential write-{4,8}.
+ CHECK_EQ(Prev->Next, Y);
+ Prev->Next = X;
+ X->Prev = Prev;
+ X->Next = Y;
+ Y->Prev = X;
+ Size++;
}
- void checkConsistency() {
- if (Size == 0) {
- CHECK_EQ(First, nullptr);
- CHECK_EQ(Last, nullptr);
+ void push_back(T *X) {
+ X->Next = nullptr;
+ if (empty()) {
+ First = X;
} else {
- uptr Count = 0;
- for (Item *I = First;; I = I->Next) {
- Count++;
- if (I == Last)
- break;
- }
- CHECK_EQ(size(), Count);
- CHECK_EQ(Last->Next, nullptr);
+ DCHECK_EQ(Last->Next, nullptr);
+ Last->Next = X;
}
+ X->Prev = Last;
+ Last = X;
+ Size++;
}
- template <class ItemT> class IteratorBase {
- public:
- explicit IteratorBase(ItemT *CurrentItem) : Current(CurrentItem) {}
- IteratorBase &operator++() {
- Current = Current->Next;
- return *this;
+ void pop_front() {
+ DCHECK(!empty());
+ First = First->Next;
+ if (!First)
+ Last = nullptr;
+ else
+ First->Prev = nullptr;
+ Size--;
+ }
+
+ // The consistency of the adjacent links is aggressively checked in order to
+ // catch potential corruption attempts, that could yield a mirrored
+ // write-{4,8} primitive. nullptr checks are deemed less vital.
+ void remove(T *X) {
+ T *Prev = X->Prev;
+ T *Next = X->Next;
+ if (Prev) {
+ CHECK_EQ(Prev->Next, X);
+ Prev->Next = Next;
}
- bool operator!=(IteratorBase Other) const {
- return Current != Other.Current;
+ if (Next) {
+ CHECK_EQ(Next->Prev, X);
+ Next->Prev = Prev;
}
- ItemT &operator*() { return *Current; }
-
- private:
- ItemT *Current;
- };
-
- typedef IteratorBase<Item> Iterator;
- typedef IteratorBase<const Item> ConstIterator;
-
- Iterator begin() { return Iterator(First); }
- Iterator end() { return Iterator(nullptr); }
-
- ConstIterator begin() const { return ConstIterator(First); }
- ConstIterator end() const { return ConstIterator(nullptr); }
-
-private:
- uptr Size;
- Item *First;
- Item *Last;
+ if (First == X) {
+ DCHECK_EQ(Prev, nullptr);
+ First = Next;
+ } else {
+ DCHECK_NE(Prev, nullptr);
+ }
+ if (Last == X) {
+ DCHECK_EQ(Next, nullptr);
+ Last = Prev;
+ } else {
+ DCHECK_NE(Next, nullptr);
+ }
+ Size--;
+ }
};
} // namespace scudo
diff --git a/compiler-rt/lib/scudo/standalone/primary32.h b/compiler-rt/lib/scudo/standalone/primary32.h
index 9123d07b49b..453b06ee554 100644
--- a/compiler-rt/lib/scudo/standalone/primary32.h
+++ b/compiler-rt/lib/scudo/standalone/primary32.h
@@ -197,7 +197,7 @@ private:
struct ALIGNED(SCUDO_CACHE_LINE_SIZE) SizeClassInfo {
HybridMutex Mutex;
- IntrusiveList<TransferBatch> FreeList;
+ SinglyLinkedList<TransferBatch> FreeList;
SizeClassStats Stats;
bool CanRelease;
u32 RandState;
@@ -376,7 +376,7 @@ private:
for (uptr I = MinRegionIndex; I <= MaxRegionIndex; I++) {
if (PossibleRegions[I] == ClassId) {
ReleaseRecorder Recorder(I * RegionSize);
- releaseFreeMemoryToOS(&Sci->FreeList, I * RegionSize,
+ releaseFreeMemoryToOS(Sci->FreeList, I * RegionSize,
RegionSize / PageSize, BlockSize, &Recorder);
if (Recorder.getReleasedRangesCount() > 0) {
Sci->ReleaseInfo.PushedBlocksAtLastRelease = Sci->Stats.PushedBlocks;
diff --git a/compiler-rt/lib/scudo/standalone/primary64.h b/compiler-rt/lib/scudo/standalone/primary64.h
index 8f443ea7fa3..409472c8777 100644
--- a/compiler-rt/lib/scudo/standalone/primary64.h
+++ b/compiler-rt/lib/scudo/standalone/primary64.h
@@ -202,7 +202,7 @@ private:
struct ALIGNED(SCUDO_CACHE_LINE_SIZE) RegionInfo {
HybridMutex Mutex;
- IntrusiveList<TransferBatch> FreeList;
+ SinglyLinkedList<TransferBatch> FreeList;
RegionStats Stats;
bool CanRelease;
bool Exhausted;
@@ -372,7 +372,7 @@ private:
}
ReleaseRecorder Recorder(Region->RegionBeg, &Region->Data);
- releaseFreeMemoryToOS(&Region->FreeList, Region->RegionBeg,
+ releaseFreeMemoryToOS(Region->FreeList, Region->RegionBeg,
roundUpTo(Region->AllocatedUser, PageSize) / PageSize,
BlockSize, &Recorder);
diff --git a/compiler-rt/lib/scudo/standalone/quarantine.h b/compiler-rt/lib/scudo/standalone/quarantine.h
index 35fd0bc197e..4b3f368ad96 100644
--- a/compiler-rt/lib/scudo/standalone/quarantine.h
+++ b/compiler-rt/lib/scudo/standalone/quarantine.h
@@ -160,7 +160,7 @@ public:
}
private:
- IntrusiveList<QuarantineBatch> List;
+ SinglyLinkedList<QuarantineBatch> List;
atomic_uptr Size;
void addToSize(uptr add) { atomic_store_relaxed(&Size, getSize() + add); }
diff --git a/compiler-rt/lib/scudo/standalone/release.h b/compiler-rt/lib/scudo/standalone/release.h
index 4fe29fde4bd..4b5c56ce7c1 100644
--- a/compiler-rt/lib/scudo/standalone/release.h
+++ b/compiler-rt/lib/scudo/standalone/release.h
@@ -149,7 +149,7 @@ private:
template <class TransferBatchT, class ReleaseRecorderT>
NOINLINE void
-releaseFreeMemoryToOS(const IntrusiveList<TransferBatchT> *FreeList, uptr Base,
+releaseFreeMemoryToOS(const IntrusiveList<TransferBatchT> &FreeList, uptr Base,
uptr AllocatedPagesCount, uptr BlockSize,
ReleaseRecorderT *Recorder) {
const uptr PageSize = getPageSizeCached();
@@ -199,18 +199,18 @@ releaseFreeMemoryToOS(const IntrusiveList<TransferBatchT> *FreeList, uptr Base,
// allocated page.
if (BlockSize <= PageSize && PageSize % BlockSize == 0) {
// Each chunk affects one page only.
- for (auto It = FreeList->begin(); It != FreeList->end(); ++It) {
- for (u32 I = 0; I < (*It).getCount(); I++) {
- const uptr P = reinterpret_cast<uptr>((*It).get(I));
+ for (const auto &It : FreeList) {
+ for (u32 I = 0; I < It.getCount(); I++) {
+ const uptr P = reinterpret_cast<uptr>(It.get(I));
if (P >= Base && P < End)
Counters.inc((P - Base) >> PageSizeLog);
}
}
} else {
// In all other cases chunks might affect more than one page.
- for (auto It = FreeList->begin(); It != FreeList->end(); ++It) {
- for (u32 I = 0; I < (*It).getCount(); I++) {
- const uptr P = reinterpret_cast<uptr>((*It).get(I));
+ for (const auto &It : FreeList) {
+ for (u32 I = 0; I < It.getCount(); I++) {
+ const uptr P = reinterpret_cast<uptr>(It.get(I));
if (P >= Base && P < End)
Counters.incRange((P - Base) >> PageSizeLog,
(P - Base + BlockSize - 1) >> PageSizeLog);
diff --git a/compiler-rt/lib/scudo/standalone/secondary.cpp b/compiler-rt/lib/scudo/standalone/secondary.cpp
index db7361d7134..dbf15892836 100644
--- a/compiler-rt/lib/scudo/standalone/secondary.cpp
+++ b/compiler-rt/lib/scudo/standalone/secondary.cpp
@@ -73,11 +73,7 @@ void *MapAllocator::allocate(uptr Size, uptr AlignmentHint, uptr *BlockEnd) {
H->Data = Data;
{
ScopedLock L(Mutex);
- if (LIKELY(Tail)) {
- Tail->Next = H;
- H->Prev = Tail;
- }
- Tail = H;
+ InUseBlocks.push_back(H);
AllocatedBytes += CommitSize;
if (LargestSize < CommitSize)
LargestSize = CommitSize;
@@ -94,22 +90,7 @@ void MapAllocator::deallocate(void *Ptr) {
LargeBlock::Header *H = LargeBlock::getHeader(Ptr);
{
ScopedLock L(Mutex);
- LargeBlock::Header *Prev = H->Prev;
- LargeBlock::Header *Next = H->Next;
- if (Prev) {
- CHECK_EQ(Prev->Next, H);
- Prev->Next = Next;
- }
- if (Next) {
- CHECK_EQ(Next->Prev, H);
- Next->Prev = Prev;
- }
- if (UNLIKELY(Tail == H)) {
- CHECK(!Next);
- Tail = Prev;
- } else {
- CHECK(Next);
- }
+ InUseBlocks.remove(H);
const uptr CommitSize = H->BlockEnd - reinterpret_cast<uptr>(H);
FreedBytes += CommitSize;
NumberOfFrees++;
diff --git a/compiler-rt/lib/scudo/standalone/secondary.h b/compiler-rt/lib/scudo/standalone/secondary.h
index 9d074a57c77..b6b41377e26 100644
--- a/compiler-rt/lib/scudo/standalone/secondary.h
+++ b/compiler-rt/lib/scudo/standalone/secondary.h
@@ -10,6 +10,7 @@
#define SCUDO_SECONDARY_H_
#include "common.h"
+#include "list.h"
#include "mutex.h"
#include "stats.h"
#include "string_utils.h"
@@ -78,13 +79,13 @@ public:
void enable() { Mutex.unlock(); }
template <typename F> void iterateOverBlocks(F Callback) const {
- for (LargeBlock::Header *H = Tail; H != nullptr; H = H->Prev)
- Callback(reinterpret_cast<uptr>(H) + LargeBlock::getHeaderSize());
+ for (const auto &H : InUseBlocks)
+ Callback(reinterpret_cast<uptr>(&H) + LargeBlock::getHeaderSize());
}
private:
HybridMutex Mutex;
- LargeBlock::Header *Tail;
+ DoublyLinkedList<LargeBlock::Header> InUseBlocks;
uptr AllocatedBytes;
uptr FreedBytes;
uptr LargestSize;
diff --git a/compiler-rt/lib/scudo/standalone/stats.h b/compiler-rt/lib/scudo/standalone/stats.h
index 16ef5b89b85..294b891d7bb 100644
--- a/compiler-rt/lib/scudo/standalone/stats.h
+++ b/compiler-rt/lib/scudo/standalone/stats.h
@@ -10,6 +10,7 @@
#define SCUDO_STATS_H_
#include "atomic_helpers.h"
+#include "list.h"
#include "mutex.h"
#include <string.h>
@@ -45,20 +46,17 @@ public:
uptr get(StatType I) const { return atomic_load_relaxed(&StatsArray[I]); }
-private:
- friend class GlobalStats;
- atomic_uptr StatsArray[StatCount];
LocalStats *Next;
LocalStats *Prev;
+
+private:
+ atomic_uptr StatsArray[StatCount];
};
// Global stats, used for aggregation and querying.
class GlobalStats : public LocalStats {
public:
- void initLinkerInitialized() {
- Next = this;
- Prev = this;
- }
+ void initLinkerInitialized() {}
void init() {
memset(this, 0, sizeof(*this));
initLinkerInitialized();
@@ -66,30 +64,23 @@ public:
void link(LocalStats *S) {
ScopedLock L(Mutex);
- S->Next = Next;
- S->Prev = this;
- Next->Prev = S;
- Next = S;
+ StatsList.push_back(S);
}
void unlink(LocalStats *S) {
ScopedLock L(Mutex);
- S->Prev->Next = S->Next;
- S->Next->Prev = S->Prev;
+ StatsList.remove(S);
for (uptr I = 0; I < StatCount; I++)
add(static_cast<StatType>(I), S->get(static_cast<StatType>(I)));
}
void get(uptr *S) const {
- memset(S, 0, StatCount * sizeof(uptr));
ScopedLock L(Mutex);
- const LocalStats *Stats = this;
- for (;;) {
+ for (uptr I = 0; I < StatCount; I++)
+ S[I] = LocalStats::get(static_cast<StatType>(I));
+ for (const auto &Stats : StatsList) {
for (uptr I = 0; I < StatCount; I++)
- S[I] += Stats->get(static_cast<StatType>(I));
- Stats = Stats->Next;
- if (Stats == this)
- break;
+ S[I] += Stats.get(static_cast<StatType>(I));
}
// All stats must be non-negative.
for (uptr I = 0; I < StatCount; I++)
@@ -98,6 +89,7 @@ public:
private:
mutable HybridMutex Mutex;
+ DoublyLinkedList<LocalStats> StatsList;
};
} // namespace scudo
diff --git a/compiler-rt/lib/scudo/standalone/tests/list_test.cpp b/compiler-rt/lib/scudo/standalone/tests/list_test.cpp
index ce6cadde123..c303885f6c2 100644
--- a/compiler-rt/lib/scudo/standalone/tests/list_test.cpp
+++ b/compiler-rt/lib/scudo/standalone/tests/list_test.cpp
@@ -11,24 +11,34 @@
struct ListItem {
ListItem *Next;
+ ListItem *Prev;
};
-typedef scudo::IntrusiveList<ListItem> List;
+static ListItem Items[6];
+static ListItem *X = &Items[0];
+static ListItem *Y = &Items[1];
+static ListItem *Z = &Items[2];
+static ListItem *A = &Items[3];
+static ListItem *B = &Items[4];
+static ListItem *C = &Items[5];
-static List StaticList;
+typedef scudo::SinglyLinkedList<ListItem> SLList;
+typedef scudo::DoublyLinkedList<ListItem> DLList;
-static void setList(List *L, ListItem *X = nullptr, ListItem *Y = nullptr,
- ListItem *Z = nullptr) {
+template <typename ListT>
+static void setList(ListT *L, ListItem *I1 = nullptr, ListItem *I2 = nullptr,
+ ListItem *I3 = nullptr) {
L->clear();
- if (X)
- L->push_back(X);
- if (Y)
- L->push_back(Y);
- if (Z)
- L->push_back(Z);
+ if (I1)
+ L->push_back(I1);
+ if (I2)
+ L->push_back(I2);
+ if (I3)
+ L->push_back(I3);
}
-static void checkList(List *L, ListItem *I1, ListItem *I2 = nullptr,
+template <typename ListT>
+static void checkList(ListT *L, ListItem *I1, ListItem *I2 = nullptr,
ListItem *I3 = nullptr, ListItem *I4 = nullptr,
ListItem *I5 = nullptr, ListItem *I6 = nullptr) {
if (I1) {
@@ -58,20 +68,10 @@ static void checkList(List *L, ListItem *I1, ListItem *I2 = nullptr,
EXPECT_TRUE(L->empty());
}
-TEST(ScudoListTest, IntrusiveList) {
- ListItem Items[6];
- EXPECT_EQ(StaticList.size(), 0U);
-
- List L;
+template <typename ListT> static void testListCommon(void) {
+ ListT L;
L.clear();
- ListItem *X = &Items[0];
- ListItem *Y = &Items[1];
- ListItem *Z = &Items[2];
- ListItem *A = &Items[3];
- ListItem *B = &Items[4];
- ListItem *C = &Items[5];
-
EXPECT_EQ(L.size(), 0U);
L.push_back(X);
EXPECT_EQ(L.size(), 1U);
@@ -122,6 +122,16 @@ TEST(ScudoListTest, IntrusiveList) {
L.pop_front();
EXPECT_TRUE(L.empty());
L.checkConsistency();
+}
+
+TEST(ScudoListTest, LinkedListCommon) {
+ testListCommon<SLList>();
+ testListCommon<DLList>();
+}
+
+TEST(ScudoListTest, SinglyLinkedList) {
+ SLList L;
+ L.clear();
L.push_back(X);
L.push_back(Y);
@@ -139,14 +149,10 @@ TEST(ScudoListTest, IntrusiveList) {
L.pop_front();
EXPECT_TRUE(L.empty());
- List L1, L2;
+ SLList L1, L2;
L1.clear();
L2.clear();
- L1.append_front(&L2);
- EXPECT_TRUE(L1.empty());
- EXPECT_TRUE(L2.empty());
-
L1.append_back(&L2);
EXPECT_TRUE(L1.empty());
EXPECT_TRUE(L2.empty());
@@ -160,26 +166,32 @@ TEST(ScudoListTest, IntrusiveList) {
checkList(&L1, X, Y, Z, A, B, C);
EXPECT_TRUE(L2.empty());
- setList(&L1, X, Y);
- setList(&L2);
- L1.append_front(&L2);
- checkList(&L1, X, Y);
- EXPECT_TRUE(L2.empty());
+ L1.clear();
+ L2.clear();
+ L1.push_back(X);
+ L1.append_back(&L2);
+ EXPECT_EQ(L1.back(), X);
+ EXPECT_EQ(L1.front(), X);
+ EXPECT_EQ(L1.size(), 1U);
}
-TEST(ScudoListTest, IntrusiveListAppendEmpty) {
- ListItem I;
- List L;
+TEST(ScudoListTest, DoublyLinkedList) {
+ DLList L;
L.clear();
- L.push_back(&I);
- List L2;
- L2.clear();
- L.append_back(&L2);
- EXPECT_EQ(L.back(), &I);
- EXPECT_EQ(L.front(), &I);
- EXPECT_EQ(L.size(), 1U);
- L.append_front(&L2);
- EXPECT_EQ(L.back(), &I);
- EXPECT_EQ(L.front(), &I);
+
+ L.push_back(X);
+ L.push_back(Y);
+ L.push_back(Z);
+ L.remove(Y);
+ EXPECT_EQ(L.size(), 2U);
+ EXPECT_EQ(L.front(), X);
+ EXPECT_EQ(L.back(), Z);
+ L.checkConsistency();
+ L.remove(Z);
EXPECT_EQ(L.size(), 1U);
+ EXPECT_EQ(L.front(), X);
+ EXPECT_EQ(L.back(), X);
+ L.checkConsistency();
+ L.pop_front();
+ EXPECT_TRUE(L.empty());
}
diff --git a/compiler-rt/lib/scudo/standalone/tests/release_test.cpp b/compiler-rt/lib/scudo/standalone/tests/release_test.cpp
index 1de7fed1c4c..3776768e9a8 100644
--- a/compiler-rt/lib/scudo/standalone/tests/release_test.cpp
+++ b/compiler-rt/lib/scudo/standalone/tests/release_test.cpp
@@ -173,7 +173,7 @@ template <class SizeClassMap> void testReleaseFreeMemoryToOS() {
std::shuffle(FreeArray.begin(), FreeArray.end(), R);
// Build the FreeList from the FreeArray.
- scudo::IntrusiveList<Batch> FreeList;
+ scudo::SinglyLinkedList<Batch> FreeList;
FreeList.clear();
Batch *CurrentBatch = nullptr;
for (auto const &Block : FreeArray) {
@@ -189,7 +189,7 @@ template <class SizeClassMap> void testReleaseFreeMemoryToOS() {
// Release the memory.
ReleasedPagesRecorder Recorder;
- releaseFreeMemoryToOS(&FreeList, 0, AllocatedPagesCount, BlockSize,
+ releaseFreeMemoryToOS(FreeList, 0, AllocatedPagesCount, BlockSize,
&Recorder);
// Verify that there are no released pages touched by used chunks and all
OpenPOWER on IntegriCloud