雑記帳
ここは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) (309d) by