Zig版ASP3カーネルのact_tsk
こんにちは、めのんです!
昨夜は久々に違う話題にしましたけど、ここのところずっとZig版TOPPERS/ASP3カーネルの話題を取り上げています。
今回はact_tskというサービスコールを見ていきたいと思います。 念のためact_tskについて少しだけ解説しておきますね。
act_tskはμITRONからあるサービスコールでタスクを起動するためのものです。 正確にいうとタスクを休止状態から実行可能状態に遷移させます。
静的APIのCRE_TSKでTA_ACTを指定したタスクはact_tskを呼ばなくても起動しますが、それ以外のタスクや一度ter_tskで休止状態にしたタスクはact_tskを呼ぶまで起動しません。 act_tskの呼び出しはキューイングできるので、キューイングされている状態でcan_tskやter_tskを呼べばキューが1つずつ減っていくんだったと思います(ちょっとうろ覚えです)。 といっても、ASP3カーネルではキューイングできるのは1つまでなので、あまりキューイングという感じはしません。
では、早速act_tskの定義を見てみましょう。 kernel/task_manage.zigに定義があります。
/// /// タスクの起動[NGKI3529] /// pub fn act_tsk(tskid: ID) ItronError!void { var p_tcb: *TCB = undefined; traceLog("actTskEnter", .{ tskid }); errdefer |err| traceLog("actTskLeave", .{ err }); try checkContextUnlock(); //[NGKI1114] if (tskid == TSK_SELF and !target_impl.senseContext()) { p_tcb = p_runtsk.?; //[NGKI1121] } else { p_tcb = try checkAndGetTCB(tskid); //[NGKI1115] } { target_impl.lockCpu(); defer target_impl.unlockCpu(); if (isDormant(p_tcb.tstat)) { make_active(p_tcb); //[NGKI1118] requestTaskDispatch(); } else if ((p_tcb.p_tinib.tskatr & TA_NOACTQUE) != 0 or p_tcb.flags.actque == TMAX_ACTCNT) { return ItronError.QueueingOverflow; //[NGKI3528] } else { p_tcb.flags.actque += 1; //[NGKI3527] } } traceLog("actTskLeave", .{ null }); }
今回は見所がたくさんありますね。
まずはerrdeferです。 関数の中でtry演算子を使うと、エラーが発生したときにただちに関数からリターンするんですけど、そのときに呼び出される処理を登録するためのものです。 今回はtraceLogを呼び出すようになっています。
次に、
p_tcb = p_runtsk.?; //[NGKI1121]
この部分ですが、うしろに .? を付けることでp_runtskがnullだったときには何もしないことを意味しています。
先ほどはerrdeferが登場しましたが、今度はdeferが登場しています。 これはエラーが発生したかどうかに関係なく、現在のスコープから抜ける際に呼び出す処理を登録しています。 tryブロックにfinallyを使える言語は多いですが、そんな感じでしょうね。
μITRONやC版ASP3カーネルのact_tskの返却値型はERですけど、このact_tsk関数はItronErrorとvoidのエラー共用体になっています。 Zig版ASP3カーネルのサービスコールは、エラーが発生せず真偽値を返すものをのぞけば、全部エラー共用体を返すようになっています。
C版と同じシグニチャを持つ関数も用意されているようで、kernel/c_api.zigに定義があります。
// act_tskのC言語API export fn act_tsk(tskid: ID) ER { return callService(task_manage.act_tsk(tskid)); }
callService関数は、エラーが発生しなければE_OKにするなどの変換を行うためのものなので、サラッと流してもいいと思います。
というわけで今回はact_tskを見てみました。 関連するサービスコールということで、次回はcan_actを見ていきたいと思います。 余力があればter_tskも見ていきたいですね。
それでは!!