(toppers-users 3891) Re: DEF_RPRIを無くすご提案

高橋和浩@nifty takahashi_kazuhiro @ nifty.com
2012年 2月 7日 (火) 10:36:03 JST


内山様 MLの皆様 おはようございます。 アライブビジョンソフトウエアの高橋です。

例示として有効だし、このような設計にフィットしたOSとして
ある条件下にはなりますが有効な機能だと思います。

杉本様との排他の話は今ひとつよくわかっていませんでしたが、これではっきり理解できました。
ありがとうございます。

末尾に「4.例示に対するさらに自分の理解の確認」を参照のうえ
以下の内容を読まれるとよいかと思います。

ただ、この設計には、条件がつきます。今までもそう言っていたケースですが、
1)リアルタイムシステムは負荷が変動するもの
2)RTOSはCPU稼働率を上げて、より費用対効果をあげるもの

と捉えています。 2は、今どきでは考える必要が無くなってきているかどうかは
実際どうなのかというのも興味のあるところです。

つまりどういうことかと言うと、例示のタスクB(メインタスク)とその他のタスク
とあわせて100%近くで使い、さらに負荷変動により、タスクBはタスクがキューイング
されるケースがあり、トータルでCPU稼働率がより高くなる設計をすると考えます。

そうした場合に、タスクCが連続で起動するため、表示のタスクDが200ms以上表示が更新されないケースが
考えられます。

自分なら例示のものの設計では、
1)タスクCとタスクDがドライバからドライバへの競合リソースを使う実装なのでそれはまずやめます
具体的にはドライバ層であるタスクCからメインタスクBを介して表示するものにします。
2)タスクBで、タスクDの処理を関数としてタスクBから呼び出します。

これで、タスクDは無くなるので、タスクCからもっともスタックが浅くなったところから関数呼び出し
すれば、スタックが減らせるのは同じ効果があります。
さらに、高負荷になっても、表示はかねがね100msおきに表示されます。単純にタスクCとタスクAの遅延分
のみになります。例示のものは、それ以上に表示が遅れます。
何が違うかと根本的には、タスクDが負荷によってCPUの稼働率が変わるからです。
私の設計の場合は、過負荷になってもタスクDの実行の割合が大きく変動しないからです。
結局、2つの優先度をもつものは負荷変動に対して、弱い設計になります。

ただ、自由に設計できない場合もあるので、そういう設計でも対応できるOSの必要性があるのかも
と思います。
この点の是非については、たぶん収拾できない話題となりそうなので割愛します。

当初から主張しているとおり(toppers-users 3795)利用できる場合は、負荷とのバランスがとれた場合のみ
利用できますが、負荷バランスが完全に把握できる場合というのもなんだか脆弱なシステム
を作ってしまうようにも思います。
ただ、負荷を十分把握して、必要十分状態で使うケースは少なくないので
私の言う「使い物にならない」というのは撤回すべきかと思います。

以下、蛇足かと思いますが、考えていたことなど書いておきます。
----------------------------------------------------------------------------------------
2.制約タスクという想定するユーザー
SSPは制約タスクしかありません。上位のITRONにおいても制約タスクの実装もされているものも
あるかと思いますが、想定するユーザーはどこになるのかというのがここでひとつはっきりした
気がします。
上位のITRONで制約タスクもある場合には制約タスクの担当者は制約的環境で、より高度な実装者が
細心の注意を払って実装するというイメージを持っていますが、それはどうなのでしょうか?
そうしたことを考えるとSSPの想定するユーザーは次のうちどれなのかという疑問が生じます。

1)SSPは省フットプリントで利用できるRTOSで従来RTOSを使って無かった人に使った貰うもの
2)SSPは制約タスクという極めて細心の注意が必要な機能のみなのでそれだけで実装できる
パワーユーザー向け

