view TaskManager/Changelog @ 18:0c9341da4522

*** empty log message ***
author gongo
date Sun, 10 Feb 2008 11:39:21 +0900
parents ee339757428d
children b4f6da36607f
line wrap: on
line source

2008-02-08  Wataru MIYAGUNI  <gongo@cr.ie.u-ryukyu.ac.jp>

	* add: kernel/ppe/SymTable.cpp
	今まで func[] = {add, sum, ...}
	とかやってかっこわるい言われまくってたので
	話し合いの通り Symbol Table みたいなものを作ることに

	// 疑似コードね
	struct sym_table {
	  char *sym;     // シンボル
	  void *address; // シンボルが示すアドレス
	} sym_table[] = {{"Sum", &Sum} , {"Draw", &draw}};

	int fd = get_fd("Sum");
	void *addr = get_address(fd);
	
	table には "Sum" と "Draw" っていう二つのシンボルが登録されている。
	例えば、ユーザ(カーネル?)が "Sum" ってシンボルにアクセスしたい場合、
	まずは get_fd で "Sum" に対する、file descripter を返す。
	ユーザは、その fd に従って get_address を取得することが出来る。
	TaskManager 的な使い方をするなら

	// 俺は今、Draw 関数を使うタスクを生成したい
	int fd = manager->open("Draw");
	manager->create_task(fd, size, in, out, func);
	manager->open では get_fd と同じ使い方です。

	まだ改良の余地ありそうですが、今は動いてるってことで。


	- 補足
	なぜ file descripter と表すか

	OS の昨日として、 fopen とかと同じ使い方もできるじゃない!

	
	
	* Todo: task が task を生成する際の処理
	今まで、 task が行う作業は、演算のみを行うような
	単純な実装に決め打ちされているわけです。
	しかし、OS なんかだと、タスク中から別のタスクを生成するとか
	ありありだと思われる。てか今のテストプログラムでなった。

	Test/Sum にあるプログラムで使われるタスク

	- init2 // 貧相な名前ですまない
	  演算する数値とかバッファの初期化

	- sum1
	  ある範囲の整数 (i から i+16 とか) の総和

	- sum2
	  sum1 で求められた、複数の範囲の総和を一つにまとめる
	  (ex. 複数の sum1 が 1->16, 17->32, 33->48 の総和を計算し、
	       sum2 で 上の3つの総和を計算する
	       要は 1->48 の総和を分割するっていうプログラムね

	- finish
	  sum2 で求まった値を表示

	この Sum というプログラム、というか OS と言おう。SumOS ね。
	SumOS は最初に TaskManager (所謂 kernel) を起動し、
	init を起動する。init では、予め決められたタスクである
	init2 と finish の二つのタスクを create して登録する。
	init2 と finish には依存関係がある (init2 が終わったら finish)
	init2 の中で、sum1 と sum2 というタスクが作られる。
	sum1 と sum2 にも依存関係はある (sum1 が終わったら sum2)
	
	今の実装だと、タスクが終了して初めて次のタスクへ行く。
	まあ当たり前なんだけど、例えばそのタスクの中で
	新たにタスクが作られた場合、そのタスクが終了するまでは
	実行されなくなってしまう。
	でまあ、今は、manager->create_task される度に
	manager->run とかして、無理やり起動してる訳さ。
	何が無理矢理かっていうと、scheduler の役目をしている
	SpeManager (これも名前変えないと) を2度呼び出してる訳。
	つまり、タスク中でタスクを作る度に、SpeManager オブジェクトを
	new してるわけさ。いいのか?いや、動いてるけどね?

	ちなみに、Cell version だと spe が勝手に取っていってくれるから
	大丈夫かなと思いつつ、もし spe を1つしか使わない設定だったら微妙。

	要するに、タスク中でタスクが作られる場合の処理を考えないとね。
	
2008-02-07  Wataru MIYAGUNI  <gongo@cr.ie.u-ryukyu.ac.jp>

	* memo: プログラミングの姿勢
	scheduler とか、task の管理をする部分は
	kernel programing のつもりで、
	example とか、task に割り当てる処理を決めたりする部分は
	user programing のつもりで。

	それぞれ違った視点で見る必要がある

	* memo: OS というもの
	OS 起動の流れ

	- PC の電源を入れる
	- BIOS が立ち上がる (OpenFirmWare, EFI, BIOS)
	- 起動デバイスをチェック (優先度とか種類とか)
	- 起動デバイスから Boot loader を起動
	  + BIOS によって、認識できるファイルシステムが違う(だっけ?)
	  + ファイルシステムのどこに Boot Loader があるか知っている
	- Boot Loader が kernel を起動
	  + ネットワークブートの場合、TCP/IP や
	    ネットワークデバイス(イーサとか?)のドライバを持ってる必要がある
	- kernel は、最初に scheduler を起動する
	- scheduler の初期化 (init を呼ぶ?)
	- init では、事前?に設定されているスクリプトとかを呼ぶ
	  + linux とかだと /etc/rc にあるやつを init が呼ぶ
	- login form が起動

	補足 こっからユーザ
	- login する
	- shell を呼ぶ
	  + login shell かどうか確かめる
	- ユーザに設定されてる起動スクリプト?を実行
	- 晴れてログイン

2008-02-06  Wataru MIYAGUNI  <gongo@cr.ie.u-ryukyu.ac.jp>

	* kernel/spe/*.cpp: new と placement new
	現在、spe kernel のタスクは、切り替わる毎に
	new/delete を繰り返しています。今はこれでいいんだけど、
	速度的にも、いずれは直さないといけないと思うわけで。
	で、予め allocate された領域を利用した placement new を使えば
	new よりもそれなりに早くなるっぽい。
	例題として、与えられた回数分 new/delete を繰り返すプログラムと、
	同じ回数分、placement new したときの速度の比較

	for (int i = 0; i < num; i++) {

	<   task = new Task;
	<   task->init(i);
	<   task->printID();
	<   delete task;
	---
	>   task = new(buff) Task; // buff = malloc(BUFF_SIZE);
	>   task->init(id);
	>   task->printID(id);
	}
	
	placement new では、delete の必要は無い。
	その中で新たに allocate してるなら必要かもしれないが。
	速度比較は以下。no_new が placement new で、ln_new が new/delete 。

	% ./a.out 10 // 10 回
	no_new:         time: 0.012135(msec)
	ln_new:         time: 0.003572(msec)

	% ./a.out 100
	no_new:         time: 0.022453(msec)
	ln_new:         time: 0.018989(msec)

	% ./a.out 1000
	no_new:         time: 0.115277(msec)
	ln_new:         time: 0.136335(msec)

	% ./a.out 10000
	no_new:         time: 1.056156(msec)
	ln_new:         time: 1.322709(msec)

	% ./a.out 100000
	no_new:         time: 10.622221(msec)
	ln_new:         time: 13.362414(msec)

	% ./a.out 1000000
	no_new:         time: 109.436496(msec)
	ln_new:         time: 136.956872(msec)

	10、100 回だと負けてるが、まあ無視しよう(ぇ
	回数が多くなるにつれて、ほんの少しだが no_new が勝ってる。
	どうなんだろうね。ちなみに printID を無くすと

	% ./a.out 1000000
	no_new:         time: 0.008512(msec)
	ln_new:         time: 27.100296(msec)

	I/O に左右され過ぎ。まあそんなもんだろうけどさ。