- ベストアンサー
リエントラント関数
はじめまして。 複数のタスクで利用されるような関数を作成しようと思っています。 この関数をFuncAとします。 void FuncA() { int a; int b; int c; 処理1; 処理2; 処理3; 処理4; } タスクは優先度低のタスクAと優先度高のタスクBがあるとします。 タスクAがこのFuncAの処理2を行っている最中に、 タスクBがこのFuncAを呼び出すとタスクBで先にFuncA処理をしてから、 タスクAに戻って続きの処理3を行うと思います。 このとき、タスクAで使用していたローカル変数a,b,cはどっかに退避されているのでしょうか?
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
>このとき、タスクAで使用していたローカル変数a,b,cはどっかに退避されているのでしょうか? auto変数はスタックに作成されるので、事実上、退避されるのと同じ。 register変数はコンテキストスイッチで自動的に保存、復元される。 「スレッドセーフな関数」とは「静的またはグローバルな変数を、参照、操作してない関数」なので、静的またはグローバルな変数にアクセスしてればアウト。当然、ポインタを用いて「関数外で確保したメモリ」にアクセスしている場合もアウト。 また「スレッドセーフが保証されてない関数」を呼んでいる場合、自分自身も「スレッドセーフが保証されてない関数」になってしまうので、その場合もアウト。 たいていの「C標準ライブラリ関数」は「スレッドセーフが保証されてない関数」なので「C標準ライブラリ関数を呼んだらアウト」と思って間違いない。 上記のように「変数だけ安全でも、ちっとも安全じゃない」ので、ご注意を。 そういう訳で ・静的またはグローバルな変数を、参照、操作してない ・関数外で確保したメモリを、参照、操作してない ・スレッドセーフが保証されてない関数を呼んでいない ・C標準ライブラリ関数(スレッドセーフが保証されている物を除く)を呼んでいない なら、両方のタスクから同じ関数を呼ぶ事が出来ます。
その他の回答 (3)
- S117
- ベストアンサー率40% (18/45)
自動変数が複数のスレッド間で独立であるかという質問でしょうか。 それとも、実装例についての質問でしょうか。 前者への回答 自動変数は別のスレッドとは干渉しません。(ポインタなどで意図的に共有しない限り) 後者への回答 スレッド間で変数は独立しますが、では関数呼び出し時に退避されるのでしょうか。 自動変数はほとんどの実装で、コールスタックに確保されます。 (コールスタック自体の説明は参考URLで。) マルチスレッドの場合、このコールスタックをスレッドごとに独立させて用意することになります。そうすると、自動変数は全く関係のない箇所に独立して用意されますので、「退避させる必要はない」のです。
- massano1
- ベストアンサー率40% (4/10)
FuncAで取っている変数は大丈夫です。 (「int a,b,c」はstaticでは無いので別に取られます) 但し、内部で呼び出す処理で外部スコープの変数(グローバル変数等)を 参照した場合は動作が変わるので「FuncA全体が安全か」は(この情報 だけでは)不明です。
- Tasuke22
- ベストアンサー率33% (1799/5383)
リエントラント・・・懐かしい言葉に思わず出てきました。 リエントラントを要求されるということは、複数のタスク から1つのモジュールがコピーされないで呼ばれるので、 内部変数があれば、即アウト、です。 タスク毎にテーブルなどを持たせ、その領域を使う仕組み でなければいけません。 簡単な方法ですと、呼出し引数に作業域を付ける、とかで す。