Skip to content

Commit cd770ad

Browse files
address jhuber6's comments
1 parent 436947e commit cd770ad

File tree

3 files changed

+43
-27
lines changed

3 files changed

+43
-27
lines changed

libc/src/__support/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ add_header_library(
405405
DEPENDS
406406
libc.hdr.types.size_t
407407
libc.src.__support.common
408+
libc.src.__support.CPP.atomic
408409
libc.src.__support.threads.sleep
409410
)
410411

libc/src/__support/aba_ptr.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLVM_LIBC_SRC___SUPPORT_TAGGED_POINTER_H
1111

1212
#include "hdr/types/size_t.h"
13+
#include "src/__support/CPP/atomic.h"
1314
#include "src/__support/common.h"
1415
#include "src/__support/threads/sleep.h"
1516

@@ -40,24 +41,28 @@ template <class T, bool IsAtomic> struct AbaPtrImpl {
4041
template <class Op> LIBC_INLINE void transaction(Op &&op) {
4142
if constexpr (IsAtomic) {
4243
for (;;) {
44+
cpp::AtomicRef<typename Impl::Atomic> ref(impl.atomic);
4345
typename Impl::Atomic snapshot, next;
44-
__atomic_load(&impl.atomic, &snapshot, __ATOMIC_RELAXED);
46+
snapshot = ref.load(cpp::MemoryOrder::RELAXED);
4547
next.ptr = op(snapshot.ptr);
4648
// Wrapping add for unsigned integers.
4749
next.tag = snapshot.tag + 1;
48-
if (__atomic_compare_exchange(&impl.atomic, &snapshot, &next, true,
49-
__ATOMIC_ACQ_REL, __ATOMIC_RELAXED))
50+
// Redo transaction can be costly, so we use strong version.
51+
if (ref.compare_exchange_strong(snapshot, next,
52+
cpp::MemoryOrder::ACQ_REL,
53+
cpp::MemoryOrder::RELAXED))
5054
return;
5155
}
5256
} else {
5357
// Acquire the lock.
54-
while (__atomic_exchange_n(&impl.mutex.locked, true, __ATOMIC_ACQUIRE))
55-
while (__atomic_load_n(&impl.mutex.locked, __ATOMIC_RELAXED))
58+
cpp::AtomicRef<bool> ref(impl.mutex.locked);
59+
while (ref.exchange(true, cpp::MemoryOrder::ACQUIRE))
60+
while (ref.load(cpp::MemoryOrder::RELAXED))
5661
LIBC_NAMESPACE::sleep_briefly();
5762

5863
impl.mutex.ptr = op(impl.mutex.ptr);
5964
// Release the lock.
60-
__atomic_store_n(&impl.mutex.locked, false, __ATOMIC_RELEASE);
65+
ref.store(false, cpp::MemoryOrder::RELEASE);
6166
}
6267
}
6368

@@ -68,7 +73,8 @@ template <class T, bool IsAtomic> struct AbaPtrImpl {
6873
// implementations that uses racy read anyway, we still load the whole
6974
// word to avoid any complications.
7075
typename Impl::Atomic snapshot;
71-
__atomic_load(&impl.atomic, &snapshot, __ATOMIC_RELAXED);
76+
cpp::AtomicRef<typename Impl::Atomic> ref(impl.atomic);
77+
snapshot = ref.load(cpp::MemoryOrder::RELAXED);
7278
return snapshot.ptr;
7379
} else {
7480
return impl.mutex.ptr;

libc/src/__support/mpmc_stack.h

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,34 +42,43 @@ template <class T> class MPMCStack {
4242
}
4343
LIBC_INLINE bool push_all(T values[], size_t count) {
4444
struct Guard {
45-
size_t count;
46-
Node **allocated;
47-
LIBC_INLINE Guard(Node *allocated[]) : count(0), allocated(allocated) {}
45+
Node *cursor;
46+
LIBC_INLINE Guard() : cursor(nullptr) {}
4847
LIBC_INLINE ~Guard() {
49-
for (size_t i = 0; i < count; ++i)
50-
delete allocated[i];
48+
while (cursor) {
49+
Node *next = cursor->next;
50+
delete cursor;
51+
cursor = next;
52+
}
53+
}
54+
LIBC_INLINE void advance(Node *node) {
55+
node->next = cursor;
56+
cursor = node;
57+
}
58+
LIBC_INLINE Node *finish() {
59+
Node *ret = cursor;
60+
cursor = nullptr;
61+
return ret;
5162
}
52-
LIBC_INLINE void add(Node *node) { allocated[count++] = node; }
53-
LIBC_INLINE void clear() { count = 0; }
5463
};
55-
// Variable sized array is a GNU extension.
56-
__extension__ Node *allocated[count];
64+
Node *first = nullptr;
65+
Node *last = nullptr;
5766
{
58-
Guard guard(allocated);
67+
Guard guard{};
5968
for (size_t i = 0; i < count; ++i) {
6069
AllocChecker ac;
6170
Node *new_node = new (ac) Node(values[i]);
6271
if (!ac)
6372
return false;
64-
guard.add(new_node);
65-
if (i != 0)
66-
new_node->next = allocated[i - 1];
73+
if (i == 0)
74+
first = new_node;
75+
guard.advance(new_node);
6776
}
68-
guard.clear();
77+
last = guard.finish();
6978
}
70-
head.transaction([&allocated, count](Node *old_head) {
71-
allocated[0]->next = old_head;
72-
return allocated[count - 1];
79+
head.transaction([first, last](Node *old_head) {
80+
first->next = old_head;
81+
return last;
7382
});
7483
return true;
7584
}
@@ -82,10 +91,10 @@ template <class T> class MPMCStack {
8291
return nullptr;
8392
}
8493
node = current_head;
85-
node->visitor.fetch_add(1);
94+
node->visitor.fetch_add(1, cpp::MemoryOrder::ACQUIRE);
8695
res = cpp::optional<T>{node->value};
8796
Node *next = node->next;
88-
node->visitor.fetch_sub(1);
97+
node->visitor.fetch_sub(1, cpp::MemoryOrder::RELEASE);
8998
return next;
9099
});
91100
// On a successful transaction, a node is popped by us. So we must delete
@@ -95,7 +104,7 @@ template <class T> class MPMCStack {
95104
// node.
96105
if (res) {
97106
// Spin until the node is no longer in use.
98-
while (node->visitor.load() != 0)
107+
while (node->visitor.load(cpp::MemoryOrder::RELAXED) != 0)
99108
LIBC_NAMESPACE::sleep_briefly();
100109
delete node;
101110
}

0 commit comments

Comments
 (0)