(toppers-users 3806) Re: SSPの DEF_EPRI とは何でしょうか。

Naoki Saito nsaito.nmiri @ gmail.com
2012年 1月 21日 (土) 23:46:32 JST


こいさんさん

斉藤です.

キューイングの件,ご提案ありがとうございます.

>  タスクの軌道前にprimap_clearをすると、sanple1ではASPと同様にキューイングが実現できているように動作します。

一見すると良いアイディアのように思えるのですが,
例えば 2つのタスクTASK1(ID=1), TASK2(ID=2)があり,
TASK1 の方が高優先度とします.
そしてシステム起動時には TASK1 が休止状態,
TASK2が実行可能状態とします.

(0) カーネルスタート(primap = 1)
(1) TASK1 実行開始 (run_task でクリアされて primap = 0)
(2) TASK1 の中から TASK2 起動 (primap = 2)
(3) TASK2 実行開始 (primap = 0)
(4) TASK2 終了

ここまでは良いのですが,run_task の while 判定
  /* 戻り先タスクの実行時優先度より高い起動時優先度をもつタスクが起動されたか */
} while((!primap_empty()) && (saved_pri > (next_pri = search_schedtsk())));

の primap_empty() が true となり,終了しませんか?

以上,よろしくお願い致します.

2012年1月20日9:38 koizumi yoshiyuki <koizumiyoshiyuki @ gmail.com>:
>  こいさんです。
>
>  言葉が足りずにすみません。申し訳なく思っています。
>
>  優先度の指定時に、_EXEPRIORITY設定によっては
> TASK3が動作しているとにTASK4が動作せず、
> TASK4が動作中にTASK3が動作しない
>  ケースはユーザがそのような優先度指定を要求しているのだと、SSPでは考えてる、と理解しました。
>  仕様なら了解です。
>
>
>  起動キューイングの話ですが、折角なのでもう少し考えて見ました。
>
>  起動してしまったタスクのready_primapフラグを使うケースは無いような気がしています。
>  タスクの軌道前にprimap_clearをすると、sanple1ではASPと同様にキューイングが実現できているように動作します。
>  ただし、sample1以外のケースのことまでは考えていません。
>
>  sample1でキーから 2,a,1,a,a,e,e,2,e と操作すると以下のように動作します。
>
> void run_task(uint_t ipri)の修正
>  do {
>   runtsk_ipri = tinib_epriority[next_pri];
>
>   /* ビットマップクリア. */
>   primap_clear(next_pri); // タスク起動前に移動
>
>   /* CPUロック解除 */
>   t_unlock_cpu();
>
>   /* タスク実行開始 */
>   (*((TASK)(tinib_task[next_pri])))(tinib_exinf[next_pri]);
>
>   if (t_sense_lock()) {
> 実行結果
> Sample program starts.
>  Task  2 activate.  2,eでTASK2が起動
>  Task  2 running.
>  Task  2 running.
>  Task  2 running.
>  Task  1 activate.  1,aでTASK1が起動、TASK2より優先度が高いのでTASK2は動作としては待たされている(又、叱られそう)
>  Task  1 running.
>  Task  1 running.  aでTASK1の起動キューイング
>  Task  1 running.
>  Task  1 running.
>  Task  1 running.
>  Task  1 exit.     eでTASK1終了したが
>  Task  1 activate.  TASK1のキューイングでTASK1起動
>  Task  1 running.
>  Task  1 running.
>  Task  1 exit.     e、でタスク終了
>  Task  2 running.  中断中のTASK2が動作を継続
>  Task  2 running.
>  Task  2 running.
>  Task  2 running.
>  Task  2 running.
>  Task  2 exit.     2、eでタスク終了
>  なんとなく出来そうですね。
>
>  以上
> 2012年1月19日23:09 Naoki Saito <nsaito.nmiri @ gmail.com>:
>>
>> 斉藤です.
>>
>>
>> > >  優先度の問題は設計方針の話だと思っています。現行、_EXEPRIORITYが一つのとき矛盾した値を設定すとCFGがエラーを通知してくれています。(私はCFGのプログラムを読みきれません。私がテストしたケースはエラーになった。テストした値は忘れました) _EXEPRIORITYを2つ設けて前に書いたような設定をしたとき、(私的には)矛盾が起きます。これが仕様で、使い方の誤りというなら了解です。
>>
>> 仕様上は間違いではありません.
>> その上で,間違った使い方(パラメータの設定の仕方がおかしいとか)であるか
>> どうかについては,何をしたいプログラムかによりますので,分かりません.
>>
>> >
>> > ・ 例で上げたケースをCFGでエラーにすることは出来とおもいます。_kernel_tinib_epriorityが昇順(同じ値は正しい)でなければエラーでよいと思います。
>>
>> 仕様上は誤りではありませんので,エラーには出来ません.
>> _kernel_tinib_epriority が昇順であるべきという意見はまだ良く理解出来ていません.
>> その必要は無いと考えています.
>>
>> それから,(toppers-users 3790) にて,
>> >>> 2番目の文に対しては,当然でたらめになり得ます.
>> と書きましたが,「でたらめ(出鱈目)」という言葉は辞書で
>> 「根拠が無い」とか「首尾一貫しない」というような意味だそうです.
>>
>> 一応は,仕様で定められた振る舞いを行うように作っていまして
>> 仕様上説明の出来ない結果を出さないようにしているつもりです.
>> (もちろんテストしてますがバグが無いことを完全に示せている訳では
>> ありませんし,開発環境の要因により説明出来ない結果になる可能性は
>> 否定出来ませんが)
>>
>> 従いまして,でたらめというのが,仕様上説明出来ないような結果となることを
>> 意味するのだとしたら,優先度がでたらめになることは基本的にないと
>> 考えております.
>> ただし,使い方によっては目的に沿わない結果となる可能性はあり得ます.
>> という具合に訂正したいと思います.
>>
>> 以上です.
>>
>> 2012年1月19日21:12 koizumi yoshiyuki <koizumiyoshiyuki @ gmail.com>:
>> > こいさんです
>> >
>> >  キューイングの話は、ロックして終了すればよいですね。
>> >
>> > (私の勘違いがありました。タスク終了時の、禁止解除を逆に解釈。フラグのセット、クリア時だけの短い時間のロックを小まめに実施と勝手に理解。長いロックは嬉しくないですからね。ここでは私の想像より長いロックでした。お騒がせしてすみません)
>> >
>>
>> > >  優先度の問題は設計方針の話だと思っています。現行、_EXEPRIORITYが一つのとき矛盾した値を設定すとCFGがエラーを通知してくれています。(私はCFGのプログラムを読みきれません。私がテストしたケースはエラーになった。テストした値は忘れました) _EXEPRIORITYを2つ設けて前に書いたような設定をしたとき、(私的には)矛盾が起きます。これが仕様で、使い方の誤りというなら了解です。
>> >
>> >  ただし、回避策としては
>> >
>> > ・ 例で上げたケースをCFGでエラーにすることは出来とおもいます。_kernel_tinib_epriorityが昇順(同じ値は正しい)でなければエラーでよいと思います。
>> >
>> > ・ 又、Cortex-M3の割り込み優先度のように優先度を16*2にしてprimap_searchの優先度は前半の16bitを使う手法もあるとは思います。こちらは意図が変わるので採用はどうかと思う。
>> >
>> > どちらも本当に出来かまで考えたわけでは有りません。
>> >  SSPはダイナミックに優先度が変更できるシステムではないので回避策はあると思っています。
>> >
>> >  似たような意味のパラメータを2箇所で指定すると指定誤りは犯しやすいものです(特に私は)。
>> >  それが仕様なら、注意書きくらい欲しいですね。
>> >
>> >  又、余分な話
>> >  勝手ながら、_PRIORITYはdefineではなく、enumにした方がスマートな気もします。(歴史的な経緯も有るでしょう、余分な話ですね)
>> >  _EXEPRIORITYは即値ではなく、xx_PRIORITYが良いかな。 と独り言。
>> >
>> >  そうだ、こんな書き方もありますかね。
>> > #if 0
>> > #define INIT_PRIORITY   (1)
>> > #define MAIN_PRIORITY   (2)
>> > #define TASK1_PRIORITY   (3)
>> > #define TASK2_PRIORITY   (4)
>> > #define TASK3_PRIORITY   (5)
>> > #define TASK4_PRIORITY   (6)
>> > #define TASK3_EXEPRIORITY  (4)
>> > #define TASK4_EXEPRIORITY  (3)
>> > #else
>> > enum {
>> >  INIT_PRIORITY = 1,
>> >  MAIN_PRIORITY,
>> >  TASK1_PRIORITY,
>> >  TASK2_PRIORITY,
>> >  TASK3_EXEPRIORITY = TASK2_PRIORITY,
>> >  TASK4_EXEPRIORITY = TASK2_PRIORITY, //if0の矛盾とは違っています
>> >  TASK3_PRIORITY,
>> >  TASK4_PRIORITY,
>> > };
>> > #endif
>> >  _EXEPRIORITYは前に書くので美しくないかね。
>> >
>> >  以上
>> >
>> > 2012年1月19日19:39 Naoki Saito <nsaito.nmiri @ gmail.com>:
>> >>
>> >> 斉藤です。
>> >>
>> >> >  2番目の文に対しては,当然でたらめになり得ます.
>> >> > しかしそれは使い方次第です.どんなむちゃくちゃなプロ グラムを書いても
>> >> > ちゃんと動けというのはそりゃムリです.
>> >>
>> >> とはいいましても
>> >> できるだけ問題を検知出来るような、
>> >> OSやツールの機能が提供できれば
>> >> とも考えておりますので、
>> >> どのような心配事が有り得るか
>> >> 御教示いただければとも思います。
>> >>
>> >> 以上、よろしくお願いします。
>> >>
>> >> 2012/01/19 18:58 "Naoki Saito" <nsaito.nmiri @ gmail.com>:
>> >>>
>> >>> 斉藤です.
>> >>> (toppers-users 3788) を確認したという前提の元で,お返事します.
>> >>>
>> >>> > TASK3が動作しているときはTASK4が動かず、
>> >>> (略)
>> >>> >  これが意図とでは優先度とは何よと思いたくなるのは、私だけでしょうかね。
>> >>>
>> >>> 逆に.優先度とはどのようなものと思われたのか,興味を持ちました.
>> >>>
>> >>> 例として仰られたようなケースは一つの使い方でして,
>> >>> そのような挙動をさせたいというケースもないとはいえないです.
>> >>> 例えば (toppers-users 3781) で高田先生が仰られた様な
>> >>> スタック領域が少なくて済むようにしたいというのもその一つかと思います.
>> >>> 排他制御のためにそうしたいという理由もあると思います.
>> >>>
>> >>>
>> >>> >
>> >>> > > >  どちらのタスクが優先度が高いのかと一言で表現できないのは、美しくないと思います。やる人はいないと思うが、もっと複雑な(誤った?)設定をした場合、優先度がでたらめになりませんか。
>> >>>
>> >>> 最初の文に対して,
>> >>> 美しいかどうかは主観的な評価なのでなんとも申し上げることは出来ませんが
>> >>> 仰るような考え方によりますと,動的に優先度が変更し得るOSは皆美しくない
>> >>> ことになりますね.そういう理解で合ってますでしょうか?
>> >>> 現存するOSはそういうものも割と多いと思いますが,どう思われます?
>> >>>
>> >>> 2番目の文に対しては,当然でたらめになり得ます.
>> >>> しかしそれは使い方次第です.どんなむちゃくちゃなプログラムを書いても
>> >>> ちゃんと動けというのはそりゃムリです.
>> >>>
>> >>> 以上,適切なお答えになっているか心配ですが,よろしくお願いします.
>> >>>
>> >>> 2012年1月19日16:15 koizumi yoshiyuki <koizumiyoshiyuki @ gmail.com>:
>> >>> >  こいさんです
>> >>> >
>> >>> >  理屈としては解るのですが、この場合
>> >>> > TASK3が動作しているときはTASK4が動かず、
>> >>> > TASK3が動作しているときはTASK4が動きません。
>> >>> >  これが意図とでは優先度とは何よと思いたくなるのは、私だけでしょうかね。
>> >>> >
>> >>>
>> >>> >
>> >>> > > >  どちらのタスクが優先度が高いのかと一言で表現できないのは、美しくないと思います。やる人はいないと思うが、もっと複雑な(誤った?)設定をした場合、優先度がでたらめになりませんか。
>> >>> >
>> >>> >  まあ、意図なら納得するしかありません。
>> >>> >
>> >>> >  以上
>> >>> >
>> >>> > 2012年1月19日15:39 Naoki Saito <nsaito.nmiri @ gmail.com>:
>> >>> >>
>> >>> >> こいさんさん
>> >>> >>
>> >>> >> 斉藤です.
>> >>> >>
>> >>> >> >  現行のSSPのCFGで以下の設定をすると、優先度反転が発生します。これは良いのでしょうか。
>> >>> >> >  TASK3が動作中にTASK4はTASK3より優先度が高いのに起動できません。
>> >>> >>
>> >>> >> TASK3 の実行時優先度は4で,TASK4の起動時優先度は6ですので
>> >>> >> TASK4 は TASK3 より優先度が低い(数値としては大きい)です.
>> >>> >> したがってTASK4 が起動出来ないのは仕様に沿っているように思います.
>> >>> >>
>> >>> >> >  CFGで生成されたkernel_cfg.cは以下のようになり、TASK3とTASK4の優先度の反転が発生しています。
>> >>> >> >
>> >>> >> > const uint_t   _kernel_tinib_epriority[TNUM_TSKID] =
>> >>> >> >
>> >>> >> >
>> >>> >> >
>> >>> >> > {INT_PRIORITY(1),INT_PRIORITY(2),INT_PRIORITY(3),INT_PRIORITY(4),INT_PRIORITY(4),INT_PRIORITY(3)};
>> >>> >>
>> >>> >> これは実行時優先度を格納する配列です.
>> >>> >> プリエンプトが発生するかどうかは
>> >>> >> 実行中タスクの実行時優先度と起動要求タスクの起動時優先度とを
>> >>> >> 比較します.従いまして,TASK4 の実行時優先度はこの場合参照されません.
>> >>> >>
>> >>> >> 以上,よろしくお願いします.
>> >>> >>
>> >>> >> 2012年1月19日10:59 koizumi yoshiyuki <koizumiyoshiyuki @ gmail.com>:
>> >>> >> >    高田先生
>> >>> >> >
>> >>> >> >  こいさんです。表現は色々有ると思いますが、私にはSSPは優先度を2つ持っているように見えています。
>> >>> >>
>> >>> >> >
>> >>> >> > > >  2つの優先度は _PRIORITY >_EXEPRIORITY 設定されてる必要が有るでしょう。これは解りにくいケースもあると思います。
>> >>> >> >
>> >>> >>
>> >>> >> >
>> >>> >> > >
>> >>> >> > > > >  同じようなケースが(私にはある意味、同じように見えています)Cortex-M3の割り込み優先度に見られます。ここでは優先度を上位/下位の2つに分け、上位側で横取り割り込み優先度とし、下位側は等優先度内(制約タスク相当)の優先度としています。外からは優先度は一つしかないので優先度設定の混乱を避けることができていると思います。
>> >>> >> >
>> >>> >> >  尚、
>> >>> >> >  現行のSSPのCFGで以下の設定をすると、優先度反転が発生します。これは良いのでしょうか。
>> >>> >> >  TASK3が動作中にTASK4はTASK3より優先度が高いのに起動できません。
>> >>> >> >
>> >>> >> >  テストタスクを3つから4つに増やし優先度を以下のように設定する
>> >>> >> >
>> >>> >> >  sample1.h
>> >>> >> > #define INIT_PRIORITY   (1)
>> >>> >> > #define MAIN_PRIORITY   (2)
>> >>> >> > #define TASK1_PRIORITY   (3)
>> >>> >> > #define TASK2_PRIORITY   (4)
>> >>> >> > #define TASK3_PRIORITY   (5)
>> >>> >> > #define TASK4_PRIORITY   (6)
>> >>> >> > #define TASK3_EXEPRIORITY  (4)
>> >>> >> > #define TASK4_EXEPRIORITY  (3)
>> >>> >> >
>> >>> >> >  sample1.cfgを以下のように記述
>> >>> >> > CRE_TSK(INIT_TASK , { TA_ACT , 0 , init_task , INIT_PRIORITY ,
>> >>> >> > STACK_SIZE ,
>> >>> >> > NULL });
>> >>> >> > CRE_TSK(MAIN_TASK , { TA_NULL , 0 , main_task , MAIN_PRIORITY ,
>> >>> >> > STACK_SIZE ,
>> >>> >> > NULL });
>> >>> >> > CRE_TSK(TASK1 , { TA_NULL , 1 , task , TASK1_PRIORITY ,
>> >>> >> > STACK_SIZE ,
>> >>> >> > NULL
>> >>> >> > });
>> >>> >> > CRE_TSK(TASK2 , { TA_NULL , 2 , task , TASK2_PRIORITY ,
>> >>> >> > STACK_SIZE ,
>> >>> >> > NULL
>> >>> >> > });
>> >>> >> > CRE_TSK(TASK3 , { TA_NULL , 3 , task , TASK3_PRIORITY ,
>> >>> >> > STACK_SIZE ,
>> >>> >> > NULL
>> >>> >> > });
>> >>> >> > CRE_TSK(TASK4 , { TA_NULL , 4 , task , TASK4_PRIORITY ,
>> >>> >> > STACK_SIZE ,
>> >>> >> > NULL
>> >>> >> > });
>> >>> >> > DEF_EPRI(TASK3 , { TASK3_EXEPRIORITY });
>> >>> >> > DEF_EPRI(TASK4 , { TASK4_EXEPRIORITY });
>> >>> >> >  CFGで生成されたkernel_cfg.cは以下のようになり、TASK3とTASK4の優先度の反転が発生しています。
>> >>> >> >
>> >>> >> > const uint_t   _kernel_tinib_epriority[TNUM_TSKID] =
>> >>> >> >
>> >>> >> >
>> >>> >> >
>> >>> >> > {INT_PRIORITY(1),INT_PRIORITY(2),INT_PRIORITY(3),INT_PRIORITY(4),INT_PRIORITY(4),INT_PRIORITY(3)};
>> >>> >> >  以上
>> >>> >
>> >>> >
>> >
>> >
>
>