问题 旋转锁有问题吗?


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

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);
}

10496
2017-07-17 01:58


起源

我的补充是在上面。 - venus.w
优秀;它可能不是错误,但对我而言似乎很奇怪 spin_destroy() 用于释放未分配的内存 spin_init()。 (有没有 spin_alloc() 功能呢?) - sarnold
spin_destory可能过剩了。 - venus.w
也许这是过分的。但提供匹配 _init() 和 _destroy() 功能 是 很好,特别是如果你想在将来修改任何东西。 - sarnold


答案:


您的代码等于:

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 */
}

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

我猜你认为锁前缀会锁定整个三条指令,但实际上锁定前缀只能用于附加的唯一指令(并非所有指令都可以附加) 并且我们在SMP上不需要用于xchg的锁前缀。引自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内核如何实现它。

11
2017-07-17 03:39





我认为问题是锁定指令前缀仅适用于以下指令,因此您的交换不是原子的。有关详细信息,请参阅有关SO的其他答案: “锁定”指令在x86汇编中意味着什么?

我想如果你将锁定指令前缀移动到xchg,它将起作用。

编辑:这可能很有用(例如gcc程序集中的原子交换): http://locklessinc.com/articles/locks/

请注意,我认为我的原始答案实际上是错误的,进一步的谷歌搜索显示,如果自386以来自动引用内存,xchg将被锁定。


2
2017-07-17 02:56