【问题标题】:Mysterious "value computed is not used" warnings on __atomic_exchange_n__atomic_exchange_n 上的神秘“未使用计算值”警告
【发布时间】:2015-09-06 12:42:06
【问题描述】:

我基于 gcc 的原子内置函数开发了一个可重入函数。不幸的是,我收到关于“计算但未使用”值的神秘警告:

$ gcc -c -Wall ss.c
ss.c: In function ‘ss_wrapper’:
ss.c:87:3: warning: value computed is not used [-Wunused-value]
   __atomic_exchange_n(&ss_top, hit, __ATOMIC_SEQ_CST);
   ^
ss.c:91:5: warning: value computed is not used [-Wunused-value]
     __atomic_exchange_n(&ss_top, bkp->next, __ATOMIC_SEQ_CST); // release the lock, find out if there is new element
     ^

这是我的功能:

static void ss_wrapper(int signum, siginfo_t* siginfo, void *ucontext) {
  // currently top element on the signal stack
  static struct ss_hit* ss_top = NULL;


  struct ss_hit* hit = ss_newhit(signum, siginfo, (ucontext_t*)ucontext);
  struct ss_hit* bkp;

  again:

  bkp = hit;
  __atomic_exchange_n(&ss_top, hit, __ATOMIC_SEQ_CST);
  if (!hit) { // we got the lock, we are the master
    ss_fire(bkp);

    // release the lock, find out if there is new element
    __atomic_exchange_n(&ss_top, bkp->next, __ATOMIC_SEQ_CST);
    if (bkp->next) { // there IS

      hit = bkp;
      free(bkp);
      goto again;

    } else
      free(bkp);
  } else { // we didn't got the lock, but we got the top in hit
    __atomic_store(&hit->next, &bkp, __ATOMIC_SEQ_CST);
  }
}

为什么会这样? __atomic_exchange_n 不应该计算任何东西,它只会交换两个变量的内容。

【问题讨论】:

  • 整个源文件可以在here找到。
  • 你不应该直接使用 atomic-builtins,而是使用 C11 stdatomic.h。为什么要让你的代码在没有实际需要的情况下依赖编译器。
  • @Olaf 由于缺乏信任,我尝试使用可能的最低级别。但是现在我的代码生成了很好的 asm,没有更多理由不使用符合标准的方式,这就是我要做的。
  • "缺乏信任"...好吧,因为这是一个仅标题的功能,您可以轻松验证这一点。所以你验证你的编译器生成的所有汇编?如果汇编器映射到错误的机器码怎么办?你在哪里停下来?
  • @Olaf 不是全部,只做硬件附近的事情,例如原子操作。验证原子指令的汇编是一件非常简单的事情,在我之前的尝试中,我多次发现原子内置指令产生了可疑代码(例如,如果它从堆栈中读取变量,在 regs 中进行交换,然后将它回来了,它已经不是原子的)。另一个原因是我想看看 gcc 是如何做到的。

标签: c gcc atomic gcc4.9 reentrancy


【解决方案1】:

它只交换两个变量的内容

不,它没有。它将一个变量的内容与寄存器的内容交换。第二个变量永远不会改变。 (即使没有查阅文档,这从传递两个参数的不同约定中也很明显——原子交换的内存地址作为指针传递,另一个值被复制,而不是就地访问)

由于这种误解,你的逻辑被打破了。你的意思是:

hit = __atomic_exchange_n(&ss_top, hit, __ATOMIC_SEQ_CST);
if (!hit) { // we got the lock, we are the master

将寄存器的新值写回第二个变量。对hit 的访问是非原子的,但没关系,因为它是一个局部变量,不与任何其他线程共享。

不要直接把返回值扔掉,如果你这样做了,你永远不会进入“我们是主人”的分支

【讨论】:

  • 你说得对,这确实是使 asm 完美的唯一方法......也许我误解了 gcc 内置文档,也许不是。 :-(
【解决方案2】:

@Olaf 在评论中回答了我的问题:虽然用 __attribute__((unused)) 声明一个虚拟变量并给他返回值可以避免警告,但还有一种更简单的方法可以做到这一点:将函数转换为 (void) ,所以:

(void)__atomic_exchange_n(...);

扩展:虽然这个解决方案也消除了警告,但它仍然没有正确使用__atomic_exchange_n gcc 内置函数(尽管有时它编译了正确的代码)。接受的答案最终解决了问题。

【讨论】:

  • 这根本解决不了问题。是的,它显示了如何丢弃表达式的结果,但是读取整个函数,很明显需要结果。
  • @BenVoigt 你说得对,这确实是使 asm 完美的唯一方法......也许我误解了 gcc 内置文档,也许不是。 :-(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-05
  • 2011-10-25
  • 2023-03-06
  • 2011-03-04
  • 2023-03-21
相关资源
最近更新 更多