1

これは C++ インライン asm です。

inline bool swap_if_null(head_t **p, head_t *np) {
      register head_t *old;
      asm volatile(
          "lock;\n\t"
          "cmpxchgq %3, %2"
          : "=a"(old)
          : "0"(0), "m"(*p), "r"(np)
          : "memory");
      return old == NULL;
}
4

2 に答える 2

3

関数は でアトミックな比較交換を行っており*p、これは状態 であると予想されnp、目的の新しい値はNULLです。関数はこれを 1 回だけ実行し、操作が成功したかどうかを返します。

いくつかの説明: マシン命令は( lock cmpxchgq R, MAT&T 構文で)ですR。変更する (これは " "、つまり "2 番目の入力オペランド"、つまり)。np%3M%2*p

新しい値は register にあると予想されます%rax。このレジスタは、0 番目の出力オペランドとして変数 in に関連付けられていますが、「0 番目の入力オペランドと同じ」を意味するoldため、最初の入力オペランドでもあります。"0"しかし、入力時に値は変数にバインドされず、代わりに " 0" に設定されます。つまり、%rax最初はゼロであり、命令oldがそれを参照し、操作の結果を含んだ後です。

コンペア アンド スワップの性質上、操作が成功して変更されない場合、または操作が失敗してメモリの現在の%rax値がゼロの場合、 (したがって) はゼロになります。どちらの場合も、関数は成功を返します。つまり、「ヘッドは現在ゼロです」。old%rax

于 2013-08-21T00:04:11.780 に答える
1
inline bool swap_if_null(head_t **p, head_t *np) {
  register head_t *old;
  asm volatile(
      "lock;\n\t"
      "cmpxchgq %3, %2"
      : "=a"(old)
      : "0"(0), "m"(*p), "r"(np)
      : "memory");
  return old == NULL;
}

この関数は、が NULLの場合、*pandの内容を「交換」します。np*p

これは、 (Compare and Exchange, quadword [64 bits]) 命令を使用して、つまり、( )cmpxchgqの 64 ビット値を*p(引数 0、つまり) と比較し、値がメモリと一致するかどうかによって行われます。 、( )に新しい値を格納します。最後に、置換が行われた場合にメモリ位置にあった値が含まれているため、置換されたときにそれがあったことを確認できます。プレフィックスにより、プロセッサがメモリに排他的にアクセスできるようになり、現在、他のプロセッサがこの場所に書き込むことはできません。 %20raxraxnp%3oldNULLlock

これは、リンクされたリストの最後に何かを挿入するときにミューテックスを使用しないようにするために行われます。複数のスレッドが挿入しようとしている場合、要素をリストの最後に追加する時点で、リストの最後が本当に NULL であることを確認する必要があります。ドロップ」アイテム)。cmpxchgこのような「値がこの値なら、別の値に置き換える」という指示が出されます。

于 2013-08-21T00:04:23.060 に答える