雑記帳
ここはhideyosiの雑記帳です。テケトーに書き散らしてるだけなので間違っていたりとは普通にしてます。信用度は相当低いことをあらかじめご了承を。またご覧のようにWikiを使ってますが、hideyosi意外は書き込めません。
16日目
- 複数のタスクへの対応。
TASK構造体。個々のタスクと考えてよい。
TASKCTL構造体。この構造体の中に全てのタスクが納まっている。そして現在稼動中のタスクや総数を記憶。つまり、このシステム全体のタスクを管理しているただ一つの構造体。
task_init関数。タスクを一つ初期化し、稼動できる状態にする。内訳は
struct TASK *task_init(struct MEMMAN *memman)
{
int i;
struct TASK *task; /* タスクを一つ準備する。
/*----------------------------------------------------------------------------*/
/* これまででは、
struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT;
set_segmdesc(gdt + 何番目?, 103, (int) どのtss構造体?, AR_TSS32);
・・・と、こういう指定でtssをGDTにセットしていた。 */
/*----------------------------------------------------------------------------*/
/* ここはまあ、前と同じだが・・・・ */
struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT;
/*これ以降が違う。GDTの何番目にセットするのか。セットするtss構造体はどれなのか?
という情報を、以下のプログラムで自動的に探し出してセットしている*/
/* ちなみにtaskctl構造体がデカイのでメモリをゲットしているところ。
taskctl = (struct TASKCTL *) memman_alloc_4k(memman, sizeof (struct TASKCTL));
/* ここにあるforで0〜最大タスク個数まで繰り返す。空いている番号が見つかったら
そこを新しいタスクとする。これにより、GDTの何番目を使うのか、tssがどの
タスク内のものなのかがわかる*/
/*↑・・・っと思い込んでたが大間違いだった。
/*ここは、とにかくGDTの3(TASK_GDT0)〜最大数までのGDTテーブルを一気にtss化して
/*予約してしまうのだ!さらに、taskctl内のtasks0[]と一対一に対応させちゃう。
/*なので、以降は単に「どのtasks[?]が空いてるかな?」を探し、空きが見つかったら
/*そのtasks0[?]に当て込めば自動的にtssも設定させると!。こういう仕掛けか!
for (i = 0; i < MAX_TASKS; i++) {
taskctl->tasks0[i].flags = 0;
taskctl->tasks0[i].sel = (TASK_GDT0 + i) * 8;
set_segmdesc(gdt + TASK_GDT0 + i, 103, (int) &taskctl->tasks0[i].tss, AR_TSS32);
}
/*上記のGDTの予約?のおかげで、もうGDTは気にしなくていいのだ!
/*以降は、task_allocさえすれば、自動的にタスクがすぐ走れる状態で
/*1個準備される。
/*以下は、今動いている自分自身(HariMain。これまでの仮想的なtask_aのこと)を
/*ひとつのタスクとして登録しているだけ。
task = task_alloc();
task->flags = 2; /* 動作中マーク */
taskctl->running = 1;
taskctl->now = 0;
taskctl->tasks[0] = task;
load_tr(task->sel);
task_timer = timer_alloc();
timer_settime(task_timer, 2);
return task;
}- たくさん勘違いしていたが、このtask_init関数は、ほぼ一度だけやれば以降はしなくていい。タスクをシートのように管理するための単なる下地作りに過ぎないのだ。
- これ以降、タスクを新設したい場合はtask_alloc関数を使う。この関数は
struct TASK *task_alloc(void)
{
int i;
struct TASK *task; /*とりあえずtask構造体を一つ用意する*/
for (i = 0; i < MAX_TASKS; i++){ /*このforループで、taskctl内にある */
/*tasks0[]配列を上からチェックする。*/
if (taskctl->tasks0[i].flags == 0 { /*もしflagsが0。つまり使用されていないtasks0[]があったら */
task = &taskctl->tasks0[i]; /*よし!ここだ!上で今回用意したtask構造体をこのtasks0[]とする */
task->flags = 1; /*そこをとりあえず使用中とするためマークする。(確保するわけ) */
task->tss.eflags = 0x00000202; /*これ以降は、まったく新しいタスクの
/*tssを準備したのだから、初期化処理をする。*/
task->tss.eax = 0;
:
:
task->tss.ldtr = 0;
task->tss.iomap = 0x40000000;
return task;
}
}
}- これによって全ての準備が出来上がった。しかし、まだ走っていない。走らせるには、task_run関数で指令してやらないといけない。
Last-modified: 2024-01-06 (Sat) 22:39:13 (JST) (709d) by