2

私の知る限り、メモリバリアとして機能する pthread 関数があります (たとえば、ここでは clarifications -on-full-memory-barriers-involved-by-pthread-mutexes )。しかし、コンパイル時のバリアについてはどうでしょうか。つまり、コンパイラ (特に gcc) はこれを認識していますか?
言い換えれば - たとえば - gcc が並べ替えを実行しない pthread_create() の理由ですか?

たとえば、コードでは次のようになります。

a = 1;
pthread_create(...);

再注文が行われないことは確実ですか?
さまざまな関数からの呼び出しはどうですか:

void fun(void) {
    pthread_create(...);
    ...
}

a = 1;
fun();

fun() もコンパイル時間の障壁ですか (pthread_create() を想定)?
異なる翻訳単位の関数はどうですか?

一般的な gcc および pthreads の動作仕様に関心があることに注意してください。必ずしも x86 固有ではありません (さまざまな組み込みプラットフォームに焦点を当てています)。
また、他のコンパイラ/スレッド ライブラリの動作には興味がありません。

4

1 に答える 1

3

などのpthread_create()関数は外部関数であるため、コンパイラは、関数を呼び出す前に、外部関数に表示される可能性のある副作用 (グローバル変数への書き込みなど) を確実に実行する必要があります。コンパイルはa、最初のケースの関数呼び出しの後まで書き込みを並べ替えることができませんでした)aグローバルであるか、そうでなければ外部からアクセスできる可能性があると仮定します)。

これはどの C コンパイラにも必要な動作であり、実際にはスレッドとはほとんど関係ありません。

ただし、変数がローカル変数である場合、アドレスのようなものが取得されて外部で利用可能にされない限りa、コンパイラは関数呼び出しの後までそれを並べ替えることができる可能性があります (aそのことについてはメモリ内にまったく収まらない可能性があります)。aどういうわけか(スレッドパラメーターとして渡すなど)。

例えば:

int a;

void foo(void)
{
    a = 1;
    pthread_create(...);    // the compiler can't reorder the write to `a` past 
                            //  the call to `pthread_create()`

    // ...
}


void bar(void)
{
    int b;
    b = 1;
    pthread_create(...);    // `b` can be initialized after calling `pthread_create()`
                            // `b` might not ever even exist except as a something
                            //  passed on the stack or in a register to `printf()`

    printf( "%d\n", b);
}

これをより詳細に概説しているドキュメントがあるかどうかはわかりません - これは主に C の 'as if' ルールでカバーされています。5.1.2.3/3「プログラムの実行」にあるC99では。Cは、副作用が完全でなければならないシーケンスポイントを持つ抽象マシンによって指定され、プログラムは、副作用が必要ないとコンパイラーが推測できる場合を除いて、その抽象マシンモデルに従う必要があります。

上記の私の例では、コンパイラは通常、 が設定を必要としないfoo()ことを推測できないため、 を呼び出す前に値への設定の副作用を完了する必要があります。他の場所で使用されていないと推測できるグローバルな最適化を実行するコンパイラがある場合、それらは割り当てを遅らせたり省略したりする可能性があることに注意してください。ただし、その場合、他に副作用を使用しているものは何もないため、問題はありません。a = 1;pthread_create()a1pthread_create()a

于 2012-11-24T19:35:16.013 に答える