スレッド A はブロックしたスレッドfの
実行を再開できる条件を満たしているとする.
スレッド A は restart_thread(
c)
を
呼ぶことによって f を再開することができる. ここで
c は switch_to_parent
によって満たされたヒープの
コンテキストである. 基本的な操作は次のようになる.
スタックの頭にfの局所変数と入力パラメタの領域を
作り, f の callee-save register を回復し, SP と FP を新しい
フレームの場所にセットし, 再開ポイントにジャンプする.
f が終了するか再びブロックしたときには, f が
正しい callee-save register の状態とともに, 正しく
restart_thread
にリターンするように
注意を払わなければならない. これは f の epilogue コード列を
実行しても restart_thread
にリターンせず,
もともとの caller の callee-save register, SP, FPの値とともに
f のもともとの caller にリターンすることを意味する.
これに対する我々の解答は, 二つの部分からなっている.
一つめは, fが正しいFPとSPの値とともにrestart_thread
へ
リターンするように, restart_thread
は caller へのリンクを
保持している f のフレームのスロットを上書きする.
より具体的に言えば, caller のリターンアドレスと FP を
保存しているスロットを上書きする. 二つめは, restart_thread
は
f を再開する前に callee-save register を保存し, f が
リターンしたあと自分で callee-save register を回復する.
図3.4: ブロックスレッド f を回復する制御パス. f の スタックフレームをスタックの頭に作成したあと(1と2), (3) で f が restart_thread へリターンするように, リターンアドレスと親の FP を交換する. そのあと, (4) で callee-save register をセーブし, (5) で f がブロック したときに獲得された callee-save register を回復する. そのあと再開ポイントにジャンプする. f の epilogue は もはや有効ではない. よって, restart_thread は (4) で保存された callee-save register を自分で回復する.
まとめると, ブロックしたスレッドを再開することは
次のステップを含んでいる. (1) f のためにスタックフレームを
確保する. (2) 局所変数と入力パラメタをスタックにコピーする.
(3) f が restart_thread
にリターンできるように,
親へのリンク(リターンアドレスと親のFP)を restart_thread
への
リンクに置き換える.
(4) 全ての callee-save register を保存する. (5) f がブロック
したときに獲得された全ての callee-save register を回復する.
(6) 再開ポイントにジャンプする. f は無効な callee-save register の
状態で restart_thread
にリターンするので,
restart_thread
は f がリターンした後に
(4)で保存された callee-save register をすべて回復する.
f を再開し, 最終的に f が restart_thread
にリターンする
制御パスを図3.4に示す.