我正在研究Seqlock的实现。但是我发现的所有资料来源都以不同的方式实现它们。
static inline unsigned __read_seqcount_begin(const seqcount_t *s)
{
unsigned ret;
repeat:
ret = READ_ONCE(s->sequence);
if (unlikely(ret & 1)) {
cpu_relax();
goto repeat;
}
return ret;
}
static inline unsigned raw_read_seqcount_begin(const seqcount_t *s)
{
unsigned ret = __read_seqcount_begin(s);
smp_rmb();
return ret;
}
Run Code Online (Sandbox Code Playgroud)
基本上,它使用易失性读取以及在读取器端具有获取语义的读取屏障。
使用时,后续读取不受保护:
struct Data {
u64 a, b;
};
// ...
read_seqcount_begin(&seq);
int v1 = d.a, v2 = d.b;
// ...
Run Code Online (Sandbox Code Playgroud)
RIGTORP_SEQLOCK_NOINLINE T load() const noexcept {
T copy;
std::size_t seq0, …Run Code Online (Sandbox Code Playgroud) 我正在研究Michael 和 Scott 的无锁(en-,de-)队列算法。问题是我无法解释/理解(除了代码本身的注释之外,论文也无法解释)几行。
入队:
enqueue(Q: pointer to queue_t, value: data type)
E1: node = new_node() // Allocate a new node from the free list
E2: node->value = value // Copy enqueued value into node
E3: node->next.ptr = NULL // Set next pointer of node to NULL
E4: loop // Keep trying until Enqueue is done
E5: tail = Q->Tail // Read Tail.ptr and Tail.count together
E6: next = tail.ptr->next // Read next ptr and count fields together …Run Code Online (Sandbox Code Playgroud) 我想从原子 uint32s 拼凑一个 uint64 原子计数器。计数器有一个写入器和多个读取器。编写器是一个信号处理程序,所以它不能阻塞。
我的想法是使用低位的代数作为读锁。读取器重试,直到整个读取过程中生成计数稳定,并且低位未设置。
以下代码在内存排序的设计和使用中是否正确?有没有更好的办法?
using namespace std;
class counter {
atomic<uint32_t> lo_{};
atomic<uint32_t> hi_{};
atomic<uint32_t> gen_{};
uint64_t read() const {
auto acquire = memory_order_acquire;
uint32_t lo, hi, gen1, gen2;
do {
gen1 = gen_.load(acquire);
lo = lo_.load(acquire);
hi = hi_.load(acquire);
gen2 = gen_.load(acquire);
} while (gen1 != gen2 || (gen1 & 1));
return (uint64_t(hi) << 32) | lo;
}
void increment() {
auto release = memory_order_release;
gen_.fetch_add(1, release);
uint32_t newlo = 1 + lo_.fetch_add(1, release);
if (newlo …Run Code Online (Sandbox Code Playgroud) atomic ×1
c ×1
c++ ×1
c++11 ×1
concurrency ×1
lockless ×1
nonblocking ×1
rust ×1
seqlock ×1
stdatomic ×1