排他制御の基本と使い分け
組み込みシステムでは、複数のタスクや割り込み処理が共有するデータや周辺機器へアクセスする場面が頻繁に発生します。排他制御を適切におこなわなければ、データ不整合や競合状態(Race Condition)、デッドロック、処理待ち、割り込み遅延などの問題が発生します。
共有リソースの排他制御やタスク間の同期に利用される代表的な手法として、「ミューテックス」「セマフォ」「割り込み禁止」があります。目的や利用できる場面はそれぞれ異なるため、特徴を理解した上で適切に使い分けることが重要です。
この記事では、それぞれの仕組みや特徴、組み込みシステムでの使い分け、さらに安全な排他制御を実現するための設計ポイントを解説します。
- 排他制御の基本概念と組み込みシステムでの重要性
- ミューテックス・セマフォ・割り込み禁止の特徴と比較
- 組み込みシステムでの排他制御の使い分け
- 排他制御で注意すべき設計のポイント
- 排他制御の適切な設計のためのポイント
排他制御の基本概念と組み込みシステムでの重要性
排他制御を適切に設計するには、意味や役割、必要性を理解することが求められます。ここでは排他制御の基本的な概念と、組み込みシステムで意識すべきポイントを説明します。
排他制御とは
排他制御とは、複数のタスクや割り込み処理が同じ共有リソースへアクセスしないよう制御する仕組みです。同時アクセスが許されない区間をクリティカルセクションと呼び、適切に保護しないと実行順序によって結果が変わる競合状態が発生します。
なお、排他制御は共有リソースを保護することが目的であり、処理順序を制御する同期制御とは役割が異なります。たとえば、共有変数の保護はミューテックス(排他制御)、処理完了通知はセマフォ(同期制御/通知)です。
排他制御が適切でない場合に生じる問題
排他制御が不十分だと、共有データの更新漏れや破損、タスクと割り込み処理の競合などが発生します。これらは発生条件が限られるため再現性が低く、原因の特定が難しい不具合になりやすいことが特徴です。
組み込みシステム特有の排他制御のポイント
組み込みシステムでは、RTOS(リアルタイムOS)の有無やISR(割り込みサービスルーチン)とタスクの共存を考慮した設計が必要です。また、共有変数だけでなく周辺機器のレジスタも排他対象となることがあるため、用途に応じて適切な排他手法を選択する必要があります。
ミューテックス・セマフォ・割り込み禁止の特徴と比較
排他制御には複数の実現方法があります。ここでは、3つの方式の特徴を順に整理します。
ミューテックスの特徴
ミューテックスは、共有リソースの競合を防ぐための排他制御機構です。ロックを取得したタスクがリソースの使用権(所有権)を持ち、使用後に解放します。
多くのRTOSは、高優先度タスクが低優先度タスクの持つリソース解放を待つ間に中優先度タスクが割り込んで実行される「優先度逆転(Priority Inversion)」の影響を緩和する、優先度継承機能を備えています。
セマフォの特徴
セマフォは排他制御だけでなく、タスク間の同期やイベント通知にも活用されます。バイナリセマフォはイベント通知、カウンティングセマフォは複数リソースの管理に適しており、ISRからタスクへの通知手段としても有効です。
セマフォは排他にも使えますが、所有権(owner)を持たないため、排他用途には原則ミューテックスを用います。
割り込み禁止の特徴
割り込み禁止は、CPU(中央処理装置)の割り込みを一時的に停止してクリティカルセクションを保護する方法です。高速に排他処理を実現できますが、割り込み応答が遅れるため、最小限の使用に限定することが原則となります。たとえば、最長経路が許容最大割り込み遅延を超えない範囲でだけ使用します。
また、マルチコア環境では割り込み禁止だけでは排他にならないため、スピンロックなどの別機構が必要です。
3つの方式の比較
ミューテックスはタスク間の共有リソース保護、セマフォは同期やイベント通知、割り込み禁止は短時間のクリティカルセクション保護に適しています。また、利用できる環境(タスク・ISR・ベアメタル)やオーバーヘッドも異なるため、利用目的と実行環境を踏まえて適切な方式を選択することを推奨します。
組み込みシステムでの排他制御の使い分け
排他制御は、目的に応じて適切な手法を選択する必要があります。ここでは、代表的な利用場面ごとに適した排他制御を紹介します。
ミューテックスを使うべき場面
ミューテックスは、複数タスクから共有リソースへアクセスする場合に適しています。複数のタスクから利用される通信スタックやデバイスドライバ、ファイルシステムなどで、同時アクセスを防ぎたい場面に利用します。あらかじめロックを取得してリソースへのアクセス権を得るため、安全な排他制御を実現できます。
セマフォを使うべき場面
セマフォは、DMA(ダイレクトメモリアクセス)などの非同期処理完了通知やタスク間の同期に適しています。また、ISRからタスクへイベントを通知する用途でも広く利用されます。
割り込み禁止を使うべき場面
割り込み禁止は、短時間のクリティカルセクションを保護する場合に適しています。また、RTOS起動前の初期化処理や、ごく短い共有データ更新処理でも利用されます。ただし、割り込み応答に影響するため、使用時間は必要最小限にとどめることを推奨します。
迷ったときの選択基準
複数のタスク間で共有リソースの競合を防ぐ場合は、原則としてミューテックスを利用します。処理完了の通知やイベント同期にはセマフォ、短時間の共有データ更新には割り込み禁止が適しています。RTOSの有無やISRとの関係も考慮し、用途に応じて選択しましょう。
排他制御で注意すべき設計のポイント
排他制御は、適切な手法を選ぶだけでは不十分です。設計や実装方法によっては、性能低下やデッドロックなどの原因となるため注意が必要です。
デッドロックを防ぐ設計
複数のミューテックスを使用する場合は、ロックを取得する順序をシステム全体で統一することが求められます。また、複数のミューテックスを同時に取得する設計は必要最小限にし、タイムアウトを利用して異常状態を検出できるようにすると、安全性が向上します。
優先度逆転への対策
前述の優先度継承機能を備えたミューテックスを利用し、RTOSが提供する機能を適切に活用することで影響を軽減できます。
割り込み禁止の多用を避ける設計
割り込み禁止を長時間使用すると、割り込みレイテンシの増加やリアルタイム性の低下を招きます。クリティカルセクションは必要最小限にし、ポーリングなどの待ち処理や時間のかかる複雑な計算を含めないことが基本です。
コードレビューで確認すべき項目
コードレビューでは、ISRでブロッキングAPIを使用していないか、ロック保持時間が長すぎないか、ロック取得と解放が必ず対応しているかを確認します。また、共有データへの排他制御漏れがないかも重要な確認項目です。
排他制御の適切な設計のためのポイント
排他制御は、システム全体の設計方針として考えることが重要です。ルールを統一し、保守性とリアルタイム性を両立できる設計を目指しましょう。
排他対象を明確にする
まず、共有リソースを洗い出し、排他制御を要する箇所を明確にします。共有変数のほか、通信バッファや周辺レジスタも洗い出しの対象に含めます。ロックの範囲は、適切に設定することが求められます。
システム全体でルールを統一する
ロックの取得順序や、ミューテックス・セマフォ・割り込み禁止の使い分けをルールとして定め、コーディング規約へ反映しましょう。設計方針を統一することで、デッドロックの防止や保守性の向上につながります。
保守性とリアルタイム性を両立する
ロックの保持時間は最小限に抑え、実機で性能や応答時間を確認することが重要です。また、将来の機能追加も見据えて排他制御の範囲を設計しておくことで、変更時の影響を抑えながら保守性とリアルタイム性を両立できます。


