00001 /* 00002 * TOPPERS/ASP Kernel 00003 * Toyohashi Open Platform for Embedded Real-Time Systems/ 00004 * Advanced Standard Profile Kernel 00005 * 00006 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory 00007 * Toyohashi Univ. of Technology, JAPAN 00008 * Copyright (C) 2005-2008 by Embedded and Real-Time Systems Laboratory 00009 * Graduate School of Information Science, Nagoya Univ., JAPAN 00010 * 00011 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ 00012 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改 00013 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する. 00014 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 00015 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー 00016 * スコード中に含まれていること. 00017 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 00018 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 00019 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 00020 * の無保証規定を掲載すること. 00021 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 00022 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ 00023 * と. 00024 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 00025 * 作権表示,この利用条件および下記の無保証規定を掲載すること. 00026 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに 00027 * 報告すること. 00028 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 00029 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. 00030 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理 00031 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを 00032 * 免責すること. 00033 * 00034 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お 00035 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的 00036 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ 00037 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ 00038 * の責任を負わない. 00039 * 00040 * @(#) $Id: task.c 748 2008-03-07 17:18:06Z hiro $ 00041 */ 00042 00043 /* 00044 * タスク管理モジュール 00045 */ 00046 00047 #include "kernel_impl.h" 00048 #include "wait.h" 00049 #include "task.h" 00050 00051 /* 00052 * トレースログマクロのデフォルト定義 00053 */ 00054 #ifndef LOG_TEX_ENTER 00055 #define LOG_TEX_ENTER(texptn) 00056 #endif /* LOG_TEX_ENTER */ 00057 00058 #ifndef LOG_TEX_LEAVE 00059 #define LOG_TEX_LEAVE(texptn) 00060 #endif /* LOG_TEX_LEAVE */ 00061 00062 #ifdef TOPPERS_tskini 00063 00064 /* 00065 * 実行状態のタスク 00066 */ 00067 TCB *p_runtsk; 00068 00069 /* 00070 * 最高優先順位のタスク 00071 */ 00072 TCB *p_schedtsk; 00073 00074 /* 00075 * タスクディスパッチ/タスク例外処理ルーチン起動要求フラグ 00076 */ 00077 bool_t reqflg; 00078 00079 /* 00080 * ディスパッチ禁止状態 00081 */ 00082 bool_t disdsp; 00083 00084 /* 00085 * タスクディスパッチ可能状態 00086 */ 00087 bool_t dspflg; 00088 00089 /* 00090 * レディキュー 00091 */ 00092 QUEUE ready_queue[TNUM_TPRI]; 00093 00094 /* 00095 * レディキューサーチのためのビットマップ 00096 * 00097 * ビットマップサーチ関数で優先度が16段階であることを仮定しているため, 00098 * uint16_t型としている. 00099 */ 00100 uint16_t ready_primap; 00101 00102 /* 00103 * タスク管理モジュールの初期化 00104 */ 00105 void 00106 initialize_task(void) 00107 { 00108 uint_t i, j; 00109 TCB *p_tcb; 00110 00111 p_runtsk = p_schedtsk = NULL; 00112 reqflg = false; 00113 disdsp = false; 00114 dspflg = true; 00115 00116 for (i = 0; i < TNUM_TPRI; i++) { 00117 queue_initialize(&(ready_queue[i])); 00118 } 00119 ready_primap = 0U; 00120 00121 for (i = 0; i < tnum_tsk; i++) { 00122 j = INDEX_TSK(torder_table[i]); 00123 p_tcb = &(tcb_table[j]); 00124 p_tcb->p_tinib = &(tinib_table[j]); 00125 p_tcb->actque = false; 00126 make_dormant(p_tcb); 00127 if ((p_tcb->p_tinib->tskatr & TA_ACT) != 0U) { 00128 make_active(p_tcb); 00129 } 00130 } 00131 } 00132 00133 #endif /* TOPPERS_tskini */ 00134 00135 /* 00136 * ビットマップサーチ関数 00137 * 00138 * bitmap内の1のビットの内,最も下位(右)のものをサーチし,そのビッ 00139 * ト番号を返す.ビット番号は,最下位ビットを0とする.bitmapに0を指定 00140 * してはならない.この関数では,優先度が16段階であることを仮定し, 00141 * bitmapをuint16_t型としている. 00142 * 00143 * ビットサーチ命令を持つプロセッサでは,ビットサーチ命令を使うように 00144 * 書き直した方が効率が良い場合がある.このような場合には,ターゲット 00145 * 依存部でビットサーチ命令を使ったbitmap_searchを定義し, 00146 * OMIT_BITMAP_SEARCHをマクロ定義すればよい.また,ビットサーチ命令の 00147 * サーチ方向が逆などの理由で優先度とビットとの対応を変更したい場合に 00148 * は,PRIMAP_BITをマクロ定義すればよい. 00149 * 00150 * また,標準ライブラリにffsがあるなら,次のように定義して標準ライブ 00151 * ラリを使った方が効率が良い可能性もある. 00152 * #define bitmap_search(bitmap) (ffs(bitmap) - 1) 00153 */ 00154 #ifndef PRIMAP_BIT 00155 #define PRIMAP_BIT(pri) (1U << (pri)) 00156 #endif /* PRIMAP_BIT */ 00157 00158 #ifndef OMIT_BITMAP_SEARCH 00159 00160 static const unsigned char bitmap_search_table[] = { 0, 1, 0, 2, 0, 1, 0, 00161 3, 0, 1, 0, 2, 0, 1, 0 }; 00162 00163 Inline uint_t 00164 bitmap_search(uint16_t bitmap) 00165 { 00166 uint_t n = 0U; 00167 00168 assert(bitmap != 0U); 00169 if ((bitmap & 0x00ffU) == 0U) { 00170 bitmap >>= 8; 00171 n += 8; 00172 } 00173 if ((bitmap & 0x0fU) == 0U) { 00174 bitmap >>= 4; 00175 n += 4; 00176 } 00177 return(n + bitmap_search_table[(bitmap & 0x0fU) - 1]); 00178 } 00179 00180 #endif /* OMIT_BITMAP_SEARCH */ 00181 00182 /* 00183 * 優先度ビットマップが空かのチェック 00184 */ 00185 Inline bool_t 00186 primap_empty(void) 00187 { 00188 return(ready_primap == 0U); 00189 } 00190 00191 /* 00192 * 優先度ビットマップのサーチ 00193 */ 00194 Inline uint_t 00195 primap_search(void) 00196 { 00197 return(bitmap_search(ready_primap)); 00198 } 00199 00200 /* 00201 * 優先度ビットマップのセット 00202 */ 00203 Inline void 00204 primap_set(uint_t pri) 00205 { 00206 ready_primap |= PRIMAP_BIT(pri); 00207 } 00208 00209 /* 00210 * 優先度ビットマップのクリア 00211 */ 00212 Inline void 00213 primap_clear(uint_t pri) 00214 { 00215 ready_primap &= ~PRIMAP_BIT(pri); 00216 } 00217 00218 /* 00219 * 最高優先順位タスクのサーチ 00220 */ 00221 #ifdef TOPPERS_tsksched 00222 00223 TCB * 00224 search_schedtsk(void) 00225 { 00226 uint_t schedpri; 00227 00228 schedpri = primap_search(); 00229 return((TCB *)(ready_queue[schedpri].p_next)); 00230 } 00231 00232 #endif /* TOPPERS_tsksched */ 00233 00234 /* 00235 * 実行できる状態への移行 00236 * 00237 * 最高優先順位のタスクを更新するのは,実行できるタスクがなかった場合 00238 * と,p_tcbの優先度が最高優先順位のタスクの優先度よりも高い場合であ 00239 * る. 00240 */ 00241 #ifdef TOPPERS_tskrun 00242 00243 bool_t 00244 make_runnable(TCB *p_tcb) 00245 { 00246 uint_t pri = p_tcb->priority; 00247 00248 p_tcb->tstat = TS_RUNNABLE; 00249 LOG_TSKSTAT(p_tcb); 00250 queue_insert_prev(&(ready_queue[pri]), &(p_tcb->task_queue)); 00251 primap_set(pri); 00252 00253 if (p_schedtsk == (TCB *) NULL || pri < p_schedtsk->priority) { 00254 p_schedtsk = p_tcb; 00255 return(dspflg); 00256 } 00257 return(false); 00258 } 00259 00260 #endif /* TOPPERS_tskrun */ 00261 00262 /* 00263 * 実行できる状態から他の状態への移行 00264 * 00265 * 最高優先順位のタスクを更新するのは,p_tcbが最高優先順位のタスクで 00266 * あった場合である.p_tcbと同じ優先度のタスクが他にある場合は,p_tcb 00267 * の次のタスクが最高優先順位になる.そうでない場合は,レディキューを 00268 * サーチする必要がある. 00269 */ 00270 #ifdef TOPPERS_tsknrun 00271 00272 bool_t 00273 make_non_runnable(TCB *p_tcb) 00274 { 00275 uint_t pri = p_tcb->priority; 00276 QUEUE *p_queue = &(ready_queue[pri]); 00277 00278 queue_delete(&(p_tcb->task_queue)); 00279 if (queue_empty(p_queue)) { 00280 primap_clear(pri); 00281 if (p_schedtsk == p_tcb) { 00282 p_schedtsk = primap_empty() ? (TCB *) NULL : search_schedtsk(); 00283 return(dspflg); 00284 } 00285 } 00286 else { 00287 if (p_schedtsk == p_tcb) { 00288 p_schedtsk = (TCB *)(p_queue->p_next); 00289 return(dspflg); 00290 } 00291 } 00292 return(false); 00293 } 00294 00295 #endif /* TOPPERS_tsknrun */ 00296 00297 /* 00298 * 休止状態への移行 00299 */ 00300 #ifdef TOPPERS_tskdmt 00301 00302 void 00303 make_dormant(TCB *p_tcb) 00304 { 00305 p_tcb->tstat = TS_DORMANT; 00306 p_tcb->priority = p_tcb->p_tinib->ipriority; 00307 p_tcb->wupque = false; 00308 p_tcb->enatex = false; 00309 p_tcb->texptn = 0U; 00310 LOG_TSKSTAT(p_tcb); 00311 } 00312 00313 #endif /* TOPPERS_tskdmt */ 00314 00315 /* 00316 * 休止状態から実行できる状態への移行 00317 */ 00318 #ifdef TOPPERS_tskact 00319 00320 bool_t 00321 make_active(TCB *p_tcb) 00322 { 00323 activate_context(p_tcb); 00324 return(make_runnable(p_tcb)); 00325 } 00326 00327 #endif /* TOPPERS_tskact */ 00328 00329 /* 00330 * タスクの優先度の変更 00331 * 00332 * タスクが実行できる状態の場合には,レディキューの中での位置を変更す 00333 * る.オブジェクトの待ちキューの中で待ち状態になっている場合には,待 00334 * ちキューの中での位置を変更する. 00335 * 00336 * 最高優先順位のタスクを更新するのは,(1) p_tcbが最高優先順位のタス 00337 * クであって,その優先度を下げた場合,(2) p_tcbが最高優先順位のタス 00338 * クではなく,変更後の優先度が最高優先順位のタスクの優先度よりも高い 00339 * 場合である.(1)の場合には,レディキューをサーチする必要がある. 00340 */ 00341 #ifdef TOPPERS_tskpri 00342 00343 bool_t 00344 change_priority(TCB *p_tcb, uint_t newpri) 00345 { 00346 uint_t oldpri; 00347 00348 oldpri = p_tcb->priority; 00349 p_tcb->priority = newpri; 00350 00351 if (TSTAT_RUNNABLE(p_tcb->tstat)) { 00352 /* 00353 * タスクが実行できる状態の場合 00354 */ 00355 queue_delete(&(p_tcb->task_queue)); 00356 if (queue_empty(&(ready_queue[oldpri]))) { 00357 primap_clear(oldpri); 00358 } 00359 queue_insert_prev(&(ready_queue[newpri]), &(p_tcb->task_queue)); 00360 primap_set(newpri); 00361 00362 if (p_schedtsk == p_tcb) { 00363 if (newpri >= oldpri) { 00364 p_schedtsk = search_schedtsk(); 00365 return(p_schedtsk != p_tcb && dspflg); 00366 } 00367 } 00368 else { 00369 if (newpri < p_schedtsk->priority) { 00370 p_schedtsk = p_tcb; 00371 return(dspflg); 00372 } 00373 } 00374 } 00375 else { 00376 if (TSTAT_WAIT_WOBJCB(p_tcb->tstat)) { 00377 /* 00378 * タスクが,同期・通信オブジェクトの管理ブロックの共通部 00379 * 分(WOBJCB)の待ちキューにつながれている場合 00380 */ 00381 wobj_change_priority(((WINFO_WOBJ *)(p_tcb->p_winfo))->p_wobjcb, 00382 p_tcb); 00383 } 00384 } 00385 return(false); 00386 } 00387 00388 #endif /* TOPPERS_tskpri */ 00389 00390 /* 00391 * レディキューの回転 00392 * 00393 * 最高優先順位のタスクを更新するのは,最高優先順位のタスクがタスクキ 00394 * ューの末尾に移動した場合である. 00395 */ 00396 #ifdef TOPPERS_tskrot 00397 00398 bool_t 00399 rotate_ready_queue(uint_t pri) 00400 { 00401 QUEUE *p_queue = &(ready_queue[pri]); 00402 QUEUE *p_entry; 00403 00404 if (!queue_empty(p_queue) && p_queue->p_next->p_next != p_queue) { 00405 p_entry = queue_delete_next(p_queue); 00406 queue_insert_prev(p_queue, p_entry); 00407 if (p_schedtsk == (TCB *) p_entry) { 00408 p_schedtsk = (TCB *)(p_queue->p_next); 00409 return(dspflg); 00410 } 00411 } 00412 return(false); 00413 } 00414 00415 #endif /* TOPPERS_tskrot */ 00416 00417 /* 00418 * タスク例外処理ルーチンの呼出し 00419 * 00420 * ASPカーネルでは,タスク例外処理ルーチン内でCPUロック状態に移行し, 00421 * 元の状態に戻さずにリターンした場合,カーネルが元の状態に戻す. 00422 */ 00423 #ifdef TOPPERS_tsktex 00424 #ifndef OMIT_CALL_TEXRTN 00425 00426 void 00427 call_texrtn(void) 00428 { 00429 TEXPTN texptn; 00430 PRI saved_ipm; 00431 bool_t saved_disdsp, saved_dspflg; 00432 00433 saved_ipm = t_get_ipm(); 00434 saved_disdsp = disdsp; 00435 saved_dspflg = dspflg; 00436 do { 00437 texptn = p_runtsk->texptn; 00438 p_runtsk->enatex = false; 00439 p_runtsk->texptn = 0U; 00440 00441 t_unlock_cpu(); 00442 LOG_TEX_ENTER(texptn); 00443 (*((TEXRTN)(p_runtsk->p_tinib->texrtn)))(texptn, 00444 p_runtsk->p_tinib->exinf); 00445 LOG_TEX_LEAVE(texptn); 00446 if (!t_sense_lock()) { 00447 t_lock_cpu(); 00448 } 00449 t_set_ipm(saved_ipm); 00450 disdsp = saved_disdsp; 00451 dspflg = saved_dspflg; 00452 if (p_runtsk != p_schedtsk && dspflg) { 00453 dispatch(); 00454 } 00455 } while (p_runtsk->texptn != 0U); 00456 p_runtsk->enatex = true; 00457 } 00458 00459 #endif /* OMIT_CALL_TEXRTN */ 00460 00461 /* 00462 * タスク例外処理ルーチンの起動 00463 */ 00464 #ifndef OMIT_CALLTEX 00465 00466 void 00467 calltex(void) 00468 { 00469 if (p_runtsk->enatex && p_runtsk->texptn != 0U) { 00470 call_texrtn(); 00471 } 00472 } 00473 00474 #endif /* OMIT_CALLTEX */ 00475 #endif /* TOPPERS_tsktex */
Copyright © 2008 by Kijineko Inc.