というのは、例示のシステムを設計者は相当タスク設計については理解している必要がありますが
これがメンテナンスになって、RTOSをこれから勉強しようというつまり前述の1)の人が引き継いだ場合
には、おそらくデグレードをすると考えます。
特に競合リソースについては、例示の設計ではタスク優先度により強力な排他が働きますが
ソースを見る限り排他らしき部分は確認できず。DEF_EPRIからそうなると導く必要があります。
これはもっと競合リソースを明示的したほうがよいとも考えています。

----------------------------------------------------------------------------------------
3.排他の代替案
このメールを受ける前に排他については少し手を考えていましたので、紹介します。
ディスパッチ禁止ではちょっと範囲が広くなるため、優先度マスクをかけたらどうか
と考えました。 割り込みマスクをかけるようなものです。
つまり
vmask_pri(優先度)
vunmask_pri()  (シンボル名は思いつきです)
というサービスコールを新設します。 これで指定した起動時優先度以下のディスパッチを
抑止します。実装方法は、変数に書いておき、スケジューラで、起動元の優先度(実行時)と
ready_mapからの起動時優先度の大小比較をしていますが、さらにマスク優先度とも比較し、
それ以下の起動時優先度のタスクはディスパッチしないという処理をすれば実現できると思います。

そうした場合に先ほどの例示の場合ですが、
タスクDをタスクBと同一優先度、つまり(外部表現)優先度4とし、
タスクDで mask_pri(3) unmask_pri()を呼び出せばよい
と考えます。

優先度による排他は、本来セマフォが無いので必然的に必要になったことがたぶん発端だと
思いますが、セマフォよりもオーバーヘッドの少ない方法のように思います。
ASP等への互換性を考えた場合にも有効な方法だと思いますが、DEF_EPRIをASPに移植するより
vmask_pri(優先度)vunmask_pri()を実装するほうが楽なんじゃないかと思っています。

さらに、ソースコード上にも競合リソースに対するアクセスが明示的に表れる点も
メンテナンス的にはプラスだと考えています。

-----------------------------------------------------------------------------
4.例示に対するさらに自分の理解の確認

B-C間はプリエンプトする(BからC)。
B-D間はお互いにプリエンプトするとまずい
C-D間もお互いにプリエンプトするとまずい。
これはいったいどういうことか考えてみます。

DとBの共有エリアつまり競合するメモリやリソースがあり
それを両方のタスクが参照変更している。
DとCについても同様

B-Cは、Cのプリエンプトがあるので、Bの参照編集リソースはCは参照編集しない。
BのDとの競合リソースとCのDとの競合リソースは重複しない。
単純にタスクDは、Bから呼ばれたときはBとの競合リソースのみ参照編集し
Cとの競合リソースを参照しなければ排他を緩めることも可能であるが
タスクDはBとCの共有リソースを常に両方参照編集する作りになっていると
考えています。

つまりグローバル変数いっぱいでどのタスクがどのタイミングでアクセスするか
を特定せず、各タスクが自由にアクセスできるような設計かと思います。

-------------------------------------------------------------------------------
5.まとめ
とりあえず、結果的にどうなの?ということを再度聞かれることがあるので
くどいようですがまとめておきます。

DEF_EPRIを無くす提案で特に問題はないと思っています。
リストアップしますと
1)狭義の省スタック化が可能 --> SSPと同じ
2)優先度による排他可能   --> SSPと方法は違う(vmask_pri)が可能ということで同じ
3)FCFSの対応        --> SSPがレディキューを入れるのと同じ効果
4)タスク優先度設計の互換性 --> SSPはDEF_EPRIがあるので互換性が多少問題がある
5)vmask_priによる上位互換  --> SSPにはない。 上位のITRONにも実装可能であるし、実装することで
互換性を持たせることが可能。
6)タスク設計の難易度    --> SSPの場合はDEF_EPRIを使うかぎり過負荷についてさらに注意が必要


