首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否有可能在atomic_set()之前执行memset64()?

是否有可能在atomic_set()之前执行memset64()?
EN

Stack Overflow用户
提问于 2022-11-01 06:20:20
回答 1查看 57关注 0票数 2

我有一段代码如下所示:

核心0:

代码语言:javascript
复制
memset64(buffer, 0xFFFFFFFFFFFFFFFFULL, 4096);
position.atomic_set(1);

缓冲区是指向DDR中4KB缓冲区的指针。位置是一个原子整数变量。

请参阅https://elixir.bootlin.com/linux/v4.1/source/arch/arm64/include/asm/atomic.h

核心1:

代码语言:javascript
复制
while (1) {
    if (position.atomic_read() == 1) {
        break;
    }
}
*buffer = "4KB data";

有两个线程同时工作在两个核心上。

核心0将首先将缓冲区设置为memset,然后将原子变量position设置为1。

核心1将原子化读取无限循环中的变量position,如果position的值为1,则它会中断并向缓冲区写入某些内容。

我遇到了一个错误:程序完成后,position的值是1,但是缓冲区的内容是0 0xFF。

这似乎是一个可能的根本原因,在核心1看来,原子变量在memset之前被设置为1,因此核心1对缓冲区的修改被核心0的memset覆盖。

我正在用arm64 gcc 8.3和-O2优化一起编译代码。精灵将运行在一个2集群,8核心臂皮质-A53 CPU.

我想知道在aarch64中,在CPU上的memset64()之前执行atomic_set()是否有可能?或者,是否有可能是另一个CPU内核在看到memset之前就看到了原子值的变化?

我对系统编程很陌生,所以我对内存模型这样的概念不太熟悉。我将非常感激任何人都能给我一些建议。

EN

回答 1

Stack Overflow用户

发布于 2022-11-01 07:08:17

在当前线程(调用上面这两行代码的线程)中,后续读取buffer中的值或读取position将具有预期的行为。因此,如果您的程序是单线程,您可以停止现在。

但是,轮询position和观察new_pos的其他线程随后可能会从buffer读取,但看不到原始线程所写的期望值。它可以从缓冲区读取“旧”值。这有时被称为内存排序或缓存一致性问题。这是完全正常的--特别是在多核和多处理器系统中。在单核系统上很少有问题。

您需要引入一个内存屏障来强制同步。最简单的方法就是使用互斥对象来读取和写入这些值。

也就是说,在原来的线程中:

代码语言:javascript
复制
{
    std::lock<std::mutex>(mut); // mut is a shared instance of std::mutex
    memset64(buffer, 0xFFFFFFFFFFFFFFFFULL, 4096);
    position.atomic_set(new_pos);
}

然后,“读取”位置和缓冲区从另一个线程,采取锁的第一。

代码语言:javascript
复制
{
    std::lock<std::mutex>(mut); // same instance of mut above
    auto pos = position.atomic_get();
    if (pos != last_pos)
    {
        last_pos = pos;
        // read values of buffer while inside the lock
    }
}

使用互斥体的一个副作用是,它可能使原子原语的使用变得不必要。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74272208

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档