1

我有一个关于在 ARM 平台上的 Linux 内核中实现互斥锁的问题。

__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
{
    int __ex_flag, __res;

    __asm__ (

             "ldrex  %0, [%2]        \n\t"
             "sub    %0, %0, #1      \n\t"
             "strex  %1, %0, [%2]    "  //for ARMv6+ ,kernel use ldrex/strex implement mutex lock.

              : "=&r" (__res), "=&r" (__ex_flag)
              : "r" (&(count)->counter)
              : "cc","memory" );

             __res |= __ex_flag;    //How can we know the "strex" operation is successfully finished or not? 
                                    //The status of (atomic_t *count) is different in these two cases. 
                                    //I wonder this is a bug ,or I did not understand the lock mechanism so well.

      if (unlikely(__res != 0))
           fail_fn(count);
      }

非常感谢您对此问题的建议或回答。任何事情都会受到赞赏。

有关源代码的更多信息,请参阅;http://lxr.oss.org.cn/source/arch/arm/include/asm/mutex.h?v=3.5.2;a=arm

文件路径为:

linux-3.5.2/arch/arm/include/asm/mutex.h
4

1 回答 1

4

__res如果成功则为零

STREX{cond} Rd, Rm, [Rn] 存储到 Rn 中的地址,如果成功则在 Rd 中标记(如果成功,则 Rd = 0)

注意__resis or'd with__ex_flag

 __res |= __ex_flag;

因此,如果ldrexstrex操作中的任何一个失败,则检查失败。

注意:如果该值是在ldrex独占访问失败后访问的;strex失败并且该值将不会被存储。在信息中心有更多关于此的信息:

STREX 指令将一个字有条件地存储到内存中。如果独占监视器允许存储,则操作更新内存位置并在目标寄存器中返回值 0,表示操作成功。如果独占监视器不允许存储,则操作不会更新内存位置并在目标寄存器中返回值 1。

关键是,如果独占访问失败,无论是在加载还是存储时,内核都会知道它,因为__ex_flags=1或者__res=1,如果它没有失败,但互斥体已经被锁定,我们仍然会知道它,因为__res=0xFFFFFFFF那时它不会不管独占访问是否因为互斥锁被锁定而失败。

现在,我看到的唯一问题是它将存储0xFFFFFFFF到计数中,但是当锁定互斥锁的人解锁它时,它可能会再次增加,这意味着它可能是多个线程在互斥锁上等待的一种方式。这是来自您链接中的评论:

如果一旦递减它就不是零,或者如果它的回存由于独占存储的争议而失败,我们只需通过缓慢的路径立即退出,在该路径中重新尝试锁定直到成功

于 2012-11-12T09:56:21.117 回答