以上です。
On Mon, 6 Feb 2012 16:35:44 +0900
"内山 敏和" <uchiyama-1415 @ ntk-g.co.jp> wrote:

> 皆様、初めまして
> 
> 新潟通信機の内山と申します。
> 
> 
> 起動時優先度と実行時優先度が設定できれば有り難いと思うケースを考えて見ました。
> 余談ですが、
> 私はμITRINはVer2とVer4を良く使ってて、TOPPERSにも興味がありMLを拝見させて頂いております。
> 普段からメモリリソースに厳しい環境下で開発しているので省メモリなSSPに期待があります。
> TOPPERSはド素人なので、突っ込みどころ満載かもしれませんが、こんな風に使えるのかなぁ
> と思い、送っております。
> 
> 
> ・システム条件
>  [タスクA]
>  システム的に最も早急に処理しなければならない処理で、
>  他タスクの実行をプリエンプトしてでも実行開始しなければならない。
>  1回の起動でのタスク処理時間は短い。
> 
>  [タスクB]
>  アプリケーション的な処理を行うタスク
>  1回の起動でのタスク処理時間は長いが、最長でも100ms程度で終了する。
>  4タスク中、最も低優先度での実行で構わない。
>  タスクDにプリエンプトされると問題発生する。
> 
>  [タスクC]
>  デバイスドライバを利用するタスク
>  1回の起動でのタスク処理時間は中程度で、最長でも十数msで終了する。
>  タスクBより高優先度で処理する必要がある。
>  タスクDにプリエンプトされると問題発生する。
> 
>  [タスクD]
>  表示ハードウェアデバイスドライバのタスク
>  タスクB及びCからの要求を受けて処理が開始するが、起動の遅延は数百ミリ秒程度許される。
>  ハードウェアデバイスの特性として、一旦アクセスを開始したら完結するまで走りきる必要がある。
>  1回の起動でのタスク処理時間は短く、最長でも数msで終了する。
>  タスクB及びタスクCにプリエンプトされると問題発生する。
>  使用するスタック容量は、タスクBとタスクCが使用するスタック容量を足したものより少ない。
> 
>  [その他]
>  メモリ資源が乏しく、できるだけスタック領域として使用するRAMも最小限にしたい。
> 
> ・条件に基づくタスクの優先度割当て
>  [タスクA]
>  起動時優先度1
>  実行時優先度1
> 
>  [タスクB]
>  起動時優先度4
>  実行時優先度4
> 
>  [タスクC]
>  起動時優先度3
>  実行時優先度3
> 
>  [タスクD]
>  起動時優先度5
>  実行時優先度2
> 
> ・動作の確認
>  タスクDの起動時優先度は5なので、タスクA、B、C全て終了するまで起動できない。
>  一旦タスクDが起動し実行開始すると、タスクB及びタスクCは起動できない。
>  (タスクDは、B及びCと排他で起動)
> 
> タスクで使用する総スタック容量
>  タスクA使用量+タスクB使用量+タスクC使用量 となる。
>  但し、タスクD使用量 <(タスクB使用量+タスクC使用量)
>  よって、タスクD使用量分、スタック容量を節約できる
> 
> 
> 同一優先度による排他制御では、この様なシステムは難しいと考えます。
> 優先度を2つ持つことは、システム全体を設計することを複雑にし、
> それによるリスクもあると思いますが、
> メモリリソースが厳しい環境下では有効だと思います。
> 
> 
> また、ML内での話題の流れについて行けない部分もあり、
> 皆様にとって、邪魔なメールになってしまわないか心配ではありますが、
> その節は、ご容赦のほどお願い致します。
> 
> 
> 
---
アライブビジョンソフトウエア株式会社
高橋和浩
673-0005兵庫県明石市小久保2-2-7幹線ビル4F
Email:takahashi_kazuhiro @ nifty.com
http://homepage3.nifty.com/ALVS/