或曰

木曜日, 5月 10, 2007

スクリプト D&I (13) マルチスレッド対応

設計時点での決定事項。
  1. non-preemptive
  2. 親子関係を持つ
  3. スレッド間のリッチな通信機能は用意しない。
システムプログラミングや複数CPUマシンで効率的に動かすプログラムを記述するのに使うわけじゃないので、これで十分。

実装に関して、まずはスレッド固有のリソース(資源)と共有されるリソースの区別から。

共有リソース
  • 仮想機械の一部レジスタ
    • ステータスワード
  • 実行対象のバイトコード
  • グローバル変数
  • 文字列データ
固有リソース
  • 仮想機械の一部レジスタ
    • 実行中の命令を格納しておくレジスタ (pw)
    • プログラムカウンタ (pc)
    • スタックフレームポインタ (fp)
    • スタックポインタ (sp)
  • スタック領域
こんなところかな。

これまでグローバル変数をスタック下位領域に割り当てていたが、これだと固有/共有リソースがごっちゃになって都合が悪いため、別領域に割り当てるよう修正。コード生成ルーチン、仮想機械、あとはkンパイル済みのバイトコードのシリアライズ処理部分にちょろっと手を入れる。ここまでは簡単。

スレッド関連のAPIを決める必要があるが、まずスレッド生成はシンプルにスレッド開始のエントリポイントとなる関数を指定する方法で。Win32 の beginthread() や POSIX Thread の pthread_create () 方式。

下準備として型システムの拡張。これまで型は
  • float
  • handle
  • int
  • string
  • void
を実装済みで、関数ポインタ型は用意してない。また型の属性として「関数の型として使える」「引数の型として使える」というのを用意してある。void foo(void a) といった宣言をエラーにするため。

今回の API ではスレッド開始のエントリポイントを引数として渡す必要がある。C言語だと関数ポインタ型を使うところだけど、ポインタを実装する気はないので thread 型を用意。


// スレッドのエントリポイント
thread thread_main(void) {}

void main()
{
// スレッド作成
// ここで他にも引数を渡せるようにするかは要検討
sysThreadCreate(thread_main);
}


thread 型は変数として使う必要はないが引数としては使いたいので、この二つの変数属性を分離 [354:405]

これで文法的な処理は終わったので、本格的に API 設計と仮想機械の拡張に手をつけるか。

ラベル: