リアルタイム

デッドラインを絶対に落としてはならない部分は、ネイティブの Zig タスクとして書きます。VM はその周りを指揮します。プリエンプトするタイマがあるので、暴走したスクリプトがネイティブのタスクを止めることはできません。

プリミティブ群

スケジューラは、ハード RTOS のプリミティブ群をアーキ非依存のコードとして持ちます。

プリミティブ機構
優先度継承ミューテックス待たされた高優先度の待ち手が所有者を自分の優先度へ引き上げ、unlock で戻す。タスクにつきミューテックス 1 つ(ネストや連鎖継承は未実装)
デッドラインタイマタイマはナノ秒で次のイベントに合わせて張る。眠っているタスクの起床・周期タスクのリリース・ラウンドロビンのスライス、その最も早いもの。固定周期で刻むのではない
時間付き待ちの有界化イベント発生か n ナノ秒後の早い方で起床する
デッドライン超過検出レート単調の暗黙デッドラインで、超過回数を数える
CPU 時間計上中断されたタスクに実行 tick を課金する
CPU 予約 / 時間隔離タスク毎の予算と周期。予算を超えたタスクは補充まで抑制する
ソフトウェアウォッチドッグheartbeat の生存確認。固まったタスクを検出できる
RM スケジューリング解析双曲線境界 Π(Cᵢ/Tᵢ + 1) ≤ 2。すべて整数演算
高分解能クロックx86 は PIT 較正の TSC、riscv は rdtime、aarch64 は CNTVCT/CNTFRQ、ARMv6-M は µs TIMER
サブ µs ビジー待ちナノ秒クロックをスピンする

**x86_64・riscv64・aarch64 は、この一式を起動して走らせています。**RP2350 は下の「デッドライン充足」の 2 タスクを起動します(タスク表の上限が 8 で、一式は 12 要るため)。RP2040 は 1 つも起動していません。

**RM 解析は受付ゲートではありません。**呼べば「このタスク集合が収まるか」を答える関数であって、spawn がそれを参照して生成を拒否する、という形にはなっていません。

スケジューラがデッドラインを守る

**スケジューラにとっての「いま」はナノ秒クロックで、タイマは次のデッドラインに合わせて張ります。**眠っているタスクの起床・周期タスクのリリース・ラウンドロビンのスライス、その最も早いものに。固定周期で刻むわけではないので、要求できる最短のデッドラインに、tick が下限を作りません。sleepwait_period はナノ秒で受け、tick 版はそれを薄く包んだだけです。これに要るハードウェア——絶対値のワンショット比較器——は、5 つのターゲットが最初から持っていました。

本物の制御則が、スケジューラ配下のふつうの周期タスクとして、実機で 1 kHz で回り、スケジューラがデッドラインを守ります。

これは本物の control()(ソフトフロートのカスケード PID + 四元数)で、OS がループの中にいます。スケジュールし、CPU 時間を計上し、ネットワークや VM 飛行アクターとチップを分け合いながら。これが RTOS かどうかを決めるのは、この数字です——スケジューラが本物の 1 kHz タスクを時間どおりに出す、実機で、ネットワークとミッションが同じチップを奪い合う中で。

同じ制御則が、HIL フライトコントローラとして、同じ実機で Wi-Fi 越しに配送ミッション(島、投下、帰投、着陸)**を飛ばします。**こちらは HIL フレームのレートで回ります。上の 1 kHz はスケジュールされた RT タスクのほうです。1 つの制御則の 2 つの実証であって、同じループではありません。

合成のタスク対(C/T = 2/10 と 5/40、利用率 32.5%。双曲線境界が schedulable と判定する集合)も、x86_64・riscv64・aarch64・RP2350 で全デッドラインを守ります。解析は走らせる前に判定を出力するので、予測と実測が互いに突き合わされます。**ただしそれは、通るように選んだ集合です。**本物の制御則は、そうではありません。

測定値

**制御則の最悪値を、両ボードで実測しました。**各ボードが起動時に、割り込みをマスクして、到達可能な飛行包絡線の 2 万入力の敵対的掃引で control() を回します。どちらも 125 MHz なので、数値は直接比較できます。

どちらのコアもキャッシュも分岐予測も投機も持たないので、実測の最大値がそのままエンジニアリング WCET です——隠れたテールがありません。掃引は決定的で、ボード上で再現できます。

スケジューラ自身の応答の床は、riscv64 で実測して、割り込み駆動で 約 1.1 µs(Sstc タイマ)、タイマがファームウェア呼び出しになる場合で 約 3.5 µs。これが「OS があなたのタスクに到達するまでの代金」であり、周期と突き合わせるべき数字です。

決定的な仮想時間-icount shift=0)の下では、絶対デッドラインの待ちがジッタ 0 を示します。機構が厳密であり、負荷のかかったホストで見えるジッタはホストのものであって OS のものではない、ということです。

実機の x86 で残る残差は、ファームウェアのシステム管理割り込み(マスク不能)と、キャッシュやマイクロアーキの効果です。これより下の決定性には、専用ハードか FPGA ソフトコアが要ります。

制御ループの最悪実行時間

HIL(ハードウェア・イン・ザ・ループ)フライトコントローラが、Lambda OS 上で動きます。コントローラは本物です。実機、実演算、実モータ出力を、シミュレートされた機体(プラント)が駆動します。これは実機を飛ばす前にフライト制御を検証する標準的な方法です。デッドラインの挙動を、決定論的に、再現可能に詰められます。実飛行にはできないことです。ここでの検証は、設計上 HIL を軸にしています。

**飛ぶのは貨物配送のミッションです。**デモの全体——フォールト応答、プリフライト関門、HIL リグ——は 飛行制御 のページにあります。

デッドラインが安全かどうかを決めるのは、制御演算そのものの最悪実行時間、すなわちソフトフロートのカスケード PID + 四元数です。各ボードが起動時に、割り込みをマスクして純粋な演算時間だけを取り、到達可能な飛行包絡線の 2 万入力の敵対的掃引で自分の値を計測します——姿勢球面の全域、±35 rad/s のジャイロ、±400 m の位置誤差、1.0〜1.4 kg の全質量域。平方根と除算がデータ依存の最悪パスを通るよう入力を選びます。

なぜ実測の最大値を WCET と呼べるのか

Cortex-M0+ には、**キャッシュも、分岐予測も、投機も、マスク不能な SMI もありません。**だから、実測の向こうに隠れている値がない。ばらつきの元はデータ依存のソフトフロートのコストだけで、そこはミッションが広く踏んでいます。

キャッシュ付きスーパースカラのチップでは実測 max が真の最悪値より下に出るため静的解析が要りますが、M0+ では実測の最大値がそのままエンジニアリング WCET です。これが、ハードなデッドラインに「遅いが決定的」が勝つ理由です。生のスループットは低く、fib(25) の解釈実行に 24 秒かかりますが、デッドラインを背負う制御演算の WCET は 190 µs です。その遅さは、デッドライン経路から意図的に外した VM インタプリタに閉じ込めてあります。

この測定が及ぶ範囲