1

GCC アトミック ビルトインを使用して単純な fetchAndSet を実装するための単純で効率的な方法を探しています。ここで最も近いのは__sync_lock_test_and_setビルトインですが、他の関数のように完全なメモリバリアを発行するわけではなく、他のすべての関数は操作 (add、sub、xor など) を実行するか、条件付き (比較およびスワップ機能)。任意のポインター データを保持する変数を操作しようとしているため、これらは機能しません。

私が思いついた最高のものは次のようなものでした:

type *fetchAndSet(type **loc, type *newvar) {
  while (1) {
    type *oldvar = __sync_fetch_and_add(loc, 0);
    if (__sync_bool_compare_and_swap(loc, oldvar, newvar)) return oldvar;
  }
}

... 言い換えれば、メモリの場所で値をアトミックにフェッチし、その古い値を新しい値に正常に置き換えるとすぐにループから抜け出します。この解決策にはあまり満足していません。なぜなら、これは単一のアトミック操作ではないからです。また、2 つ以上のスレッドが同じメモリ位置を争っている場合、飢餓の危険性が非常に高くなります。だから、私の質問:これを行うためのより良い方法はありますか?

4

2 に答える 2

1

gcc 4.6 のビルトイン (リンクごと) を使用すると、sync で値を取得する必要がないため、(理想的には) 1 つの sync 命令のみを発行するようにサンプル コードを変更できます。

type *fetchAndSet(type **loc, type *newvar) {
  while (1) {
    type *oldvar = *loc;
    if (__sync_val_compare_and_swap(loc, oldvar, newvar) == oldvar) return oldvar;
  }
}

2 番目のオプションは、__sync_lock_test_and_set() の呼び出しの前に __sync_synchronize() を追加して、完全なバリアが存在するようにすることです。

gcc 4.6 のビルトインを超えて、R の回答を参照してください。

于 2013-05-12T00:58:18.680 に答える