(toppers-users 2572) FI4 のイベントフラグの実装について

takaya_kakizaki @ gmx.yamaha.com takaya_kakizaki @ gmx.yamaha.com
2007年 2月 13日 (火) 11:35:34 JST


柿崎と申します。

FI4カーネルのイベントフラグの実装を眺めていたのですが、
set_flgの実装は以下のようになっており、
TA_WMUL かつ TA_CLRの場合にも待ち行列の先頭でしかフラグのマッチングを行わ
ず、
結果、フラグの条件を満たしていたとしても待ちが解除されない場合が発生する
気がします。
もう一点、現在の実装ではTA_WMULでの待ち解除のとき、
待ち行列の数え上げのwhileループの中でディスパッチを行ってしまうので、
イベントフラグの全ての待ちが解除されないまま、タスクに制御が移ってしまいま
す。

μITRON4.0仕様の3.5.3ではスタンダードプロファイル外では
サービスコールの不可分性は実装依存ということのようですが
今回の場合はwhileループの外にディスパッチ処理を出せばよいだけなので
そうした方がよりよいと考えます。


ご意見お願いします。


[修正前]

        if ((flgcb->flginib->flgatr & TA_WMUL) != TA_WMUL ||
            (flgcb->flginib->flgatr & TA_CLR) == TA_CLR) {
                if (!(queue_empty(&(flgcb->wait_queue)))) {
                        BOOL disp;
                        queue = flgcb->wait_queue.next;
                        chk_flg_cond(flgcb, queue, &disp);
                        if (disp) {
                                dispatch();
                        }
                }
        } else {
                queue = NULL;
                while ((queue = queue_enumerate(&(flgcb->wait_queue), 
queue)) != NULL) {
                        BOOL disp;
                        queue = chk_flg_cond(flgcb, queue, &disp);
                        if (disp) {
                                dispatch();
                        }
                }
        }


[修正後]
        BOOL disp = FALSE;

        if ((flgcb->flginib->flgatr & TA_WMUL) != TA_WMUL) {
                if (!(queue_empty(&(flgcb->wait_queue)))) {
                        queue = flgcb->wait_queue.next;
                        chk_flg_cond(flgcb, queue, &disp);
                }
        } else {
                queue = NULL;
                while ((queue = queue_enumerate(&(flgcb->wait_queue), 
queue)) != NULL) {
                        queue = chk_flg_cond(flgcb, queue, &disp);
                        /*  [kakizaki] 不具合修正(TA_CLR指定の場合待ち行列
の先頭しか見ていなかった) */
                        /* 戻り値dispはディスパッチするかどうかの判定であ
って、フラグ条件を満たしたかどうかではないので */
                        /* 微妙な判定法ではある */
                        if (disp && flgcb->flginib->flgatr & TA_CLR) == 
TA_CLR) {
                                break;
                        }
                }
        }

        /* [kakizaki] 不具合修正(ディスパッチをwhileループの外へ出す) */
        if(disp){
                dispatch();
        }