モダンOSのお砂場(39) Mbed OS6、ConditionalVariableヤバイ?

Joseph Halfmoon

カッコイイ機能があるな、ということで使ってみました。ConditionalVariableであります。確かにカッコイイのですが、ターゲットのSTM32F401REにとっては結構ヤバイ奴でした。シンプルなサンプルコードなのにRAMがいっぱいいっぱいな感じ。何かコードを書けるような余地があるような気がしません。気のせい?

※2022/03/17追記:「気のせい」でした。すみません。OS6はZI Dataとして扱われる部分が多いためにヤバイなどと書いてしまいました。全然ヤバくありません。ヤバイのは自分。

まずは、マニュアルページへのURLを以下に貼り付けておきます。

ConditionVariable

ConditionalVariableは、これだけで使えるような制御構造ではなく、かならずMutexの上で動作するようです。「素のMutex」の上に一枚被せた感じのものです。

何かクリティカルな部分があり、複数のThreadで同時にそこに入らないようにするときにMutex使うことがあると思うのです。排他制御というやつ。ただ、素のMutexで排他制御書いていると、稀にコンガラがって、決して抜け出せないデッドロックなどこさえてしまうことがあるかと(立派な人はそんなことはまかり間違っても無いでしょうが。)

しかし、このConditionalVariableを使うと、結構簡単にMutex lockの制御が書けるようです。今回は、Arm Mbed OS6のサンプルコードをそのままWebコンパイラでコンパイルしてNucleo F401RE上で走らせてみました。ちゃんと排他制御仕切ってくれます。機能的にはまったく問題ないのです。しかしビルド結果みてちょっとビックリ。

だいたいサンプルコードなのにwarning多過ぎじゃないか

上記のAPI解説ページに、ConditionVariable example なるものが掲載されており、その傍らには、”Import into Mbed IDE” と書かれたボタンまでおかれています。MbedのWeb環境に登録済であれば、ここを押すだけでWeb環境にサンプルコードがコピーされ、即座にビルド可能な環境が出来上がります。超簡単。

複数ボードを使っている場合は、ターゲットボードの設定を確かめた方が良いです。私なんぞはF401REのつもりが他のボードになっていてトホホな件も数しれず。。。

ターゲット・ボートの設定が正しく、そこでコンパイルすれば、main.cppから呼ばれている筈の一切合切がみなビルドされて実行可能オブジェクトがダウンロードされてまいります。しかしね、warning多いです。サンプルコードでもまったくでないということはないですが結構多い。この感じ、あまりメンテナンスされてないんじゃないかと?エラーじゃないのでオブジェクトは生成されているのですが、ちょっと大丈夫なの?という感じ。

warning

何故か何時もよりコンパイルされているソースの分量が多い感じがします。実際時間もかかっています。

ConditionalVariableの威力

warningで色が変わっている行があるので、ちょっと見苦しい感じがしますが、ConditionalVariableの威力を知るためにサンプルコードの一部を引用させていただきます。

まず、ワーカースレッド側。ワーカースレッドはmain()関数内でスレッドとして起動されています。その実体が以下に。

worker

ぱっと見ると、スレッドの先頭でmutexのlockを取得し、doneフラグが立つまで作業を続け、スレッドから脱出する間際でようやくlockを手放すように見えます。mutexだけだったらずっとlockになってしまってこれはマズイ。しかしdoループの中に cond.wait()というConditonalVariableの待ちが入っていることでこれでOKです。多分この中でlockを良きように制御してくれているはず。

一方 main()関数のmutex使っている部分がこちら。

main

ConditonalVariableがなければ、決してうまく動作しない筈ですが、動かしてみるとほれこのように。

Results

mainが、値をセットして、cond.notify_all()した直後にcond.wait()しているスレッドが動いているようです。どうもConditonalVariableの中で、Mutexのlock/unlockは「良きように」操作してくれているみたいです。「一枚被せた」だけの御利益はある、と。

しかしご利益ばかりではないです

しかし、ビルド結果を確認してちょっと愕然としました。小さなサンプルコードなのでコードを格納するFlash領域は小さいです。しかしRAMが。ほれこのとおり。

build

確かに今時のマイクロコントローラとしては、STM32F401REの96kBはそれほど大きなRAMサイズではありません。しかし規模の小さなマイクロコントローラを見慣れているこの年寄りには、96kBは使いきれない大容量にも思えておりましたぞ。しかし、95.6kBの使用とな。RAMの残り400バイト。

大域変数などのRW Dataは0.3kBしか使われておらず、大部分はZIデータとあるのでゼロ初期化のメモリ。動的に使用する領域みたいです。動的に使用する領域であれば「押したり引いたり」する余地はありそうではあります。でもOS6でConditonalVariable使うのならば、それくらい「確保しとけ」ということだよね。「小さなF401RE」は、なんとかサンプルコードを走らせているけれど、あんまり余裕は無い気がいたします。

モダンOSのお砂場(38) Mbed OS6、Timerでインターバル測定。STM32 へ戻る

モダンOSのお砂場(40) Mbed OS6、EventFlags、便利なお知らせ へ進む