6

並行/並列 GC の目的で、mprotect syscall によって提供されるメモリ順序の保証 (つまり、複数のスレッドでの mprotect の動作または mprotect のメモリ モデル) に興味があります。私の質問は(コンパイラの並べ替えがない、または十分なコンパイラバリアがあると仮定して)です

  1. スレッド 1 がスレッド 2 の mprotect によってアドレスで segfault をトリガーした場合、スレッド 1 の segfault のシグナル ハンドラで syscall が確認される前に、すべてがスレッド 2 で発生することを確認できますか? スレッド 1 でロードを実行する前に、完全なメモリ バリアがシグナル ハンドラに配置されるとどうなるでしょうか。

  2. スレッド 1 が、スレッド 2 によって PROT_NONE に設定されたアドレスで揮発性ロードを実行し、セグメンテーション違反をトリガーしなかった場合、これは 2 つの間の関係の前に発生するのに十分ですか。または別の言い方をすれば、2 つのスレッドが実行する場合 (*gaとして開始され0p読み取り専用で開始されたページ アライン アドレスです)

    // thread 1
    *ga = 1;
    *(volatile int*)p; // no segfault happens
    
    // thread 2
    mprotect(p, 4096, PROT_NONE); // Or replace 4096 by the real userspace-visible page size
    a = *ga;
    

    aスレッド 2 が になるという保証はあります1か? (スレッド 1 で segfault が観察されず、他のコードが変更されないと仮定します*ga)

私は主に Linux の動作、特に x86(_64)、arm/aarch64、および ppc に関心がありますが、他のアーキテクチャ/OS に関する情報は歓迎されます (Windows の場合、mprotect を VirtualProtect に置き換えるか、それが何と呼ばれるものでも....)。これまでのところ、x64 および aarch64 Linux での私のテストでは、これらの違反は示唆されていませんが、私のテストが決定的であるかどうか、または動作が長期的に信頼できるかどうかはわかりません.

mprotect一部の検索では、許可が削除されたときにアドレスがマップされたすべてのスレッドで TLB シュートダウンを発行する可能性があることが示唆されています。将来のカーネル コードの最適化によって、この保証が破られる可能性がある場合。

1週間前にこれについて尋ねたLKMLの投稿を参照してください。まだ返信はありません...

編集:質問についての明確化。私は、tlb の撃墜が私が探している保証を提供する必要があることを認識していましたが、そのような動作が信頼できるかどうかを知りたいです。言い換えれば、そのようなリクエストがカーネルによって発行される理由は何ですか。何らかの順序保証を提供するためでなければ必要ないからです。

4

1 に答える 1

4

だから私はここに投稿した翌日にメカニカル・シンパシー・グループでこれを尋ね、ギル・テネから答えを得た. 彼の許可を得て、ここに彼の回答の要約を示します。含まれていない不明な点がある場合に備えて、完全なスレッドをここで入手できます。

全体的な動作については、OS に期待できます。

(「OSが満たさないのは驚くべきことです」のように):

  1. mprotect() の呼び出しは、呼び出しの前後に発生するロードとストアに関して完全に順序付けされています。これは、CPU および OS レベルで簡単に達成される傾向があります。これは、mprotect がトラップを含むシステム コールであり、トラップが完全な順序付けを伴うためです。[奇妙な非リング遷移実装 (例えば、カーネル内実行など) では、保護呼び出しはおそらく、この順序付けの仮定をエミュレートする責任があります]。

  2. mprotect の呼び出しは、保護要求がプロセス内のあらゆる場所で意味的に保持されるまで返されません。mprotect() 呼び出しがフォールトの原因となる保護を設定する場合、この mprotect() 呼び出しの後に発生するスレッド上のすべての操作はフォールトする必要があります。同様に、mprotect() 呼び出しがフォールトを防止する保護を設定する場合、この mprotect() 呼び出しの後に発生するすべてのスレッドでの操作は、フォールトしないようにする必要があります。

これは基本的に、他のスレッド上の影響を受けるページでのメモリ操作が、スレッド呼び出しと同期されることを意味しますmprotect。より具体的には、元の質問で言及されている 2 つのケースの両方が保証されていると期待できます。いえ

  1. 影響を受けるページ フォールトの 1 つのスレッドで mprotect 呼び出しが原因でロードが発生することが観察された場合、このフォールトは mprotect() 呼び出しの後に発生するため、mprotect の前に発生したすべてのメモリ操作を監視できます。

  2. 影響を受けるページの 1 つのスレッドでの読み込みが mprotect 呼び出しの無効化に失敗しないことが観察された場合、読み込みは mprotect 呼び出しの前に発生し、mprotect 呼び出しとその後のコードは読み込みの後に発生し、すべてのメモリを観察できます。ロード前に発生する操作。

また、推移性が機能しない可能性があることも指摘されました。つまり、あるスレッドのフォルト ロードが、別のスレッドの非フォルト ロードの後に​​続くとは限りません。これは、(事実上) tlb フラッシュの非原子性が原因で、異なるスレッド/CPU が異なる時間にアクセス許可の変更を監視することによって引き起こされる可能性があります。

于 2017-05-04T01:34:19.057 に答える