スレッド 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に示す.