(toppers-users 462) RE: TOPPERS/JSP の実装で教えてください。

mandrake mandrake @ imail.plala.or.jp
2002年 8月 6日 (火) 03:22:27 JST


松川さん、はじめまして。

豊橋技術科学大学の若林と申します。

ご質問の項目に関して答えられる範囲で回答します。
長文になってしまいましたが、お付き合いください。
 #詳しい方、フォローよろしくおねがいします

---
1.1 tcb->tskctxbにPCが含まれている理由

これはコードの可読性/汎用性を高めるためだと理解しています。スタック上に
PCやPSWの情報を載せても、結果は同じだと思います。変数の局所性もそれほど
変わらないと思います。

ちなみに、PCをTCBに含むことによるメリットとしては、
 ・_kernel_exit_and_dispatch関数がディスパッチ先スタックに依存しない
 ・高速な内部RAMを持つプロセッサへの対応
があります。

前者は可読性や理解のしやすさに貢献しています。また、作成途中のHALが妙な
暴走をする(大抵スタック破壊)場合、デバッグ時における有力なデータアクセス
ブレーク対象アドレスのひとつになります。
後者はV850やM32Rプロセッサのように、内部に高速なRAMを持っている場合、
ldscriptをちょっといじってカーネルが使用している変数を内部RAMに配置する
ことで、カーネル動作をより高速にし かつ 高い予測可能性を保たせることがで
きます (大抵 内部RAMはNo-wait)。

デメリットとしては、TCBに入れてしまうことで余計なRAMが消費されているとい
う点があります。ですが、余計に消費されているのは "現在動いているタスクの
分" だけなので、TCBの中にPCを含めてもタスク1個分 = 4バイト余計に消費して
いるだけであり、代償として妥当な範囲だと思います。

あと、TCBのサイズが確か24バイトとかだった気がするので、ここにSPとPCを加
えて32バイトにすると、TCBの配列を扱うようなアドレス演算がちょっとだけ高
速になるというメリットもあります。

---
1.2 タスクの起動処理がactivate_rという関数に分けられている

これは各実装者の趣味だと思います。実装によってはactivate_rが要らないケー
スもあると思います。

私が書いた依存部(Win, V850, M32R)に関しては、activate_rではタスク処理に
相当する関数に渡す引数の準備と、脱出時にext_tskに飛ばすようにする処理し
かしていないです。

---
2. Caller-saved registersを退避しない理由

_kernel_dispatch関数を呼び出す前に呼出元の関数がそのレジスタの内容を退避
しているため、同じ内容の二重保存になってしまうからです。ディスパチャがす
べてのレジスタ情報を退避していたとしても、そのレジスタ情報は結果として復
帰後に一回も使われないまま再復帰が行われるため、最初の復帰処理が無意味な
ディスパッチオーバヘッドになってしまいます。ディスパッチオーバヘッドは
カーネルの性能指標のひとつでもあるため、出来る限り必要最低限のレジスタし
か退避しないようにしています。

---
3. 初期スタックに関して

その理解でいいと思います。
カーネル動作中のスタックは、依存部で好きに出来るので問題ないと思います。
またカーネル終了時ですが、カーネルが終了するのは能動的に_kernel_exit関数
を呼んだときなので、カーネル終了時の作業領域は呼出元のスタック上に確保さ
れるため、初期スタックとして使用していた領域をシステムスタックとして回収
しても問題ないと思います。V850/M32R依存部では、初期スタック=システムス
タック(非タスクコンテキスト用スタック)になっています。

---
4. システムクロックドライバ

TOPPERS/JSPでご指摘のような構成をしている最大の理由は、「システムクロッ
クドライバを取り外し可能にする」と目的のためです。

uITRON4.0では、カーネルがタイマのハードウェアに強く依存してしまうことを
避けるため、isig_timというAPIが新しく導入されました。その結果、カーネル
クロックを提供するためのルーチンはカーネルと分離可能になりました。
TOPPERS/JSPはこの特徴を受け、このような実装になっていると思います。

ちなみに、取り外し可能であることの利点ですが、ユーザが独自にドライバを作
りやすくなると言う点や、どなたかが今のTOPPERS/JSPのドライバよりも優秀な
ドライバを作り、提供しやすくなるといった点があります。

余談ですが、あるタスクのループ内の処理が全体のクロックになっているような
場合があるとします。このとき、システムクロックドライバを外し、ループのど
こかでisig_timをCPU例外などで呼び出すようにすると、時刻の単位が「回目の
ループ」になるカーネルが作れます。またストリーム処理などでは、データ受信
ごとにisig_timを呼び出すと、時刻の単位が「パケット目の受信」となるような
カーネルが作れます。内部の大部分が時刻以外の何かで動いているアプリケー
ションでは、このような使い方もアリだと思います。

---
 5. 遅延ディスパッチ

割込み出入り口のオーバヘッド、ディスパッチオーバヘッドが妥当な範囲であれ
ば、多分 特に問題ないように思います。

気をつける点があるとすれば、タスク例外処理ルーチンの呼出方でしょうか。頭
が整理できていないので詳しくは言えないのですが、安直に作ると優先度逆転現
象が起こったり、別途タスク例外専用ディスパッチャを作ることになりそうな気
がしています。

---

お仕事でしょうか? 移植作業は大変だと思いますが、がんばってください。

ちなみに移植作業に当たっては、一度 m68kのコード(コメント)をご覧になられ
ると誤解が少なくてよいと思います (各依存部を眺めていると系統樹が見えてき
ますが、その頂点がm68kです)。

以上 ご参考になれば幸いです。

--------
  わかばやし たかゆき (mailto:takayuki @ ertl.ics.tut.ac.jp)