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)

__resそれはまたはであることに注意してください__ex_flag

 __res |= __ex_flag;

したがって、ldrexまたはstrex操作のいずれかが失敗した場合、チェックは失敗します。

ldrex注:排他的アクセスが失敗した後に値にアクセスした場合。strex失敗し、値は保存されません。これについての詳細は、情報センターにあります。

STREX命令は、ワードのメモリへの条件付きストアを実行します。専用モニターがストアを許可する場合、操作はメモリー位置を更新し、操作が成功したことを示す値0を宛先レジスターに返します。専用モニターがストアを許可しない場合、操作はメモリー位置を更新せず、宛先レジスターに値1を返します。

__ex_flags=1重要なのは、排他的アクセスが失敗した場合、ロードまたはストアのいずれかでカーネルがそれを認識します。__res=1失敗しなかったとしても、ミューテックスがすでにロックされているため__res=0xFFFFFFFF、その時点でカーネルはそれを認識します。ミューテックスがロックされたために排他的アクセスが失敗したかどうかは関係ありません。

さて、私が見る唯一の問題は、それがカウントに保存されることですが、ミューテックスをロックした人がロックを解除する0xFFFFFFFFと、おそらく再び増分されます。つまり、複数のスレッドがミューテックスを待機する方法である可能性があります。これはあなたのリンクのコメントからです:

一度デクリメントされた場合、それはゼロではありません。または、専用ストアでの紛争のためにストアバックが失敗した場合、ロックが成功するまでロックが再試行される低速パスを介してすぐにベイルアウトします。

于 2012-11-12T09:56:21.117 に答える