要約
- TinyOSの長い処理はsplit-phaseであり、コマンドが要求を開始または拒否して直ちに戻り、提供側が定義した完了を後のイベントが伝えた。
- 一つの小さなスタックを複数の処理で共有し、待機中にCPUを眠らせられる一方、順序、バッファの占有、期限切れ、回復を状態機械で管理する必要が生じた。
sendDoneはメッセージを再利用できるという強い局所証拠になっても、遠隔アプリケーションの受信、受理、実行まで証明するものではなかった。
ハードウェアの時計に合わせる
センサー変換や無線送信は、関数が次の行へ進んだから終わるのではない。物理装置が自分の時間で進み、状態を変えたところで割り込みが起きる。小さな装置でその時間を待つために、スレッドごとのスタックを確保したり、CPUを起こしたままにしたりする余裕はなかった。
TinyOSはタスクとイベントを使った。後で実行できる計算はタスクキューに置き、非同期な変化はイベントで知らせる。タスクがなければプロセッサは眠り、割り込みが新しい仕事を持ち込む。
時間のかかる操作は二つの局面に分かれた。コマンドは要求を出すと制御を返し、後のイベントが処理を再開させる。待機中の活動ごとにスタックを抱えないため、わずかなRAMでも複数の流れを進められた。
ただし、消えたのは状態ではなく、暗黙の待機である。アプリケーションは、どの要求が未決か、どのバッファを相手に預けているか、次にどのイベントが来るはずか、来なければどうするかを記録しなければならない。非同期性は無料ではなく、時間を可視化する代価だった。
一つのインターフェースに往路と復路
2004年のNSDI論文 The Emergence of Networking Abstractions and Techniques in TinyOS は、Philip Levis、Sam Madden、David Gay、Joseph Polastre、Robert Szewczyk、Alec Woo、Eric Brewer、David Cullerの共著である。論文では、コマンドが動作開始の要求を表し、イベントが要求の完了または環境で生じた出来事を表す。どちらの方向にもエラーを伝える余地がある。
nesCはこの関係を言語の形にした。インターフェースは双方向で、コマンドは利用側から提供側へ進み、イベントは提供側から利用側へ戻る。sendとsendDoneは同じ型の契約に入り、静的な配線が両方向を結んだ。
全プログラムを見渡せるため、コンパイラは多数の競合候補を検出し、構成を確認し、動的な間接処理を減らせた。資源の乏しい機械では、実行時の負担をコンパイル時へ移す効果が大きい。
しかし、配線が保証するのはプログラムの構成であって、外界の真正性ではない。物理センサーが本物か、無線の相手が期待した組織か、受信値が現実を正しく表すかは証明しない。コンパイラがプログラム全体を知っていても、プログラム外の世界について自動的な権威を持つわけではない。
イベントはすべて受領証ではない
イベントには二つの起源があった。あるものは先行する要求を完了させ、別のものは外部から始まる。パケットの到着、タイマーの満了、センサー条件の成立は、必ずしもコマンドへの返答ではない。
この区別を失うと、「イベントが来た」という事実に誤った意味を載せてしまう。完了イベントには対応する要求と完了条件が必要である。環境イベントには観測源と時点が必要である。名前が同じ機構を使うからといって、証拠の役割まで同じにはならない。
反対に、コマンドも完了ではない。呼び出した記録は意図を示す。即時の返答は拒否または受付を示せる。完了イベントは提供コンポーネント内の遷移を示す。その後の無線確認、遠隔受信、アプリケーション処理、物理効果には、それぞれの役割から新しい証拠が要る。
一つの「成功」にまとめれば画面は簡単になるが、どの主体が何を証言したのか分からなくなる。
バッファを預けるということ
TinyOSでコピーを避けることは、単なる高速化ではなかった。パケットの複製にはRAM、命令、電力が必要になるため、コンポーネント間では一つのバッファへのポインタを渡すことが多かった。
送信要求が受理されると、呼び出し側はそのメモリを保持したまま、内容を変更する権利を一時的に失う。無線がまだ同じバイトを使っているからである。sendDoneはその局所的な占有が終わったことを知らせ、バッファを次の用途に回せるようにする。
早く書き換えれば送信途中の内容を壊す。イベントが来なければ希少なメモリが拘束され続ける。対応付けを誤れば別の要求のバッファを解放する。重複イベントを無防備に処理すれば、一つの資産を二度返却したことになる。
したがって、sendDoneは飾りのコールバックではなく、保管関係を閉じる受領証である。同時に、その強さは局所的である。実装によってはリンク層の結果まで含むかもしれないが、名前だけで遠隔アプリケーションの受信、保存、理解、実行を保証しない。
受付と完了の間
提供側が忙しいとき、TinyOSのコンポーネントは新しい要求を直ちに拒否するか、後で扱うためにキューへ入れられる。二つの選択は異なる状態を作る。
拒否なら、存在しない処理を「保留中」にしてはならない。バッファは呼び出し側に残り、待つか捨てるか再試行するかを決める。受付なら、提供側に未完了の義務が生まれる。定めた完了またはエラーを返すまで、資源の保管が続く。
この中間状態は、現代のジョブキュー、ストレージ、決済、ネットワーク変更にもある。投入は実行ではなく、実行は必ずしも業務上の確定でもない。中間の受領証を最終結果として使うと、資源を早く再利用するか、逆に永久に拘束することになる。
狭い証拠は弱い証拠ではない。バッファを戻すには十分であり、相手のアプリケーションを語るには不十分である。その境界を保つことが、再利用可能な証拠にする。
完了通知の経路も有限だった
T2報告は、split-phaseの仕組み自身が作る故障を扱っている。上位層は無線からsendDoneを受け取るまでバッファを保持する。通常、無線スタックは完了を知らせるタスクをキューへ登録する。しかし、タスクキューは有限だった。
登録に失敗すると、呼び出し側はいつまでも待つ可能性がある。そこでTinyOSは、割り込みコンテキストから直接sendDoneを通知する逃げ道を使うことがあった。進行は回復するが、別の危険が生まれる。タスク文脈で走るつもりのコードが非同期に呼ばれ、競合やメモリ破壊を起こしうる。
著者らは、この形が特定の無線スタックだけの問題ではないと説明する。完了通知をタスク登録に頼るsplit-phaseコンポーネントなら、キュー圧力の下で同じ選択に直面する。通知を失えば上位が永久に止まり、文脈を変えて通知すれば並行性の仮定を壊す。
この記述を、すべてのTinyOS展開で同じ障害が起きたという主張へ広げるべきではない。T2は多数の研究者と企業が作った設計上の応答であり、現場事故の統計ではない。確かな教訓は、完了証拠の配送も実行中の処理であり、キューや文脈の制約から逃れられないという点にある。
状態機械は実行履歴になる
ブロッキング呼び出しを順番に書けない代わりに、プログラムは状態機械を持つ。要求を出し、未決を記録し、一致するイベントを待ち、次の遷移を選ぶ。
状態は、待機、要求済み、拒否、受付、ハードウェア処理中、局所完了、期限切れ、取消しを区別できる。タイムアウトは「失敗した事実」ではなく、「期限内に証拠を見なかった事実」として残せる。遅いイベントも、操作IDがあれば元の要求へ戻せる。
再試行にも意味を与えられる。同じ操作の照会なのか、新しい処理の作成なのかを区別すれば、重複実行を避けやすい。状態と相関を捨てれば、遅れて届いた完了を現在の要求と取り違える。
もちろん、悪い状態機械は誤る。遷移を省き、IDを再利用し、キューあふれを隠すこともある。静的解析は競合を減らしても、選んだ業務上の意味まで正しいとは保証しない。履歴として役立つのは、各状態が観測可能な実行事実に対応するときだけである。
Heng LuのRunning-Code Primacyは、ここで現代的な比較を与える。宣言されたコマンドは意図であり、動いているコンポーネントと後のイベントがより強い証拠を出す。ただし、イベントの権限は発行主体の遷移で止まる。これは編集上の比較であり、後年のインターネット統治理論をTinyOSの著者へ遡及して帰するものではない。
Cullerを共同作業の中に置く
Berkeleyの公式プロフィールは、TinyOSとBerkeley MotesをDavid Cullerの研究歴を形作るシステムとして挙げている。研究環境を築き、アーキテクチャを育てた人物として彼を中心に据える理由はある。しかし、共同制作を一人の発明へ縮める理由はない。
NSDI論文は8人の仕事である。nesC論文はDavid Gay、Philip Levis、Robert von Behren、Matt Welsh、Eric Brewer、Cullerの共著である。T2報告にはStanford、Berkeley、Intel Research、Technische Universität Berlin、UCLA、Crossbow、Arch Rock、Moteiv、Washington Universityにまたがるさらに大きなチームが名を連ねる。2012年の十年回顧はPhilip Levisによる。
これは礼儀だけの話ではない。TinyOSは、言語、OS、無線、ハードウェア、配備、利用者コミュニティの契約が組み合わさって成立した。知的な来歴も、コンポーネントシステムと同じく分散している。
成熟が明らかにした負担
Levisは2012年の回顧で、TinyOSが当時広い研究基盤となり、商用製品にも使われたと記した。同時に、成功を支えた選択の長期コストも論じている。資源節約、nesC、細粒度コンポーネントは、専門家が複雑な仕組みを小さな装置へ載せる助けになった。成熟後には、専用言語と多数の小コンポーネントに散らばるロジックが、新規利用者の学習と既存コードの理解を難しくした。
そこで示された採用状況は2012年時点の歴史であり、現在の統計ではない。重要なのは、局所的に優れた抽象化も、エコシステム全体では調整費用を生むと認めたことだ。実行時のメモリを節約する静的な選択が、人間の理解時間を増やす場合がある。
それでも、要求と完了を区別する原則は残る。現在はfuture、promise、完了キュー、永続ジョブ状態など別の表現を使う。名前が変わっても、命令が結果ではなく、局所結果が端から端までの事実ではないことは変わらない。
完了とは、誰の完了か
先に戻るコマンドは欠陥ではなかった。要求の境界を正確に示し、次の事実を別の主体へ委ねていた。後から来るイベントも万能ではない。インターフェースが定めた局所状態に達したことを告げるだけだった。
リンク確認、遠隔受信、アプリケーション処理、物理的な結果まで必要なら、それぞれに新しい受領証を設けなければならない。一枚の緑色表示が、その連鎖を代替することはない。
極端な資源制約は、時間、保管、不確実性を設計の表面へ押し出した。豊かなシステムはそれらを隠せても、消去はできない。誠実な仕組みは、要求と完了を相関させ、未決を未決のまま保存し、実行証拠の意味を発行者の境界内にとどめる。
出典
- UC Berkeley EECS — David E. Culler
- USENIX — The Emergence of Networking Abstractions and Techniques in TinyOS
- Levis et al. — The Emergence of Networking Abstractions and Techniques in TinyOS (PDF)
- Gay et al. — The nesC Language: A Holistic Approach to Networked Embedded Systems
- Levis et al. — T2: A Second Generation OS for Embedded Sensor Networks
- Philip Levis — Experiences from a Decade of TinyOS Development
- Heng Lu — Running-Code Primacy
会員向け解説
プロフィールの詳細
適切な会員レベルでログインすると、解説全文と出典メモをご覧いただけます。
Strategic Circle 限定
Strategic Circle
すべての読者に公開されています。参加してログインすると プロフィール解説 を閲覧できます。
Strategic Circle に参加Leadership Alliance 会員限定
Leadership Alliance
対象となる IP 資産の所有者・管理者向けです。ログインすると Leadership Alliance の解説を閲覧できます。
Leadership Alliance に参加
