1

現在、Linux カーネルのスピンロックはすべて「チケットベース」のスピンロックを使用していることがわかりました。しかし、それの ARM 実装を見た後、「load-add-store」操作がまったくアトミックではないため、私は混乱しています。以下のコードを参照してください。

 74 static inline void arch_spin_lock(arch_spinlock_t *lock)
 75 {
 76         unsigned long tmp;
 77         u32 newval;
 78         arch_spinlock_t lockval;
 79 
 80         __asm__ __volatile__(
 81 "1:     ldrex   %0, [%3]\n"   /*Why this load-add-store is not atomic?*/
 82 "       add     %1, %0, %4\n"
 83 "       strex   %2, %1, [%3]\n"
 84 "       teq     %2, #0\n"
 85 "       bne     1b"
 86         : "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
 87         : "r" (&lock->slock), "I" (1 << TICKET_SHIFT)
 88         : "cc");
 89 
 90         while (lockval.tickets.next != lockval.tickets.owner) {
 91                 wfe();
 92                 lockval.tickets.owner = ACCESS_ONCE(lock->tickets.owner);
 93         }
 94 
 95         smp_mb();
 96 }

ご覧のとおり、81 ~ 83 行目で lock->slock を "lockval" にロードし、それを 1 増やしてから lock->slock に格納します。

ただし、これがアトミックであることが保証されている場所はどこにもありませんでした。したがって、次のことが可能です。

異なる CPU を使用する 2 人のユーザーが同時に lock->slock を自分の変数 "lockval" に読み込んでいます。次に、「lockval」をそれぞれ 1 つずつ追加してから、元に戻します。

これにより、これら 2 人のユーザーが同じ「番号」を取得し、「所有者」フィールドがその番号になると、両方ともロックを取得し、いくつかの共有リソースで操作を行います!

カーネルがスピンロックでそのようなバグを持つことはないと思います。私はどこか間違っていますか?

4

1 に答える 1

2

STREXARM がその名前を使用しない場合でも、このコードにはLoad Link-Store Conditionalセマンティクスがあります。

操作はアトミックに完了するか、失敗します。

アセンブラ ブロックは失敗をテストし (tmp変数は失敗を示します)、新しい値 (別のコアによって更新された値) を使用して変更を再試行します。

于 2013-11-03T22:54:07.567 に答える