C++のグリーンスレッドでは、ほとんどがboost::coroutine2
と同様のPOSIX関数makecontext()/swapcontext()
のようなリサーチを行い、boost::coroutine2
の上にC++グリーンスレッドライブラリを実装する予定です。両方とも、ユーザーコードが新しい関数/コルーチンごとにスタックを割り当てる必要があります。C++グリーンスレッドのスタック割り当て
ターゲットプラットフォームはx64/Linuxです。私は私の緑色のスレッドライブラリを一般的な使用に適しているようにしたいので、必要に応じてスタックを展開しなければなりません(妥当な上限は、例えば10MBです)、あまりにも多くのメモリが使用されていないとき)。私はスタックを割り当てるための適切なアルゴリズムを理解していません。いくつかのグーグル後
、私はいくつかのオプションを自分で考え出し:
- 使用スプリット・スタックは、コンパイラ(gccの-fsplitスタック)で実装されますが、分割スタックは、パフォーマンスのオーバーヘッドがあります。パフォーマンス上の理由から、Goはすでにスプリットスタックから離れています。
mmap()
で大きなメモリチャンクを割り当てます。カーネルは、物理メモリを未割り当てのままにしておき、スタックにアクセスするときにだけ割り当てることができます。この場合、私たちはカーネルの慈悲に満ちています。- は、
mmap(PROT_NONE)
で大きなメモリ領域を予約し、SIGSEGV
シグナルハンドラを設定します。シグナルハンドラでは、SIGSEGV
がスタックアクセスによって発生した場合(アクセスされたメモリが予約されている大きなメモリ空間内にある場合)、必要なメモリをmmap(PROT_READ | PROT_WRITE)
で割り当てます。このアプローチの問題は次のとおりです。mmap()
は非同期の安全ではなく、シグナルハンドラ内で呼び出すことはできません。これはまだ実装することができます非常にトリッキー:メモリ割り当てのためのプログラム起動中に別のスレッドを作成し、pipe() + read()/write()
を使用して、信号ハンドラからスレッドにメモリ割り当て情報を送信します。オプション3について
さらにいくつかの質問:
- が、私はこのアプローチのパフォーマンスオーバーヘッドわからないんだけど、カーネル/ CPUが実行する方法も/悪いメモリ空間は、のために非常に断片化されたとき何千もの電話番号
mmap()
? - 割り当てられていないメモリがカーネル空間でアクセスされる場合、このアプローチは正しいですか?例えば
read()
と呼ばれると?
グリーンスレッドのスタック割り当てには、他にも(より良い)オプションがありますか?グリーンスレッドスタックは他の実装でどのように割り当てられますか? Go/Java?
'mmap'はPOSIXに従った安全で非同期されていないが、それは実際にそこのLinuxでの安全とほとんどすべての合理的な、使用可能なUNIXバリアントを非同期れます。 –
@ChrisDoddなぜ 'mmap'が緑のスレッドに適しているのか聞いてみることはできますか?私は専門家ではないが、私は知りたかった。 – VermillionAzure
@ChrisDoddこれについてのmanページ/リンクが見つかりませんでした。私にリンクを教えてください。 – user416983