(toppers-users 2451) Re: TOPPERS/FI4 のバグ

ykominami ykominami @ nifty.com
2006年 6月 14日 (水) 10:16:07 JST


小南です。

On Tue, 13 Jun 2006 17:25:01 +0900
takaya_kakizaki @ gmx.yamaha.com wrote:

> 柿崎です。
> 
> >これは、include/t_services.hで定義されたsyscallマクロによる
> >出力だと思います。
> >その場合、同じt_services.hで定義された_t_perror関数を呼び出します。
> >この関数の中で、エラーコードが0より小さい場合、すなわちE_OK以外の
> >場合は、上記のメッセージを出力します。
> >このマクロは簡易的なもので、エラーコードがE_OKか、E_OK以外かしか
> >判断しません。
> >tcal_porの場合、指定時間内にランデブが成立しなければE_OKではなく、
> >E_TMOUTが返ってきます。
> 
> >具体的な返値が知りたいです。
> 
> 一応、t_perrorはITRONのエラーコードは判別するはずです。
> unknownとあるのでITRONのエラーコード以外のコードが出力されたことを
> 意味します。
t_perrorに関しては、勘違いしていました。すみません。
 
> 具体的にエラーコードを調べてみましたら、
> -1945091748,-1945083556
> 等、毎回呼び出すたびに異なる値を返します。
> 問題のコードの直後に
>                 if (winfo.winfo.wercd == E_OK) {
>                         ercd = winfo.msgsz;
>                 } else {
>                         ercd = winfo.winfo.wercd;
>                 }
> 
> こんな処理をおこなっているので、おそらくディスパッチを行わずに
> 制御が帰っているため(wobj_make_waitの待ち状態が解除されていない)
> winfo.winfo.wercdの初期化がなされていない
> のだと思います。
他のサービスコールの場合も確認してみましたが、自タスクつまり実行状態の
タスクが待ち状態に入る場合は、必ずdispatch()を呼び出す必要があります。
他のタスク、つまり実行可能状態のタスク(の集まり)に変化があった場合とは、
処理方法が異なります。

サービスコールの処理の冒頭のCHECK_DISPATCH()マクロで、ディスパッチ禁止
状態でないことを確認しています。
またt_lock_cpu()という内部関数を呼んでいますので、割り込み処理などの
影響でディスパッチの必要性の判定が影響されることはないです。
wait_complete()がfalseを返したとしても、それはディスパッチ禁止状態
だからという理由ではないはずです。
#実際にどういう理由かは確認する必要はありますが。

(t)cal_porは、上記の2種類のタスクの変化が同時に発生するものでした。
このことを私自身見落としていました。

(t)cal_porに関しては、最初に柿崎さんがおっしゃられていたように、
wait_complete()の結果に関わらずdispatch()を呼び出す必要があると
思います。
また、もう一歩すすめて、

 if (queue != NULL) { ... } else { ... }

からdispatch()の呼び出しと、dispatch()から返ってきた場合の
処理を括り出してもよいのではないかと考えます。


 (略)

> >ITRON仕様と実装に話を分けます。
> >
> >ITRON仕様上は、ディスパッチを発生させる要因が存在すれば、ディスパッチ
> >をさせないといけません。
> >ただし、ディスパッチはディスパッチを行える状態の場合でないと行えません。
> >したがって、タイミングは要因の発生と同時ではなく、ずれることがあります。
> >
> >
> >ディスパッチ保留状態でない場合の処理に話をしぼると、実装の話になります。
> >
> >実装上は、ディスパッチを発生させる要因が生じたら、その直後にディスパッチ
> >をするか、直後でなく他の処理も行ってから、ディスパッチをすべきかを判断し
> >て、ディスパッチをするかですが、ソースコード上の見通しの良さと処理速度の
> >トレードオフ範囲内の話だととらえています。
> >サービスコールの不可分性も守られているわけですし。
> >
> >今回のような待ち解除もいろいろなサービスコールから呼び出される可能性が
> >あるため、待ち解除の直後にディスパッチを行うとしたら、どういう状態で待ち
> >解除を行ったかの条件判別が必要になる(それこそサービスコール毎に異なる処
>> >が必要になるかもしれません)と思います。
> 
> 確かにそのとおりだと思います。
> 
> μITRON4.0のランデブの章では、ランデブの成立時にどのタイミングで
> ディスパッチを行うかは言及していません。ただし、
> 「タスクAがcal_porを呼び出し、タスクBがacp_porを呼び出した時点でランデブが
> 成立し、タスクAを待ち状態としたまま、タスクBが待ち解除される。このとき
> タスクAは、ランデブの終了待ち状態になっている。」
> とあるので、タスクBの待ちが解除され、カーネル実行状態から離れたとき
> タスクA : ランデブ終了待ち
> タスクB : 実行可能状態(あるいは強制待ち状態)
> 
> という状態である必要があります。
> 
> 具体的には
> 
>                 wobj_make_wait((WOBJCB *)rdvcb, (WINFO_WOBJ *)&winfo);
>                 wait_complete(tcb);
>                 dispatch();
> 
> は許されるけれども、
> 
>                 if(wait_complete(tcb)){
>                         dispatch();
>                 }
>                 wobj_make_wait((WOBJCB *)rdvcb, (WINFO_WOBJ *)&winfo);
>                 dispatch();
> 
> 
> 等は許されないことになります。
> (タスクAが実行可能状態になってしまうため)
> 
>                 wobj_make_wait((WOBJCB *)rdvcb, (WINFO_WOBJ *)&winfo);
>                 dispatch();
>                 if(wait_complete(tcb)){
>                         dispatch();
>                 }
> 
> 
> これはどうなのでしょう?
> ITRONの解釈が間違ってたらご指摘ください。
> (今回のバグとは話がずれました)

上に書きましたように、 実行状態のタスクが待ち状態に入る場合は、必ず
明示的にdispatch()を呼び出す必要があると思います。
 
> ただしいかなる場合でも、サービスコールを呼び出したタスクが待ち状態に
> 遷移するときにディスパッチが行われないパスができてしまうと
> 今回のようにTOPPERSは破綻してしまいます。

同意します。


----------------------------------- 
小南 ykominami @ nifty.com