首页 > 解决方案 > 实际示例中的 READ_ONCE 和 WRITE_ONCE

问题描述

int __thread theft = 0;
static void flush_local_count_sig(int unused)
{
    if (READ_ONCE(theft) != THEFT_REQ) (*)
        return;
    smp_mb();
    WRITE_ONCE(theft, THEFT_ACK)
    if (!counting) {
        WRITE_ONCE(theft, THEFT_READY);
    }
    smp_mb();
}

在416 页的https://mirrors.edge.kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.2018.12.08a.pdf中有一个问题:

为什么要使用 theft per-thread 变量READ_ONCE并进行包装?WRITE_ONCE

答案是

第一个(用 (*) 注释)可以被认为是不必要的。

为什么第一个READ_ONCE不是必需的?毕竟,编译器可以尝试过于聪明并对其进行优化。


int __thread theft = 0;
static void flush_local_count_sig(int unused)
{
    if (theft != THEFT_REQ)
        return;
    smp_mb();  (*) 
    WRITE_ONCE(theft, THEFT_ACK)
    if (!counting) {
        WRITE_ONCE(theft, THEFT_READY);
    }
    smp_mb();
}

theft不是同时访问的——它由一个线程和信号处理程序访问。如果我们删除带有 (*) 注释的行,那么正确性如何?

标签: cmultithreadinglinux-kernelx86memory-model

解决方案


推荐阅读