(toppers-users 3853) Re: SSP 同一実行優先度のディパッチアルゴリズムの機能の追加

高橋和浩@nifty takahashi_kazuhiro @ nifty.com
2012年 1月 30日 (月) 19:34:20 JST


こんさんさん 
こんばんは、アライブビジョンソフトウエアの高橋です。

(toppers-users 3834)はだいたい合ってるかなと思っていますが、
これはちょっと違うと思います。メールで説明できないケースもあるので、
開発者からコメントいただいたほうがいいと思います。

たぶん1点間違えと、もう一点コメントします。

1.  }else if((saved_pri == (next_pri = search_schedtsk()))){
これは、戻り先の実行時優先度と今起動されたタスクの起動時優先度の比較ですよ。


2.プリエンプトできても狭義の省スタック化できないですよね
改造方法はいろいろあると思いますが、実行時優先度が同一で起動時優先度の違うものを
同一優先度として扱い、後押し優先でスケジュールすることも実装上可能だと思いますが
プリエンプトされるということは、(toppers-users 3839)の狭義の省スタック化はできない
ので、それよりも (toppers-users 3818)の5.先取り方式の提案 のほうがいいと思います。
FCFSのスケジューリングになります(共通用語で書くようにします)。

(toppers-users 3818)には考え方しか書いていなかったので補足します。

------------------------------------------------------------------------------
UB	pri_tbl[16];

初期化時
pri_tbl[0] = 0;
pri_tbl[1] = 1;
〜同様〜
pri_tbl[15] = 15;



--------------------------------------------------
まずスケジューラ部分
テーブルから引いてくるのみです。
起動時優先度(0-15)から実態のTCBを参照する場合にpri_tblをかまして合わせこみます。
スケジュールビットの演算はそのままやります。
	do {
		runtsk_ipri = tinib_epriority[pri_tbl[next_pri]]; // ここと違うだけ
		
		/* CPUロック解除 */
		t_unlock_cpu();
		
		/* タスク実行開始 */
		(*((TASK)(tinib_task[pri_tbl[next_pri]])))(tinib_exinf[pri_tbl[next_pri]]); //ここが違うだけ
		
		if (t_sense_lock()) {
			/*
			 *  CPUロック状態でext_tskが呼ばれた場合は,CPUロックを解除し
			 *  てからタスクを終了する.実装上は,サービスコール内でのCPU
			 *  ロックを省略すればよいだけ.
			 */
		}
		else {
			/*
			 *  このt_lock_cpuをこの下のdisdspの設定のようにしないのは,
			 *  CPUロック中に再度t_lock_cpuを呼ばないためである.
			 */
			t_lock_cpu();
		}
		
		/* 割込み優先度マスクは全解除状態のはずなので,何もしない */
		
		/*
		 *  ディスパッチ禁止状態でext_tskが呼ばれた場合は,ディスパッ
		 *  チ許可状態にしてからタスクを終了する.
		 *
		 *	本来は以下のように記述すべきであるが,いずれにせよdisdspを
		 *	falseにすればいいため,単にfalseに設定する.
		 *
		 *		if (disdsp) {
		 *			disdsp = false;
		 *		}
		 */
		disdsp = false;
		
		/* ビットマップクリア. */
		primap_clear(next_pri);		//ここはそのまま
		
	  /* 戻り先タスクの実行時優先度より高い起動時優先度をもつタスクが起動されたか */
	} while((!primap_empty()) && (saved_pri > (next_pri = search_schedtsk())));	//ここもそのまま


-------------------------------------------------
あとタスク起動のときに起動時優先度をスワップする。iact_tskのみだけど act_tskも同様だと思う。

iact_tsk(ID tskid)
{
	ER		ercd;
	uint_t	ipri;
	uint_t	ipri_org;		// オリジナルの起動優先度
	uint_t 	same_stack_map;		//狭義の省スタック化できるタスクマップ
	
	LOG_IACT_TSK_ENTER(tskid);
	CHECK_INTCTX_UNL();
	CHECK_TSKID(tskid);
	ipri_org = pri_tbl[get_ipri(tskid)];			// tblからデータを持ってくるようにする

	i_lock_cpu();
	if (test_dormant(ipri_org)) {

		same_task_map = get_task_map_same_group(taskid); // たとえば タスク1とタスク2が狭義の省スタック化なら 0x03を返す。
		if (same_task_map !=0) 				//非該当は従来どおり、非該当なら0を返す仕様とする
		{
			same_task_map = &(~ready_primap);		// すでに実行可能状態のものはマスクする
			ipri =	bitmap_search(same_task_map);		//  同一グループの中で起動優先度の高いものを選ぶ
			pri_tbl[ipri] = ipri_org;			// スワップする
			pri_tbl[ipri_org] = ipri;
		}
		else
		{
			ipri = ipri_org;
		}

		if(make_active(ipri)) {				// これでビットマップだけ起動優先度が高いものに
								// セットされる。
			reqflg = true;
		}
		ercd = E_OK;
	}
	else {
		ercd = E_QOVR;
	}
	i_unlock_cpu();

----------------------------------------

get_task_map_same_group()はサボりましたが、cfgのテーブルをどう料理するかの話なので
割愛してます。
これで実現できると思いますがいかがでしょうか?



On Mon, 30 Jan 2012 15:52:54 +0900
koizumi yoshiyuki <koizumiyoshiyuki @ gmail.com> wrote:

>  こいさんです
> 
> 同一優先度で過負荷になった場合ディスパッチされないタスクが発生する問題の、一つの対策案です。
> 
> ・ 同一優先度のディパッチアルゴリズムを追加できるようにrun_task()を変更して見ました。
> 
> void run_task(uint_t ipri)
> {
>  uint_t next_pri; /* 次に実行開始するタスクの起動時優先度 */
>  uint_t saved_pri; /* 呼び出し元タスクの起動時優先度 */
> 
>  next_pri = ipri;
>  saved_pri = runtsk_ipri;
> 
>  runtsk_ipri = tinib_epriority[next_pri];
>  do {
>   /* CPUロック解除 */
>   t_unlock_cpu();
>   /* タスク実行開始 */
>   (*((TASK)(tinib_task[next_pri])))(tinib_exinf[next_pri]);
>   if (t_sense_lock()) {
>   }else {
>    t_lock_cpu();
>   }
>   disdsp = false;
>   /* ビットマップクリア. */
>   primap_clear(next_pri);
>   if(primap_empty())break;
>   if((saved_pri < (next_pri = search_schedtsk()))){
>    break;
>   }else if((saved_pri == (next_pri = search_schedtsk()))){
> //   runtsk_ipri = samePri();
>    break;
>   }else{
>    runtsk_ipri = tinib_epriority[next_pri];
>   }
>  } while(1);
> 
>  runtsk_ipri = saved_pri;
> }
> この修正でsample1は従来と同様に動作するはずです。samePri();に同一実行優先度のディパッチアルゴリズム処理を組み込めは、その他は従来と変わりません。アルゴリズムの修正には起動優先度も必要でしょう。runtsk_ipriをunionにして起動優先度、実行時優先度を保存します。_kernel_tinib_epriorityで隣接する同一実行優先度タスクをラウンドロビンに修正するのは容易だと思っています。ラウンドロビンはFCFSでは有りませんが、サービスされないケースは回避できます。
> 
>> 別件ですが、基本的にrun_taskはロック解除で動作させたいと思っています。ディパッチ関連でロックが必要なのはready_primapのsetとclearなので(読み出しはロック不要)、ここだけロックすればよいはずです。runtsk_ipriに2つの情報を含めた場合、個別にアクセスすればロックが必要になりますが、unionで同時にアクセスすれば回避できるでしょう。うまくやれば、act_taskのキュー処理追加も容易に出来ると思っています。
> Cortex-M3に限るなら、ビットバインドエイリアスを使えばready_primapのsetとclearをロックを使わずにアトミックに実現できます。ロック時間の短縮は、確証はありませんが、出来そうな気はしています。
> SSP程度の機能なら、色々面白い作り方が有ると思っています。
> 
> 以上
---
アライブビジョンソフトウエア株式会社
高橋和浩
673-0005兵庫県明石市小久保2-2-7幹線ビル4F
Email:takahashi_kazuhiro @ nifty.com
http://homepage3.nifty.com/ALVS/