TOPPERS APIを使用する (方法3)
TOPPERS APIを使用する (方法1) と TOPPERS APIを使用する (方法2) ではFFIを使用してTOPPERSカーネルのAPIを直接呼び出す方法を説明しました。こうした外部の関数にはRustの言語機能によるメモリ・スレッド安全性が及ばないため、呼び出しを unsafe { ... }
ブロックで囲う必要があり、これを書くプログラマが安全性に関する責任を負う必要があります。(unsafe
の使い方を誤ると、"Safe Rust" はsafeではなくなります。) カーネルAPIはエラーコードを単なる数値として返すため、カーネル関数が返す可能性のあるエラーコードを網羅的に処理できていることを機械的に保証する仕組みもありません。
TOPPERS APIを使用する (方法2) で示した Cargoパッケージ itron はカーネルAPIをラップした「安全」なAPIも提供しています。これはこのパッケージのドキュメントで説明されているように実験的機能であり、バージョン間の互換性の保証がありませんが、うまく活用することにより、より自己説明的で信頼性の高いコードを記述できます。本セクションではこうした実験的機能を使う方法と、この「安全」なAPIの使用例を示します。
TOPPERS APIを使用する (方法2) で作成したコードをベースにします。
Cargo.toml
のdependencies.itron.features
に"unstable"
を追加し、dependencies.itron.version
を"= 0.1.9"
に変更します。[dependencies] itron = { version = "= 0.1.9", features = ["solid_asp3", "dcre", "unstable"] }
Note
"= 0.1.9"
は厳密にこのバージョンを要求し、自動的にマイナーバージョンを更新するのを禁止することを表します。これはitronパッケージのドキュメントで説明されているように、"unstable"
で有効化される実験的機能はバージョン間の互換性の保証がないためです。
root_task
を書き換えます。(最初のバージョンと比較してみてください。)use itron::semaphore::Semaphore; #[no_mangle] extern "C" fn root_task(_: usize) { let sem = Semaphore::build() .initial_count(1) .max_count(2) .finish() .unwrap(); sem.as_ref().signal().unwrap(); sem.as_ref().wait().unwrap(); let info = sem.as_ref().info().unwrap(); println!("Semaphore state = {:?}", info); assert_eq!(info.count(), 1); }
Note
.unwrap()
はResult::unwrap
(Rust APIドキュメント) メソッドの呼出しです。対象がOk(x)
のときはx
を返し、Err(_)
の場合はパニックします。基本的には、ソフトウェアのバグやハードウェアの異常がない限りErr(_)
が返されることが起こりえない場合に使用します。ここでは
.as_ref()
はSemaphore::as_ref
(itron APIドキュメント) メソッドを指しており、&Semaphore
をSemaphoreRef<'_>
として借用します。これが必要なのはitron 0.1.9ではセマフォ操作メソッドはSemaphoreRef
にのみ存在するためです。
実行すると、前のバージョンと同じように
T_RSEM
の内容がログ出力先で見えるはずです。Note
itron::semaphore::Info
(itron APIドキュメント) はカーネル間の差異を吸収するためのT_RSEM
のラッパーです。