質問


Sunos Inが提供する原子操作を使用していますu003Csys/atomic.h>、それです
void *atomic_cas_ptr(volatile void *target, void *cmp, void *newval);

これで使用できるように、この関数によって返され、Callee関数CMPで渡される古い値が同じであるかどうかを確認する必要があります。
しかし、私は確かな疑いがあります:この関数が古い値へのボイドポインターを返しているので、それをvoid *を *古く呼んでいて、私はvoid *cmpを渡します、そして私はこれら2つの古いCMPとCMPを比較する必要があるので、私はどのように比較するつもりですかこの二つ ?そして、古いものを比較している間、私は何をするつもりですか?
本質的に、私がやりたいことは、これらの3つの引数を取り入れ、成功または失敗を示す真またはfalseのいずれかを返す別の関数内で、この関数をゆがめることです。
関して CAS, 、私はそれをロックフリー操作と呼ぶのは誤ったノーマーであると読んだ。そのため、CASはコストのかかる操作です。

役に立ちましたか?

解決

おそらく関数宣言があなたを混乱させた。この関数は、(何? target (これは本当にvoidへのポインターであるべきです*、すなわち void* volatile * target).

通常、CASプリミティブがブールではなく古い値を返している場合、このようなものでCASの成功を確認してください。

void* atomic_ptr; // global atomically modified pointer

void* oldval, newval, comparand; // local variables
/* ... */
oldval = atomic_cas_ptr( (void*)&atomic_ptr, /* note that address is taken */
                          comparand, newval );
if( oldval == comparand ) {
    // success
} else {
    // failure
}

したがって、Old_valとComparandを比較すると、同時に変化しないローカル変数を使用して作業します(グローバルAtomic_PTRが再び変更される可能性があります)、控除なしにポインター値を比較します。

あなたが望む機能は次のようにする必要があります:

bool my_atomic_cas_ptr(volatile void* target, void* comparand, void* newval)
{
    return (comparand == atomic_cas_ptr(target, comparand, newval));
}

一部のアルゴリズムでは、古い値(CASの前のもの)がわかっているはずであるため、前者から後者を簡単に構築できるので、boolではなく古い値を返すCASの原始的なものを持つ方が良いことに注意してください。複雑で非効率的です(正しい古い値を取得しようとする次のコードを参照してください MacOS CASプリミティブ それはブールを返します)。

void* CAS(void* volatile* target, void* comparand, void* newval)
{
    while( !OSAtomicCompareAndSwapPtr(comparand, newval, target) ) {
        void* snapshot = *target;
        if( snapshot!=comparand ) return snapshot;
    }
    return comparand;
}

CASロックメモリバスについては、ハードウェアに依存します。古いX86プロセッサには当てはまりましたが、最新のX86システムでは異なります。まず、中央バスはありません。 AMDのHyperTransportとIntelのQuickPathの相互接続に置き換えられました。第二に、最近のCPU世代では、ロックされた命令がすべてシリアル化されているわけではありません(参照 いくつかのデータ 異なるメモリアドレスのロックされた命令が干渉しないことを示す)。そして最後に、で 一般的に受け入れられている定義 ロックの自由は、システム全体の進歩の保証であり、の不在ではありません シリアル化同期.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top