対応状況
Lambda OS は 5 つのターゲットで動きます。**すべての機能が、すべてのターゲットにあるわけではありません。**このページは、どれがどれかを示します。
| 済 | 動いている。実機かエミュレータかは末尾の表を参照 |
| 予定 | 設計は決まっており、残作業に入っている |
| 個別 | 汎用の実装は持たない。対象ハードウェア向けにエンゲージメントで実装する(ベアメタルの OS なので、貴社のボードのドライバは書く必要がある) |
| 無 | 対応予定なし。設計上の非目標、役割上そこに置かないもの、またはチップの制約 |
ノードの役割
分散アクターシステムでは、ノードに役割があります。MCU 列の「無」は、実装が追いついていないという意味ではありません。
- オーケストレータノード(x86_64 / riscv64 / aarch64)— 多数のアクターを抱えます。動的生成と監視、ローカルの名前レジストリは、アクターが多数いるからこそ意味を持ちます。
- エッジノード(MMU 無しの MCU)— 1〜2 個のアクターを持ち、ネットワークで協調する側。小さいチップに多数アクターの管理機構を載せるのは、分散アクターがそもそも避けるために存在する当のものです。
隔離
| x86_64 | riscv64 | aarch64 | RV32 MMU 無し | ARMv6-M MMU 無し | |
|---|---|---|---|---|---|
| アクターが非特権で走る | 済 ring 3 | 済 U-mode | 済 EL0 | 済 U-mode | 済 ¹ |
| カーネルへのゲートは 1 つ | 済 int 0x80 | 済 ecall | 済 svc | 済 ecall | 済 svc ¹ |
| アクターが別のアクターのメモリに届かない | 済 アクター毎のアドレス空間 | 済 アクター毎のアドレス空間 | 済 アクター毎のアドレス空間 | 済 アクター毎の PMP 領域 | 済 アクター毎の MPU 領域 ¹ |
| 起動時のプローブがそれを検証する | 済 #PF | 済 ストアフォルト | 済 EL0 フォルト | 済 ストアフォルト | 済 HardFault |
| アクターがカーネルのメモリにも届かない | 済 ³ | 済 | 済 | 予定 ⁴ | 予定 ⁴ |
| プリエンプトを跨いで FP を退避 | 済 FXSAVE | 予定 ⁵ | 予定 ⁵ | 済 FPU があれば | 無 FPU が無い |
| 敵対的バイトコードにも効く隔離 | 無 ⁶ | 無 ⁶ | 無 ⁶ | 無 ⁶ | 無 ⁶ |
¹ **隔離アクターを持つイメージで。**Cortex-M0+ では、隔離・Wi-Fi・分散が 1 つのイメージに収まり(実測 256 KB 中 208 KB)、制御ループと隔離アクターも 1 つのイメージに収まります。下の Cortex-M0+ のイメージ を参照。 ³ MMU を持つ 3 ターゲットは、いずれもアクター層の共有帳簿——名前レジストリ、pid→コンテキスト表、ロックワード——をカーネルメモリに置いています。FFI は ring 0 から届きますが、ring 3 からは届きません。VM のコア毎の実行状態ブロックも同様に閉じ込め済みで、アクターは 1 つのコアに固定されるため、そのアドレス空間はちょうどそのコアのブロックだけを許し、残りを拒みます。 ⁴ 実機の MMU 無し部品(RP2350 の NAPOT 限定 PMP、RP2040 の数個の MPU 領域)では領域数が少なく deny-by-default にできないため、閉じ込めは「広く許可してから兄弟を拒否する」形になります。アクターは兄弟には届きませんが、カーネルの帳簿には届きます。(bare RV32 の QEMU ビルドの TOR ベース PMP は deny-by-default です。)実機部品での deny-by-default は残作業です。 ⁵ 現状フックはスタブです。プリエンプトを跨いで浮動小数を保持するタスクが無い限り安全、という状態です。 ⁶ **設計上の非目標。**すべてのバイトコードは運用者自身のコンパイラから信頼経路で届く前提です。隔離は堅牢性の境界(バグの封じ込め)であって、マルチテナントの境界ではありません。
スケジューリングとリアルタイム
| x86_64 | riscv64 | aarch64 | RV32 | ARMv6-M | |
|---|---|---|---|---|---|
| 固定優先度プリエンプティブ、タスクはコアに固定 | 済 | 済 | 済 | 済 | 済 |
| RTOS プリミティブ群(優先度継承、時間付き待ち、デッドライン超過検出、CPU 時間計上、CPU 予約、ウォッチドッグ、RM 解析) | 済 | 済 | 済 | 済 デッドラインの組 ⁷ | 予定 ⁷ |
| デッドラインタイマ:クロックは ns、タイマは次のイベントに合わせて張る | 済 | 済 | 済 | 済 | 済 |
| RM で schedulable なタスク集合が、スケジューラ込みで全デッドラインを守る | 済 | 済 | 済 | 済 実機で | 予定 ⁷ |
| 本物の制御則が、スケジュールされた 1 kHz タスクとしてデッドラインを守る | — | — | — | 済 実機で ⁹ | 済 実機で ⁹ |
| マルチコア | 済 最大 4(ACPI MADT) | 済 SBI HSM | 済 PSCI CPU_ON | 済 2 コア | 済 2 コア |
| サブ µs のビジー待ち | 済 | 済 | 済 | 予定 ⁷ | 無 ¹⁰ |
| VM フレームの命令数ウォッチドッグ | 済 | 済 | 済 | 済 | 済 |
⁷ プリミティブ群はアーキ非依存のコードとしてスケジューラにあり、どのターゲットでもコンパイルされます。**x86_64・riscv64・aarch64 は、この一式を起動して走らせています。**RP2350 はデッドライン充足の 2 タスクを起動します(タスク表の上限が 8 で、一式は 12 要るため)。RP2040 は 1 つも起動していません。
⁸ **5 つのターゲットすべてが 2 コア目以降を起こします。**x86 は INIT-SIPI-SIPI、riscv64 は SBI HSM の hart_start、aarch64 は PSCI の CPU_ON、両 Pico は SIO FIFO のハンドシェイク(RP2350 は実機で確認済み)。
⁹ control()(ソフトフロートのカスケード PID + 四元数)が、スケジュールされたタスクとして片方のコアで 1 kHz で走り、もう片方がネットワークを回します。RP2350:1,741,824 ジョブ中、超過 0 回(周期 948.9〜1056.5 µs)、ミッションも動くフル配送飛行。RP2040:113,664 ジョブ中、超過 0 回(周期 998〜1002 µs)——264 KB に両方は載らないため VM ミッション無しの計測ビルド。±2 µs はジッタでなく 1 µs タイマの分解能の床です。
¹⁰ RP2040 のカウンタは µs 分解能の TIMER です。チップの制約であり、下限は 1 µs です。
アクター
| x86_64 | riscv64 | aarch64 | RV32 | ARMv6-M | |
|---|---|---|---|---|---|
型付きメールボックス(send / recv / msg_from / msg_a / msg_b) | 済 | 済 | 済 | 済 | 済 |
msg_tag | 済 | 済 | 済 | 予定 | 予定 |
send_remote — 別の機械のアクターを宛先にする | 済 | 済 | 済 | 済 | 済 ¹¹ |
動的 spawn(オーケストレータの機構) | 済 | 済 | 済 | 無 ¹² | 無 ¹² |
監視(monitor → MSG_DOWN → 再生成。オーケストレータの機構) | 済 | 済 | 済 | 無 ¹² | 無 ¹² |
ローカルの名前レジストリ(register_name / whereis) | 済 | 無 ¹³ | 無 ¹³ | 無 ¹³ | 無 ¹³ |
(node, pid) によるアドレッシング(node_ip / send_node / reply_node) | 済 | 予定 | 予定 | 予定 | 予定 |
| 双方向バッファ ABI(FFI 越しのポインタ) | 予定 | 済 TCP + ファイル | 済 ファイルのみ | 予定 | 予定 |
| フレームスキップによる障害復帰(エッジノード) | — | — | — | 済 ¹⁴ | 済 ¹⁴ |
| ノードを跨いだ監視・再供給(エッジノードの障害復帰) | 予定 ¹⁴ | 予定 ¹⁴ | 予定 ¹⁴ | 予定 ¹⁴ | 予定 ¹⁴ |
| 分散名前レジストリ(name → node, pid) | 予定 ¹⁵ | 予定 ¹⁵ | 予定 ¹⁵ | 予定 ¹⁵ | 予定 ¹⁵ |
| ホットコードアップグレード(走行中の差し替え) | 無 ¹⁶ | 無 ¹⁶ | 無 ¹⁶ | 無 ¹⁶ | 無 ¹⁶ |
| GC・クロージャ・動的型付け | 無 | 無 | 無 | 無 | 無 |
¹¹ ノードイメージ(隔離+無線+分散)で動きます。無線を積まないイメージでは、FFI は登録されていますが送り先がありません。
¹² 役割上、載せません。動的生成と監視は、多数のアクターを 1 チップに抱えて管理するための機構です。エッジノードは 1〜2 個を持ち、協調はネットワークで行います。
¹³ 役割上、載せません。これはローカルの「名前 → タスク index」レジストリで、アクターが多数いるオーケストレータで「consumer は常に index 1」の脆さを消すためのものです。2 アクターのエッジノードでは self() で役割が分かります。分散で必要なのはこれではなく、下の分散名前レジストリです。
¹⁴ エッジノードに合った障害復帰。オーケストレータ型の監視(動的生成)ではありません。暴走したフレームは VM のウォッチドッグが巻き戻し、ハードウェアフォルトを起こしたフレームはカーネルがスキップして、アクターの進捗を保ったまま次のフレームから再開させます。実機で、飛行中のフォルト注入に対してドローンが飛び続けることを確認済み。ノードを跨いだ監視は、未実装です。
¹⁵ いまは (node_ip, pid) と well-known ポートで、宛先を手で指定しています。「そのアクターがどのノードに居るか」を解決する分散レジストリは、ローカルの名前レジストリを移しても埋まりません。別の機構です。
¹⁶ バイトコードは起動時に差し替えます(下記)。走行中のコード入れ替えは対応予定がありません。
ネットワークとストレージ
| x86_64 | riscv64 | aarch64 | RV32 | ARMv6-M | |
|---|---|---|---|---|---|
| 同一のネットワークスタック(Ethernet → DNS、TCP クライアント+サーバ) | 済 | 済 | 済 | 済 Wi-Fi 上 ¹⁷ | 済 Wi-Fi 上 ¹⁷ |
| NIC ドライバ | 済 e1000 | 済 virtio-net | 済 virtio-net | 済 CYW43439 | 済 CYW43439 |
| 割り込み駆動の受信 | 済 | 予定 ¹⁸ | 予定 ¹⁸ | 無 ¹⁹ | 無 ¹⁹ |
| TCP:再送・輻輳制御・高速再送・SACK・3 接続 | 済 ²⁰ | 済 ²⁰ | 済 ²⁰ | 済 ²⁰ | 済 ²⁰ |
| 受信時のチェックサム検証(UDP / TCP) | 済 ²¹ | 済 ²¹ | 済 ²¹ | 済 ²¹ | 済 ²¹ |
| 機械を跨ぐアクターメッセージ | 済 | 済 | 済 | 済 ¹⁷ | 済 ¹⁷ |
| ブロックデバイス+再起動を跨ぐファイルシステム | 予定 | 済 virtio-blk | 済 virtio-blk | 個別 | 個別 |
| バイトコードを起動時に配送(焼き込みでなく) | 済 UART + TFTP ²² | 済 UART | 済 UART | 予定 | 予定 |
¹⁷ **実機で。**Pico W(RP2040)と Pico 2 W(RP2350)のどちらでも、非特権・ハードウェア隔離のアクターの隣でネットワークスタックが特権タスクとして走り、すべてが 1 つのイメージに入っています。
¹⁸ ドライバに割り込みフックはありますが、割り込みコントローラからそこへ配線されていません。ネットワークタスクがカードをポーリングします。
¹⁹ CYW43439 には、CPU に配線された受信割り込みがありません。チップの制約です。フレームは、ドライバが要求したときにバスから出てきます。
²⁰ 同時 3 接続。各接続がシーケンス状態・再送キュー・ウィンドウを自分で持ち、4-tuple 全体で多重分離します(RFC 793)。輻輳制御は接続毎の cwnd / ssthresh とスロースタート。重複 ACK 3 回で高速再送。SACK は双方向でネゴシエートし、順序外の到着を捨てずに保持します。ウィンドウスケーリングは提示しますが、こちら側のシフトは 0 です——大きな受信バッファを持たないためです。再送タイマは 400 ms から 3 s 上限で倍々、20 秒沈黙した接続は畳みます。
²¹ TCP と UDP のチェックサムは、送信時に擬似ヘッダ込みで計算し、受信時に検証します。合わない TCP セグメントは捨て、UDP は送信側が付けていれば検証します(値 0 は「省略」の意味で、IPv4 はそれを許しています)。IPv4 ヘッダと ICMP のチェックサムも検証します。
²² TFTP による取得は QEMU の fw_cfg に依存しており、実機の x86 では動きません。
Cortex-M0+ のイメージ
**隔離・Wi-Fi・分散は、1 つのイメージに収まります。**実測で 256 KB 中 208 KB、48 KB の余り。カーネルは 107 KB で、MPU 分割が要求する 128 KB の下です。無線のファームウェア(224 KB)は flash からチップへ直接ストリームされるので、そもそもホストの SRAM に載りません。
| ノード(隔離+無線+分散) | 飛行制御(ミッションアクター) | |
|---|---|---|
| ミッションが非特権・MPU 隔離 | 済 | 済 ²³ |
| Wi-Fi 上のネットワークスタック | 済 | 済 HIL リンク |
| 機械を跨ぐアクターメッセージ | 済 | — |
| ネイティブのカスケード PID 制御ループと安全包絡線 | — | 済(カーネル内) |
²³ ミッション — アップロードされる案件ごとの飛行計画 — が唯一の Lambda C アクターで、非特権・ハードウェア隔離です。**RP2040(MPU)と RP2350(PMP)の両方で。**安全包絡線と制御ループはネイティブで、カーネル内にあるので、バグったミッションはそこに一切届きません。アクター対アクターより強い隔離です。**境界を実証するまで、ミッションは起動されません。**プリフライトのチェックが非特権からカーネルメモリへのストアを試み、ハードウェアがそれを拒否しなければ、基板は中止してミッションを起動しません。全チェックが READY になると、基板は人間が発進を許可するまで待ちます。両方の基板が、実機で Wi-Fi 越しに HIL シミュレータ相手の配送ミッションを完走しました。
実機とエミュレータ
| ターゲット | 実機 | エミュレータ |
|---|---|---|
| x86_64 | 済 AMD Ryzen ノート PC、実 UEFI ファームウェア、4 コア | QEMU |
| RV32(MMU 無し) | 済 Raspberry Pi Pico 2 / Pico 2 W(RP2350、RISC-V、ソフトフロート) | QEMU |
| ARMv6-M(MMU 無し) | 済 Raspberry Pi Pico W(RP2040) | QEMU 経路なし |
| riscv64 | 未 | QEMU |
| aarch64 | 未 | QEMU |
実測値(1 kHz のデッドライン成績、制御則の WCET=Cortex-M0+ で 190 µs・Hazard3 で 98 µs)は、上の実機の行から出ています。エミュレータの行が証明するのは機構であって、タイミングではありません。