Next: Up: Previous:

仮定とマシン依存の詳細を明らかにする

  StackThreads が動くために C コンパイラのコード生成方式に 対して置いている仮定は次のようになる さらに, Cの手続き呼びだしに対しては4つの情報を必要とする. それらは, である. パラメタのサイズと caller の FP の場所はブロックしたスレッドの ために必要である. Epilogue コードアドレスとリターンアドレスの 場所は, ブロックしたスレッドと, ブロックしたスレッドから switch_to_parent への呼び出しの鎖の中の全ての 手続きについて必要である.

我々の実装はSparc version 8 [41] の呼びだし慣例 の下での無修正のGNU C コンパイラバージョン2.7.2を 使用して完成されている. レジスタ使用慣例として, 我々は, レジスタウィンドウを使用しない -mflat オプションを 使用した. この慣例はレジスタウィンドウを使用する伝統的なCバイナリ との互換性を維持する.

figure194

figure203

         図3.6: GNU C コンパイラにおける, 
                -mflat オプション(レジスタウィンドウを使用しない)
                をつけたときのスタックフレームの配置. alloca 領域の
                ちょうど二つ上のワードはcallerのFPとリターンアドレスである. 

我々の環境ではパラメタのサイズは, 現在の手続きの パラメタの個数をワードで返す 組み込みの関数, __builtin_args_info(0)によって得られる. Epilogue コードアドレスは, 図3.5に示すように, 手続きの終わりにラベルを置き, そのアドレスを && オペレータで獲得することによって得られる . リターンアドレスと caller の FP の場所はより直接的ではない. GNU C コンパイラのスタックの配置を図3.6に示す. それらは局所変数のセーブエリアの最も低い2ワードに, callerのFPを最も下に, リターンアドレスをその次に配置する. オフセットは全ての手続きを通じて, FPからも, SPからも, 定数ではない. しかし, 幸運にも, 局所変数領域のすぐ下は alloca による スタック確保のためのものであり, すべての他の alloca の要求の前に, 一番下のワードのアドレスを, alloca(例えば alloca(0) )によって ゼロバイト(!)の要求を行なうことによって得られる .

まとめると, スレッドが最終的に switch_to_parent で 終わるかもしれない手続きを呼び出すときには, (1) alloca(0) の結果, (2) その手続きの epilogue コード のアドレス (3) その手続きに対する __builtin_args_info(0) の結果を保持する, スタックに確保されたデスクリプタを渡してやる. そのような手続きが最終的に switch_to_parent を 呼び出す他の手続きを呼び出すときには, 次の手続きに対し, (1),(2), そして, 前のデスクリプタへの リンクを渡す. 我々は上の情報をスタック上に準備するマクロを 提供している. 下の例では, 前者を「SET_THREAD_DESC」と, 後者を「SET_LINK_DESC」と呼ぶ.



Mitsubishi Research Institute,Inc.
Mon Feb 24 19:27:36 JST 1997