検索
連載

マルチタスクを実装し、その原理を理解しようH8マイコンボードで動作する組み込みOSを自作してみよう!(4)(3/3 ページ)

連載「H8マイコンボードで動作する組み込みOSを自作してみよう!」の第4回。今回は、“タスク切り替え”の動作原理を理解しながら、マルチタスクを実装し、よりOSらしく発展させていきます。

PC用表示 関連情報
Share
Tweet
LINE
Hatena
前のページへ |       
※本記事はアフィリエイトプログラムによる収益を得ています

6.タスク切り替えの実装

 ここでは、KOZOSのタスク制御の実装について、簡単に説明します。

 以下のリスト17が、割り込みの入口です。具体的には「シリアル割り込み」の入口であり、ブートローダー側が持っている処理です。この処理は、割り込みハンドラとして登録されているため、シリアルで文字受信が行われて、割り込みが入った際に、リスト17の処理が呼ばれることになります。


……(中略)……
 
        .global _intr_serintr
#       .type   _intr_serintr,@function
_intr_serintr:
        mov.l   er6,@-er7
        mov.l   er5,@-er7
        mov.l   er4,@-er7
        mov.l   er3,@-er7
        mov.l   er2,@-er7
        mov.l   er1,@-er7
        mov.l   er0,@-er7
        mov.l   er7,er1
        mov.l   #_intrstack,sp
        mov.l   er1,@-er7
        mov.w   #SOFTVEC_TYPE_SERINTR,r0
        jsr     @_interrupt
        mov.l   @er7+,er1
        mov.l   er1,er7
        mov.l   @er7+,er0
        mov.l   @er7+,er1
        mov.l   @er7+,er2
        mov.l   @er7+,er3
        mov.l   @er7+,er4
        mov.l   @er7+,er5
        mov.l   @er7+,er6
        rte
リスト17 割り込みの入口(intr.S)

 リスト17の処理はアセンブラで書かれていますが、行っていることはそれほど難しいことではありません。ER0〜ER6の汎用レジスタの値をスタック上に保存し、「_interrupt()」という関数を呼び出しています。これは、図3のコンテキストの退避と関数呼び出しに当たる操作です。また、最後の「rte」命令が、図3のRFI命令の実行に相当します。

 リスト18〜20は、KOZOSのタスク制御部分です。リスト18ではタスク制御用に、「kz_context」「kz_thread」「readyque」という3つの構造体を定義しています。

/* スレッドコンテキスト */
typedef struct _kz_context {
  uint32 sp; /* スタックポインタ */
} kz_context;
 
/* タスクコントロールブロック(TCB) */
typedef struct _kz_thread {
  ……(中略)……
 
  kz_context context; /* コンテキスト情報 */
} kz_thread;
 
/* スレッドのレディーキュー */
static struct {
  kz_thread *head;
  kz_thread *tail;
} readyque[PRIORITY_NUM];
 
static kz_thread *current; /* カレントスレッド */
static kz_thread threads[THREAD_NUM]; /* タスクコントロールブロック */
 
……(後略)……
 
リスト18 タスク制御用の構造体の定義(kozos.c)

 「kz_context」は、タスクのコンテキストの保存用の構造体で、図4のコンテキストの保存先に当たるものです。H8用のKOZOSでは、汎用レジスタの値はスタック上に保存されるため、コンテキストとしてはスタックポインタの値のみを保存するようにしています。

 「kz_thread」は、タスクの各種パラメータの保存用の構造体です。このような構造体は一般に「TCB(Task Control Block)」と呼ばれます。さまざまなパラメータの保存の他に、コンテキストの保存領域も持たせています。

 「readyque」は、タスクの「レディーキュー」と呼ばれるものです。実行可能なタスクはリンクリストにより、キュー状に管理されています。

 「current」は、現在実行中のタスクを指すポインタで、(リスト中のコメントでは「カレントスレッド」になっていますが)「カレントタスク」などと呼ばれます。

 リスト19は、KOZOSの割り込み処理部分です(thread_intr())。まず、タスクのコンテキストとして、TCBにスタックポインタを退避します。その後、割り込みに応じた処理を呼び出し、「schedule()」が呼ばれます。「schedule()」では、スケジューリングが行われ、次に動作するタスクを選出します。さらに、「dispatch()」を呼び出すことで、そのタスクのコンテキストをレジスタに復元し、タスクの動作を再開させます。

……(中略)……
 
/* 割込み処理の入口関数 */
static void thread_intr(softvec_type_t type, unsigned long sp)
{
  /* カレントスレッドのコンテキストを保存する */
  current->context.sp = sp;
 
  /*
   * 割込みごとの処理を実行する。
   * SOFTVEC_TYPE_SYSCALL、SOFTVEC_TYPE_SOFTERRの場合は
   * syscall_intr()、softerr_intr()がハンドラに登録されているので、
   * それらが実行される。
   */
  if (handlers[type])
    handlers[type]();
 
  schedule(); /* スレッドのスケジューリング */
 
  /*
   * スレッドのディスパッチ
   * (dispatch()関数の本体はstartup.sにあり、アセンブラで記述されている)
   */
  dispatch(&current->context);
  /* ここには返ってこない */
}
 
……(後略)……
 
リスト19 KOZOSのタスク制御(kozos.c)

 リスト20は、スケジューリング処理です。タスクのレディーキューを検索し、見つかったタスクを変数「current」に設定することでカレントタスクとしています。

……(中略)……
 
/* スレッドのスケジューリング */
static void schedule(void)
{
  int i;
 
  /*
   * 優先順位の高い順(優先度の数値の小さい順)にレディーキューを見て、
   * 動作可能なスレッドを検索する。
   */
  for (i = 0; i < PRIORITY_NUM; i++) {
    if (readyque[i].head) /* 見つかった */
      break;
  }
  if (i == PRIORITY_NUM) /* 見つからなかった */
    kz_sysdown();
 
  current = readyque[i].head; /* カレントスレッドに設定する */
}
 
……(後略)……
 
リスト20 タスクのスケジューリング(kozos.c)

 リスト21は、タスクのディスパッチ処理です。これもアセンブラで書かれていますが行っていることはそれほど複雑ではなく、引数としてタスクのコンテキストへのポインタが渡されるため、その先(正確にはスタック上)に退避されているレジスタの値を復元し、rte命令を呼ぶことで処理を再開しています。

……(中略)……
 
        .global _dispatch
#       .type   _dispatch,@function
_dispatch:
        mov.l   @er0,er7
        mov.l   @er7+,er0
        mov.l   @er7+,er1
        mov.l   @er7+,er2
        mov.l   @er7+,er3
        mov.l   @er7+,er4
        mov.l   @er7+,er5
        mov.l   @er7+,er6
        rte
リスト21 タスクのディスパッチ処理(startup.s)

7.次回

 今回は、マルチタスクを実装しました。次回はこれらのタスクを発展させ、“実践的なコンソール応答プログラム”を作成してみます。お楽しみに! (次回に続く)


筆者紹介:

坂井弘亮(さかいひろあき)


某企業でネットワーク系の開発を行いながら、個人で組み込みOS「KOZOS」の開発や書籍/雑誌記事執筆、各種セミナーでの発表やイベント出展、勉強会の開催など多方面で活動中。IPAセキュリティ&プログラミングキャンプ 2010講師。著書は「12ステップで作る組込みOS自作入門」など多数。


モノづくりが大好き!(筆者Webサイト)

KOZOSのブログ(筆者ブログ)



Copyright © ITmedia, Inc. All Rights Reserved.

前のページへ |       
ページトップに戻る