Skip to content

Commit 33c4421

Browse files
committed
[Reland][ADT][ConcurrentHashTable] adapt ConcurrentHashTable and its users to LLVM_ENABLE_THREADS=0 mode.
This patch hides thread specific handling under LLVM_ENABLE_THREADS guard. It also removes usages of thread_local variables, since it has a weak support on some platforms. Instead, the patch uses single mutex for locking allocator. That may be replaced with more effective allocator later. f.e. D142318 Differential Revision: https://reviews.llvm.org/D147649
1 parent b00fc5a commit 33c4421

File tree

4 files changed

+59
-36
lines changed

4 files changed

+59
-36
lines changed

llvm/include/llvm/ADT/ConcurrentHashtable.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,10 @@ class ConcurrentHashTableByPtr {
175175
Bucket &CurBucket = BucketsArray[getBucketIdx(Hash)];
176176
uint32_t ExtHashBits = getExtHashBits(Hash);
177177

178+
#if LLVM_ENABLE_THREADS
178179
// Lock bucket.
179180
CurBucket.Guard.lock();
181+
#endif
180182

181183
HashesPtr BucketHashes = CurBucket.Hashes;
182184
DataPtr BucketEntries = CurBucket.Entries;
@@ -194,7 +196,9 @@ class ConcurrentHashTableByPtr {
194196
CurBucket.NumberOfEntries++;
195197
RehashBucket(CurBucket);
196198

199+
#if LLVM_ENABLE_THREADS
197200
CurBucket.Guard.unlock();
201+
#endif
198202

199203
return {NewData, true};
200204
}
@@ -204,7 +208,9 @@ class ConcurrentHashTableByPtr {
204208
KeyDataTy *EntryData = BucketEntries[CurEntryIdx];
205209
if (Info::isEqual(Info::getKey(*EntryData), NewValue)) {
206210
// Already existed entry matched with inserted data is found.
211+
#if LLVM_ENABLE_THREADS
207212
CurBucket.Guard.unlock();
213+
#endif
208214

209215
return {EntryData, false};
210216
}
@@ -283,8 +289,10 @@ class ConcurrentHashTableByPtr {
283289
// [Size] entries.
284290
DataPtr Entries = nullptr;
285291

292+
#if LLVM_ENABLE_THREADS
286293
// Mutex for this bucket.
287294
std::mutex Guard;
295+
#endif
288296
};
289297

290298
// Reallocate and rehash bucket if this is full enough.

llvm/include/llvm/DWARFLinkerParallel/StringPool.h

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,26 @@ namespace dwarflinker_parallel {
2222
/// and a string body which is placed right after StringEntry.
2323
using StringEntry = StringMapEntry<DwarfStringPoolEntry *>;
2424

25-
class PerThreadStringAllocator
26-
: public AllocatorBase<PerThreadStringAllocator> {
25+
class StringAllocator : public AllocatorBase<StringAllocator> {
2726
public:
2827
inline LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size,
2928
size_t Alignment) {
30-
return ThreadLocalAllocator.Allocate(Size, Align(Alignment));
29+
#if LLVM_ENABLE_THREADS
30+
std::lock_guard<std::mutex> Guard(AllocatorMutex);
31+
#endif
32+
33+
return Allocator.Allocate(Size, Align(Alignment));
3134
}
3235

3336
// Pull in base class overloads.
34-
using AllocatorBase<PerThreadStringAllocator>::Allocate;
37+
using AllocatorBase<StringAllocator>::Allocate;
3538

3639
private:
37-
static thread_local BumpPtrAllocator ThreadLocalAllocator;
40+
#if LLVM_ENABLE_THREADS
41+
std::mutex AllocatorMutex;
42+
#endif
43+
44+
BumpPtrAllocator Allocator;
3845
};
3946

4047
class StringPoolEntryInfo {
@@ -56,29 +63,27 @@ class StringPoolEntryInfo {
5663

5764
/// \returns newly created object of KeyDataTy type.
5865
static inline StringEntry *create(const StringRef &Key,
59-
PerThreadStringAllocator &Allocator) {
66+
StringAllocator &Allocator) {
6067
return StringEntry::create(Key, Allocator);
6168
}
6269
};
6370

64-
class StringPool : public ConcurrentHashTableByPtr<StringRef, StringEntry,
65-
PerThreadStringAllocator,
66-
StringPoolEntryInfo> {
71+
class StringPool
72+
: public ConcurrentHashTableByPtr<StringRef, StringEntry, StringAllocator,
73+
StringPoolEntryInfo> {
6774
public:
6875
StringPool()
69-
: ConcurrentHashTableByPtr<StringRef, StringEntry,
70-
PerThreadStringAllocator, StringPoolEntryInfo>(
71-
Allocator) {}
76+
: ConcurrentHashTableByPtr<StringRef, StringEntry, StringAllocator,
77+
StringPoolEntryInfo>(Allocator) {}
7278

7379
StringPool(size_t InitialSize)
74-
: ConcurrentHashTableByPtr<StringRef, StringEntry,
75-
PerThreadStringAllocator, StringPoolEntryInfo>(
76-
Allocator, InitialSize) {}
80+
: ConcurrentHashTableByPtr<StringRef, StringEntry, StringAllocator,
81+
StringPoolEntryInfo>(Allocator, InitialSize) {}
7782

78-
PerThreadStringAllocator &getAllocatorRef() { return Allocator; }
83+
StringAllocator &getAllocatorRef() { return Allocator; }
7984

8085
private:
81-
PerThreadStringAllocator Allocator;
86+
StringAllocator Allocator;
8287
};
8388

8489
} // end of namespace dwarflinker_parallel

llvm/lib/DWARFLinkerParallel/StringPool.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,3 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/DWARFLinkerParallel/StringPool.h"
10-
11-
thread_local llvm::BumpPtrAllocator
12-
llvm::dwarflinker_parallel::PerThreadStringAllocator::ThreadLocalAllocator;

llvm/unittests/ADT/ConcurrentHashtableTest.cpp

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,25 +36,38 @@ class String {
3636
std::array<char, 0x20> ExtraData;
3737
};
3838

39-
static thread_local BumpPtrAllocator ThreadLocalAllocator;
40-
class PerThreadAllocator : public AllocatorBase<PerThreadAllocator> {
39+
class SimpleAllocator : public AllocatorBase<SimpleAllocator> {
4140
public:
4241
inline LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size,
4342
size_t Alignment) {
44-
return ThreadLocalAllocator.Allocate(Size, Align(Alignment));
43+
#if LLVM_ENABLE_THREADS
44+
std::lock_guard<std::mutex> Guard(AllocatorMutex);
45+
#endif
46+
47+
return Allocator.Allocate(Size, Align(Alignment));
4548
}
46-
inline size_t getBytesAllocated() const {
47-
return ThreadLocalAllocator.getBytesAllocated();
49+
inline size_t getBytesAllocated() {
50+
#if LLVM_ENABLE_THREADS
51+
std::lock_guard<std::mutex> Guard(AllocatorMutex);
52+
#endif
53+
54+
return Allocator.getBytesAllocated();
4855
}
4956

5057
// Pull in base class overloads.
51-
using AllocatorBase<PerThreadAllocator>::Allocate;
58+
using AllocatorBase<SimpleAllocator>::Allocate;
59+
60+
protected:
61+
#if LLVM_ENABLE_THREADS
62+
std::mutex AllocatorMutex;
63+
#endif
64+
BumpPtrAllocator Allocator;
5265
} Allocator;
5366

5467
TEST(ConcurrentHashTableTest, AddStringEntries) {
5568
ConcurrentHashTableByPtr<
56-
std::string, String, PerThreadAllocator,
57-
ConcurrentHashTableInfoByPtr<std::string, String, PerThreadAllocator>>
69+
std::string, String, SimpleAllocator,
70+
ConcurrentHashTableInfoByPtr<std::string, String, SimpleAllocator>>
5871
HashTable(Allocator, 10);
5972

6073
size_t AllocatedBytesAtStart = Allocator.getBytesAllocated();
@@ -102,8 +115,8 @@ TEST(ConcurrentHashTableTest, AddStringEntries) {
102115
TEST(ConcurrentHashTableTest, AddStringMultiplueEntries) {
103116
const size_t NumElements = 10000;
104117
ConcurrentHashTableByPtr<
105-
std::string, String, PerThreadAllocator,
106-
ConcurrentHashTableInfoByPtr<std::string, String, PerThreadAllocator>>
118+
std::string, String, SimpleAllocator,
119+
ConcurrentHashTableInfoByPtr<std::string, String, SimpleAllocator>>
107120
HashTable(Allocator);
108121

109122
// Check insertion.
@@ -147,8 +160,8 @@ TEST(ConcurrentHashTableTest, AddStringMultiplueEntriesWithResize) {
147160
// Number of elements exceeds original size, thus hashtable should be resized.
148161
const size_t NumElements = 20000;
149162
ConcurrentHashTableByPtr<
150-
std::string, String, PerThreadAllocator,
151-
ConcurrentHashTableInfoByPtr<std::string, String, PerThreadAllocator>>
163+
std::string, String, SimpleAllocator,
164+
ConcurrentHashTableInfoByPtr<std::string, String, SimpleAllocator>>
152165
HashTable(Allocator, 100);
153166

154167
// Check insertion.
@@ -191,8 +204,8 @@ TEST(ConcurrentHashTableTest, AddStringMultiplueEntriesWithResize) {
191204
TEST(ConcurrentHashTableTest, AddStringEntriesParallel) {
192205
const size_t NumElements = 10000;
193206
ConcurrentHashTableByPtr<
194-
std::string, String, PerThreadAllocator,
195-
ConcurrentHashTableInfoByPtr<std::string, String, PerThreadAllocator>>
207+
std::string, String, SimpleAllocator,
208+
ConcurrentHashTableInfoByPtr<std::string, String, SimpleAllocator>>
196209
HashTable(Allocator);
197210

198211
// Check parallel insertion.
@@ -235,8 +248,8 @@ TEST(ConcurrentHashTableTest, AddStringEntriesParallel) {
235248
TEST(ConcurrentHashTableTest, AddStringEntriesParallelWithResize) {
236249
const size_t NumElements = 20000;
237250
ConcurrentHashTableByPtr<
238-
std::string, String, PerThreadAllocator,
239-
ConcurrentHashTableInfoByPtr<std::string, String, PerThreadAllocator>>
251+
std::string, String, SimpleAllocator,
252+
ConcurrentHashTableInfoByPtr<std::string, String, SimpleAllocator>>
240253
HashTable(Allocator, 100);
241254

242255
// Check parallel insertion.

0 commit comments

Comments
 (0)