【问题标题】:Is there something wrong with my spin lock?我的自旋锁有问题吗?
【发布时间】:2012-07-17 01:58:45
【问题描述】:

这是我的自旋锁实现,但它似乎无法保护关键代码。我的实现有问题吗?

static __inline__ int xchg_asm(int* lock, int val) 
{
  int ret; 
  __asm__ __volatile__(
    LOCK "movl (%1),%%eax; 
    xchg (%1),%2; 
    movl %%eax, %0" :"=m" (ret) :"d"(lock), "c"(val)
  );
  return ret; 
}
void spin_init(spinlock_t* sl) 
{ 
  sl->val = 0; 
} 
void spin_lock(spinlock_t* sl) 
{ 
  int ret; 
  do { 
    ret = xchg_asm(&(sl->val), 1); 
  } while ( ret==0 ); 
}

void spin_unlock(spinlock_t* sl) 
{
  xchg_asm(&(sl->val), 0);
}

【问题讨论】:

  • 优秀;它可能不是错误,但对我来说,spin_destroy() 函数释放未由spin_init() 分配的内存似乎很奇怪。 (也有spin_alloc() 函数吗?)
  • spin_destory 可能是多余的。
  • 也许是过分了。但是提供一个匹配的 _init()_destroy() 函数 很好,特别是如果你想在将来修改任何东西。

标签: linux assembly linux-kernel x86 kernel


【解决方案1】:

您的代码等于:

static __inline__ int xchg_asm(int* lock, int val) {
   int save_old_value_at_eax;

   save_old_value_at_eax = *lock;        /* with a wrong lock prefix */
   xchg *lock with val and discard the original value of *lock.
   return save_old_value_at_eax;           /* but it not the real original value of *lock */
}

从代码中可以看出,cpu执行xchg时save_old_value_at_eax并不是真正的原始值。 您应该通过 xchg 指令获取旧/原始值,而不是在执行 xchg 之前保存它。 (“它不是真正的旧值/原始值”是指,如果另一个 CPU 在此 CPU 保存值之后但在此 CPU 执行 xchg 指令之前获取锁,则此 CPU 将获得错误的旧值,并认为它占用了锁定成功,因此,两个 CPU 同时进入 C.S.)。您已将读取-修改-写入指令分成三个指令,整个三个指令都不是原子的(即使您将锁定前缀移动到 xchg)。

我猜你以为锁定前缀会锁定全部三个指令,但实际上锁定前缀只能用于它所附加的唯一指令(并非所有指令都可以附加) 对于 xchg,我们不需要 SMP 上的锁定前缀。引用自 linux_kernel_src/arch/x86//include/asm/cmpxchg.h

/*
 * Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
 * Since this is generally used to protect other memory information, we
 * use "asm volatile" and "memory" clobbers to prevent gcc from moving
 * information around.
 */

我的建议:

  1. 不要重复自己,请使用 linux 内核的自旋锁。
  2. 不要重复你自己,如果你想实现自旋锁,请使用 linux 内核的 xchg()、cmpxchg()。
  3. 了解有关说明的更多信息。您还可以了解 linux 内核是如何实现的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-27
    • 2016-08-12
    • 1970-01-01
    相关资源
    最近更新 更多