x86.h static inline uint xchg(volatile uint *addr, uint newval)

トップページ
jupiteroak.hatenablog.com


x86.h
https://github.com/mit-pdos/xv6-public/blob/master/x86.h#L120

static inline uint xchg(volatile uint *addr, uint newval)
{
  uint result;

  // The + in "+m" denotes a read-modify-write operand.
  asm volatile("lock;
               xchgl %0, %1"
               : "+m" (*addr), "=a" (result)
               : "1" (newval)
               : "cc");
  return result;
}

xchg関数は、引数addr(アドレス)で指定されたメモリに格納されている値と引数newvalで指定された値を交換します。

引数 uint *addr
交換対象となる値が格納されているメモリのアドレスです。

引数 uint newval
交換対象となる値です。

戻り値 uint result
引数addr(アドレス)で指定されたメモリに元々格納されていた値です。


処理の内容

インラインアセンブラ

asm volatile("lock;
               xchgl %0, %1"
               : "+m" (*addr), "=a" (result)
               : "1" (newval)
               : "cc");

関数内のインラインアセンブラを解釈すると以下のようになります。

アセンブリ言語命令

lock
xchgl [addr], eax

インラインアセンブラの命令を実行する前の状態

・eaxレジスタ(入力レジスタのリストに1、出力レジスタのリストにaで表記され、%1に対応している)
引数newvalの値が設定されています。

lock

lockプリフェックスは、次に続く命令が実行されている間、LOCK信号をアサートします(LOCK信号がアサートしている間は、排他制御を保証します)。

xchgl [addr], eax

xchg命令によって、引数addr(アドレス)で指定されたメモリに格納されている値とeaxレジスタに設定されている値が交換されます。

引数addr(アドレス)で指定されたメモリに元々格納されていた値をリターン

return result;

インラインアセンブラの命令実行後は、eaxレジスタの値がresultに格納されているので、その値を戻り値としてリターンします。


参考
https://docs.oracle.com/cd/E19455-01/806-3773/instructionset-128/index.html