私は、サボテン スタックを使用して並列プログラムを実装する MS Windows の言語であるPARLANSEを実装しました。スタック チャンクは関数ごとに割り当てられ、ローカル変数、式の一時的なプッシュ/ポップ、およびライブラリの呼び出し (ライブラリ ルーチンが動作するためのスタック スペースを含む) を処理するのにちょうどいいサイズです。このようなスタック フレームは、実際には 32 バイトまで小さくすることができます。
コードが愚かなことをしてハードウェアトラップを引き起こさない限り、これはすべてうまく機能します...その時点で、Windowsはx86マシンコンテキスト全体を「スタックに」プッシュすることを主張しているようです。FP/MMX などを含めると、これは約 500 バイト以上になります。登録します。当然のことながら、32 バイトのスタックで 500 バイトのプッシュを行うと、クラッシュしてはならないものが破壊されます。(ハードウェアはトラップにいくつかの単語をプッシュしますが、コンテキスト全体ではありません)。
[編集 2012 年 11 月 27 日: Windows が実際にプッシュするスタックのばかげた量の測定された詳細については、これを参照してください]
Windows に例外コンテキスト ブロックを別の場所 (スレッド固有の場所など) に保存させることはできますか? その後、ソフトウェアはスレッドで例外ヒットを取得し、小さなスタック フレームをオーバーフローさせることなく処理できます。
これは不可能だと思いますが、もっと多くの聴衆に聞いてみようと思いました。これを引き起こす可能性のあるOS標準の呼び出し/インターフェースはありますか?
OS で実行するのは簡単です。MS に、デフォルトで現在の従来の動作を有効にするために初期化されるコンテキスト ストレージの場所「contextp」をオプションで定義させることができれば、簡単なことです。次に、割り込み/トラップ ベクター コードを置き換えます。
hardwareint: push context
mov contextp, esp
... と ...
hardwareint: mov <somereg> contextp
test <somereg>
jnz $2
push context
mov contextp, esp
jmp $1
$2: store context @ somereg
$1: equ *
someregなどを保存するために必要な明らかな変更があります。
[私が今やっていることは、各関数の生成されたコードをチェックすることです。トラップを生成する可能性がある場合 (例: ゼロ除算)、またはデバッグ中 (不正なポインター deref の可能性など) がある場合は、FP コンテキスト用にスタック フレームに十分なスペースを追加します。スタック フレームのサイズは ~~ 500 ~ 1000 バイトになり、プログラムはそこまで再帰できなくなります。したがって、実行可能な解決策がありますが、デバッグが複雑になります]
編集 8 月 25 日: 私はこの話を、MS の誰が実際に気にかけているかを明らかにする権限を持っている Microsoft の社内エンジニアに伝えることができました。解決へのかすかな希望があるかもしれません。
編集 9 月 14 日: MS Kernal Group Architect はこの話を聞いて同情しています。彼は、MS は (提案されたような) 解決策を検討するだろうが、サービス パックに含まれる可能性は低いと述べた。Windows の次のバージョンを待つ必要があるかもしれません。(はぁ…老けるかも…)
編集: 2010 年 9 月 13 日 (1 年後)。Microsoft 側でのアクションはありません。私の最近の悪夢: Windows X64 で 32 ビット プロセスを実行しているトラップを取得すると、割り込みハンドラーが 32 ビット コンテキストをプッシュするように偽装する前に、X64 コンテキスト全体がスタックにプッシュされますか? それはさらに大きくなります(整数レジスタの2倍、幅の2倍、SSEレジスタの2倍(?))?
編集: 2012 年 2 月 25 日: (1.5 年が経過しました...) Microsoft 側からの反応はありません。彼らは私のような並列性を気にしていないだけだと思います。これはコミュニティへの不利益だと思います。通常の状況下で MS が使用する「ビッグ スタック モデル」は、大量の VM を消費することにより、任意の瞬間に実行できる並列計算の量を制限します。PARLANSE モデルを使用すると、実行中/待機中のさまざまな状態で 100 万個のライブ「グレイン」を持つアプリケーションを作成できます。これは、1 億ノードのグラフが「並行して」処理される一部のアプリケーションで実際に発生します。PARLANSE スキームは、約 1Gb の RAM でこれを行うことができ、かなり扱いやすいです。MS 1Mb の「ビッグ スタック」でそれを試した場合、スタック スペースのためだけに 10^12 バイトの VM が必要になります。
編集: 2014 年 4 月 29 日: (4 年が経ちました)。 MSはSOを読んでいないと思います。 私は PARLANSE で十分なエンジニアリングを行ったので、デバッグ中または FP 操作が進行中の場合にのみ大きなスタック フレームの代償を支払うだけなので、これに対処するための非常に実用的な方法を見つけることができました。MS は失望し続けています。さまざまなバージョンの Windows によってスタックにプッシュされるものの量は、ハードウェア コンテキストの必要性を超えて、大幅かつ著しく異なるようです。この変動性の一部は、MS 以外の製品 (ウイルス対策など) が例外処理チェーンに鼻を突っ込んでいることが原因であるというヒントがあります。なぜ彼らは私のアドレス空間の外からそれを行うことができないのですか? いずれにしても、FP/デバッグ トラップに大きなスロップ ファクターを追加するだけで、これらすべてを処理し、フィールドで必然的な MS システムがその量を超えるのを待ちます。