You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

libuv中并发C代码的内存屏障必要性及GCC编译优化疑问

关于libuv 1.3.0中并发代码内存屏障的疑问

我在libuv 1.3.0项目中发现一段并发C代码,无法理解为何需要编译器内存屏障,原代码如下:

static int uv__async_make_pending(int* pending) {
  /* Do a cheap read first. */
  if (ACCESS_ONCE(int, *pending) != 0)
    return 1;

  /* Micro-optimization: use atomic memory operations to detect if we've been
   * preempted by another thread and don't have to make an expensive syscall.
   * This speeds up the heavily contended case by about 1-2% and has little
   * if any impact on the non-contended case.
   *
   * Use XCHG instead of the CMPXCHG that __sync_val_compare_and_swap() emits
   * on x86, it's about 4x faster. It probably makes zero difference in the
   * grand scheme of things but I'm OCD enough not to let this one pass.
   */
#if defined(__i386__) || defined(__x86_64__)
  {
    unsigned int val = 1;
    __asm__ __volatile__ ("xchgl %0, %1"
                         : "+r" (val)
                         : "m"  (*pending));
    return val != 0;
  }
#elif defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ > 0)
  return __sync_val_compare_and_swap(pending, 0, 1) != 0;
#else
  ACCESS_ONCE(int, *pending) = 1;
  return 0;
#endif
}

不同环境的简化版本

这段代码可针对不同环境简化为以下版本:

  • x86环境版本:
static int uv__async_make_pending(int* pending) {
  if (ACCESS_ONCE(int, *pending) != 0)
    return 1;

  {
    unsigned int val = 1;
    __asm__ __volatile__ ("xchgl %0, %1"
                         : "+r" (val)
                         : "m"  (*pending));
    return val != 0;
  }
}
  • GNU C 4环境版本:
static int uv__async_make_pending(int* pending) {
  if (ACCESS_ONCE(int, *pending) != 0)
    return 1;

  return __sync_val_compare_and_swap(pending, 0, 1) != 0;
}
  • 其他环境版本:
static int uv__async_make_pending(int* pending) {
  if (ACCESS_ONCE(int, *pending) != 0)
    return 1;

  ACCESS_ONCE(int, *pending) = 1;
  return 0;
}

核心疑问

以最后一种环境的代码为例,若移除内存屏障(修改为如下代码),经GCC编译后是否会出现错误?我不清楚GCC会执行哪些优化导致问题:

static int uv__async_make_pending(int* pending) {
  if (*pending != 0)
    return 1;

  *pending = 1;
  return 0;
}

另外,我尝试过以下搜索但未找到答案:

  • 直接搜索该代码,未找到内存屏障必要性的相关解释
  • 了解内存屏障的概念,但搜索内存屏障相关内容,未找到针对此类特定代码的使用场景说明
  • 搜索C语言无锁编程相关内容,也未找到编译器对代码优化方式的解释

内容的提问来源于stack exchange,提问作者Droopy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 22:30:00