雑記帳
ここはhideyosiの雑記帳です。テケトーに書き散らしてるだけなので間違っていたりとは普通にしてます。信用度は相当低いことをあらかじめご了承を。またご覧のようにWikiを使ってますが、hideyosi意外は書き込めません。

16日目 anchor.png Edit

  • 複数のタスクへの対応。

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関数で指令してやらないといけない。

最終更新: 2024-01-06 (土) 22:39:13 (JST) (108d) by