今回は「セマフォ」について説明していきたいと思います。
これもイベントフラグと同じく必須の機能ではありませんが、非常によく使われる機能だと思います。
「セマフォ」ってちょっと聞き慣れない言葉ですよね。
でも普通の英単語で、「semaphore」と綴ります。
意味は「腕木式信号」や「手旗信号」とかそういった感じのものになります。
セマフォは、ある有限な資源を管理するのに使います。
例えばDMACが3つある場合、プログラムのいろいろな箇所でそれを使おうとした場合、資源の枯渇という問題が発生します。
使えない場合は使えるようになるまで待つ、というようなことを簡単に管理できる機能です。
今回はDMACを管理する、という前提で話を進めていきたいと思います。
前回はタスクのメインのループの中のイベント待ちでイベントフラグを使用しました。
void task(intptr_t exinf) { 前処理(); while (1){ イベント待ち(); タスクの処理(); /* ☆ */ } }
セマフォもその使い方で構わないのですが、私の経験ではどちらかというとプログラムの中で使用する資源を管理することが多かったため、今回はタスクの処理の箇所で使うようにしたいと思います。
前々回に説明しましたが、タスクは「イベントドリブン型」です。
「資源が使えるようになる」というのもある意味イベントですが、今回の前提である外から見えないDMACよりも、どちらかというと外から見える資源(機能)の管理に使うほうがスマートだと思います。
セマフォ関連で主に使用するサービスコールは以下のものです。
- CRE_SEM(セマフォを生成する)
- sig_sem/isig_sem(セマフォ資源の返却)
- wai_sem(セマフォ資源の獲得)
- pol_sem(セマフォ資源の獲得をポーリングで行う)
セマフォの使い方ですが、セマフォ生成時に資源の最大数を設定し、wai_semで資源が獲得されるたびにその最大数のカウンタが内部的に減っていき、sig_semで返却されるとカウンタが増えていく、というような単純な仕組みになっています。
セマフォを使う上で注意しなくてはならないことがあります。 下記のリンクの「優先順位の逆転」です。
https://ja.wikipedia.org/wiki/%E5%84%AA%E5%85%88%E9%A0%86%E4%BD%8D%E3%81%AE%E9%80%86%E8%BB%A2
火星探査船の「Mars Pathfinder」でこの不具合が発生したのが有名です。
この問題を解決するには「ミューテックス」を使用します。
ミューテックスについてはそのうち解説しようと思います。
今回はセマフォの概要について説明してみました。
次回は実機を使用してセマフォの動作を確認したいと思います。