めのん@ひとりプログラミング同好会

このブログはすべてフィクションであり、実在の人物、団体とは一切関係ありません

Zig版ASP3カーネルのext_ker

こんにちは、めのんです!

今朝予告したとおり、今回はZig版TOPPERS/ASP3カーネルのサービスコールであるext_kerを見ていくことにします。

前回見ていったsta_kerはカーネルを開始するサービスコールでしたので、それと対になるext_kerはカーネルを終了させるためのサービスコールです。 実際にコードを見てみましょう。

pub fn ext_ker() noreturn {
    var silLock = sil.PRE_LOC();

    traceLog("extKerEnter", .{});

    // 割込みロック状態に移行
    sil.LOC_INT(&silLock);

    // カーネル動作の終了
    traceLog("kernelLeave", .{});
    kerflg = false;

    // カーネルの終了処理の呼出し
    target_impl.callExitKernel();
}

これ自体はほとんど(Zigの言語仕様という意味では)見所がありません。 ですが、せっかくですので今回は最後に呼び出しているtarget_impl.callExitKernel関数をもう少し深掘りしてみることにします。

target_impl.callExitKernel関数の定義はtarget_implなのでターゲット依存部にあるはずです。 検索してみると、スタートアップルーチンがあったcore_kernel_impl.zigで見つけることができました。

pub fn callExitKernel() noreturn {
    // 例外ネストカウントを1にする.
    excpt_nest_count = 1;

    // 非タスクコンテキスト用のスタック領域に切り換え,exit_kernelに分
    // 岐する.
    asm volatile(
     \\  ldr sp, 5f
     \\  ldr sp, [sp]
     \\  b %[exit_kernel]
     \\
     \\ 5:
     \\  .long %[istkpt]
     :
     : [exit_kernel] "s" (startup.exitKernel),
       [istkpt] "s" (&cfg._kernel_istkpt),
    );
    unreachable;
}

この関数もそんなに見所はありませんね。 真ん中あたりでstartup.exitKernelを呼び出していますので、先ほどのext_kerの直後に定義されていたexitKernelも見てみましょう。

pub fn exitKernel() noreturn {
    // 終了処理ルーチンの実行
    for (cfg._kernel_terrtnb_table) |terrtnb| {
        terrtnb.terrtn(terrtnb.exinf);
    }

    // ターゲット依存の終了処理
    target_impl.exit();
}

exitKernel関数の中では、静的APIのATT_TERで登録された狩猟処理ルーチンが呼び出されています。 あとはtarget_impl.exit関数の呼び出しですね。

target_impl.exit関数はターゲット依存部で定義されるのですが、Cのホスト環境であればexit関数を呼び出すことになるんでしょうね。 このあたり微妙に言語仕様に絡んでくるところだと思います。

Cのexit関数であれば、atexit関数で登録した関数を呼び出したあと、オープンされているストリームを全部閉じて、OSに制御を戻すことになります。 C++なら非局所オブジェクトのデストラクタも呼び出されるのでしょうね。

Zigの場合はatexit関数とかあるんでしょうか? 私はまだそのあたりがよくわかっていません。 非局所オブジェクトのデストラクタみたなものはないのかなと思っています。

今回、sns_kerまで見たいなと思っていたのですが、ちょっと長くなってしまったの次回回しにします。

それでは!!