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_manage.c 748 2008-03-07 17:18:06Z hiro $ 00041 */ 00042 00043 /* 00044 * タスク管理機能 00045 */ 00046 00047 #include "kernel_impl.h" 00048 #include "check.h" 00049 #include "task.h" 00050 #include "wait.h" 00051 00052 /* 00053 * トレースログマクロのデフォルト定義 00054 */ 00055 #ifndef LOG_ACT_TSK_ENTER 00056 #define LOG_ACT_TSK_ENTER(tskid) 00057 #endif /* LOG_ACT_TSK_ENTER */ 00058 00059 #ifndef LOG_ACT_TSK_LEAVE 00060 #define LOG_ACT_TSK_LEAVE(ercd) 00061 #endif /* LOG_ACT_TSK_LEAVE */ 00062 00063 #ifndef LOG_IACT_TSK_ENTER 00064 #define LOG_IACT_TSK_ENTER(tskid) 00065 #endif /* LOG_IACT_TSK_ENTER */ 00066 00067 #ifndef LOG_IACT_TSK_LEAVE 00068 #define LOG_IACT_TSK_LEAVE(ercd) 00069 #endif /* LOG_IACT_TSK_LEAVE */ 00070 00071 #ifndef LOG_CAN_ACT_ENTER 00072 #define LOG_CAN_ACT_ENTER(tskid) 00073 #endif /* LOG_CAN_ACT_ENTER */ 00074 00075 #ifndef LOG_CAN_ACT_LEAVE 00076 #define LOG_CAN_ACT_LEAVE(ercd) 00077 #endif /* LOG_CAN_ACT_LEAVE */ 00078 00079 #ifndef LOG_EXT_TSK_ENTER 00080 #define LOG_EXT_TSK_ENTER() 00081 #endif /* LOG_EXT_TSK_ENTER */ 00082 00083 #ifndef LOG_EXT_TSK_LEAVE 00084 #define LOG_EXT_TSK_LEAVE(ercd) 00085 #endif /* LOG_EXT_TSK_LEAVE */ 00086 00087 #ifndef LOG_TER_TSK_ENTER 00088 #define LOG_TER_TSK_ENTER(tskid) 00089 #endif /* LOG_TER_TSK_ENTER */ 00090 00091 #ifndef LOG_TER_TSK_LEAVE 00092 #define LOG_TER_TSK_LEAVE(ercd) 00093 #endif /* LOG_TER_TSK_LEAVE */ 00094 00095 #ifndef LOG_CHG_PRI_ENTER 00096 #define LOG_CHG_PRI_ENTER(tskid, tskpri) 00097 #endif /* LOG_CHG_PRI_ENTER */ 00098 00099 #ifndef LOG_CHG_PRI_LEAVE 00100 #define LOG_CHG_PRI_LEAVE(ercd) 00101 #endif /* LOG_CHG_PRI_LEAVE */ 00102 00103 #ifndef LOG_GET_PRI_ENTER 00104 #define LOG_GET_PRI_ENTER(tskid, p_tskpri) 00105 #endif /* LOG_GET_PRI_ENTER */ 00106 00107 #ifndef LOG_GET_PRI_LEAVE 00108 #define LOG_GET_PRI_LEAVE(ercd, tskpri) 00109 #endif /* LOG_GET_PRI_LEAVE */ 00110 00111 #ifndef LOG_GET_INF_ENTER 00112 #define LOG_GET_INF_ENTER(p_exinf) 00113 #endif /* LOG_GET_INF_ENTER */ 00114 00115 #ifndef LOG_GET_INF_LEAVE 00116 #define LOG_GET_INF_LEAVE(ercd, exinf) 00117 #endif /* LOG_GET_INF_LEAVE */ 00118 00119 /* 00120 * タスクの起動 00121 */ 00122 #ifdef TOPPERS_act_tsk 00123 00124 ER 00125 act_tsk(ID tskid) 00126 { 00127 TCB *p_tcb; 00128 ER ercd; 00129 00130 LOG_ACT_TSK_ENTER(tskid); 00131 CHECK_TSKCTX_UNL(); 00132 CHECK_TSKID_SELF(tskid); 00133 p_tcb = get_tcb_self(tskid); 00134 00135 t_lock_cpu(); 00136 if (TSTAT_DORMANT(p_tcb->tstat)) { 00137 if (make_active(p_tcb)) { 00138 dispatch(); 00139 } 00140 ercd = E_OK; 00141 } 00142 else if (!(p_tcb->actque)) { 00143 p_tcb->actque = true; 00144 ercd = E_OK; 00145 } 00146 else { 00147 ercd = E_QOVR; 00148 } 00149 t_unlock_cpu(); 00150 00151 error_exit: 00152 LOG_ACT_TSK_LEAVE(ercd); 00153 return(ercd); 00154 } 00155 00156 #endif /* TOPPERS_act_tsk */ 00157 00158 /* 00159 * タスクの起動(非タスクコンテキスト用) 00160 */ 00161 #ifdef TOPPERS_iact_tsk 00162 00163 ER 00164 iact_tsk(ID tskid) 00165 { 00166 TCB *p_tcb; 00167 ER ercd; 00168 00169 LOG_IACT_TSK_ENTER(tskid); 00170 CHECK_INTCTX_UNL(); 00171 CHECK_TSKID(tskid); 00172 p_tcb = get_tcb(tskid); 00173 00174 i_lock_cpu(); 00175 if (TSTAT_DORMANT(p_tcb->tstat)) { 00176 if (make_active(p_tcb)) { 00177 reqflg = true; 00178 } 00179 ercd = E_OK; 00180 } 00181 else if (!(p_tcb->actque)) { 00182 p_tcb->actque = true; 00183 ercd = E_OK; 00184 } 00185 else { 00186 ercd = E_QOVR; 00187 } 00188 i_unlock_cpu(); 00189 00190 error_exit: 00191 LOG_IACT_TSK_LEAVE(ercd); 00192 return(ercd); 00193 } 00194 00195 #endif /* TOPPERS_iact_tsk */ 00196 00197 /* 00198 * タスク起動要求のキャンセル 00199 */ 00200 #ifdef TOPPERS_can_act 00201 00202 ER_UINT 00203 can_act(ID tskid) 00204 { 00205 TCB *p_tcb; 00206 ER_UINT ercd; 00207 00208 LOG_CAN_ACT_ENTER(tskid); 00209 CHECK_TSKCTX_UNL(); 00210 CHECK_TSKID_SELF(tskid); 00211 p_tcb = get_tcb_self(tskid); 00212 00213 t_lock_cpu(); 00214 ercd = p_tcb->actque ? 1 : 0; 00215 p_tcb->actque = false; 00216 t_unlock_cpu(); 00217 00218 error_exit: 00219 LOG_CAN_ACT_LEAVE(ercd); 00220 return(ercd); 00221 } 00222 00223 #endif /* TOPPERS_can_act */ 00224 00225 /* 00226 * 自タスクの終了 00227 */ 00228 #ifdef TOPPERS_ext_tsk 00229 00230 ER 00231 ext_tsk(void) 00232 { 00233 ER ercd; 00234 00235 LOG_EXT_TSK_ENTER(); 00236 CHECK_TSKCTX(); 00237 00238 if (t_sense_lock()) { 00239 /* 00240 * CPUロック状態でext_tskが呼ばれた場合は,CPUロックを解除し 00241 * てからタスクを終了する.実装上は,サービスコール内でのCPU 00242 * ロックを省略すればよいだけ. 00243 */ 00244 } 00245 else { 00246 t_lock_cpu(); 00247 } 00248 if (disdsp) { 00249 /* 00250 * ディスパッチ禁止状態でext_tskが呼ばれた場合は,ディスパッ 00251 * チ許可状態にしてからタスクを終了する. 00252 */ 00253 disdsp = false; 00254 } 00255 if (t_get_ipm() != TIPM_ENAALL) { 00256 /* 00257 * 割込み優先度マスク(IPM)がTIPM_ENAALL以外の状態でext_tsk 00258 * が呼ばれた場合は,IPMをTIPM_ENAALLにしてからタスクを終了す 00259 * る. 00260 */ 00261 t_set_ipm(TIPM_ENAALL); 00262 } 00263 dspflg = true; 00264 00265 (void) make_non_runnable(p_runtsk); 00266 make_dormant(p_runtsk); 00267 if (p_runtsk->actque) { 00268 p_runtsk->actque = false; 00269 (void) make_active(p_runtsk); 00270 } 00271 exit_and_dispatch(); 00272 assert(0); 00273 00274 error_exit: 00275 LOG_EXT_TSK_LEAVE(ercd); 00276 return(ercd); 00277 } 00278 00279 #endif /* TOPPERS_ext_tsk */ 00280 00281 /* 00282 * タスクの強制終了 00283 */ 00284 #ifdef TOPPERS_ter_tsk 00285 00286 ER 00287 ter_tsk(ID tskid) 00288 { 00289 TCB *p_tcb; 00290 ER ercd; 00291 00292 LOG_TER_TSK_ENTER(tskid); 00293 CHECK_TSKCTX_UNL(); 00294 CHECK_TSKID(tskid); 00295 p_tcb = get_tcb(tskid); 00296 CHECK_NONSELF(p_tcb); 00297 00298 t_lock_cpu(); 00299 if (TSTAT_DORMANT(p_tcb->tstat)) { 00300 ercd = E_OBJ; 00301 } 00302 else { 00303 if (TSTAT_RUNNABLE(p_tcb->tstat)) { 00304 /* 00305 * p_tcbは自タスクでないため,(シングルプロセッサでは)実 00306 * 行状態でなく,make_non_runnable(p_tcb)でタスクディスパッ 00307 * チが必要になることはない. 00308 */ 00309 (void) make_non_runnable(p_tcb); 00310 } 00311 else if (TSTAT_WAITING(p_tcb->tstat)) { 00312 wait_dequeue_wobj(p_tcb); 00313 wait_dequeue_tmevtb(p_tcb); 00314 } 00315 make_dormant(p_tcb); 00316 if (p_tcb->actque) { 00317 p_tcb->actque = false; 00318 if (make_active(p_tcb)) { 00319 dispatch(); 00320 } 00321 } 00322 ercd = E_OK; 00323 } 00324 t_unlock_cpu(); 00325 00326 error_exit: 00327 LOG_TER_TSK_LEAVE(ercd); 00328 return(ercd); 00329 } 00330 00331 #endif /* TOPPERS_ter_tsk */ 00332 00333 /* 00334 * タスク優先度の変更 00335 */ 00336 #ifdef TOPPERS_chg_pri 00337 00338 ER 00339 chg_pri(ID tskid, PRI tskpri) 00340 { 00341 TCB *p_tcb; 00342 uint_t newpri; 00343 ER ercd; 00344 00345 LOG_CHG_PRI_ENTER(tskid, tskpri); 00346 CHECK_TSKCTX_UNL(); 00347 CHECK_TSKID_SELF(tskid); 00348 CHECK_TPRI_INI(tskpri); 00349 p_tcb = get_tcb_self(tskid); 00350 newpri = (tskpri == TPRI_INI) ? p_tcb->p_tinib->ipriority 00351 : INT_PRIORITY(tskpri); 00352 00353 t_lock_cpu(); 00354 if (TSTAT_DORMANT(p_tcb->tstat)) { 00355 ercd = E_OBJ; 00356 } 00357 else { 00358 if (change_priority(p_tcb, newpri)) { 00359 dispatch(); 00360 } 00361 ercd = E_OK; 00362 } 00363 t_unlock_cpu(); 00364 00365 error_exit: 00366 LOG_CHG_PRI_LEAVE(ercd); 00367 return(ercd); 00368 } 00369 00370 #endif /* TOPPERS_chg_pri */ 00371 00372 /* 00373 * タスク優先度の参照 00374 */ 00375 #ifdef TOPPERS_get_pri 00376 00377 ER 00378 get_pri(ID tskid, PRI *p_tskpri) 00379 { 00380 TCB *p_tcb; 00381 ER ercd; 00382 00383 LOG_GET_PRI_ENTER(tskid, p_tskpri); 00384 CHECK_TSKCTX_UNL(); 00385 CHECK_TSKID_SELF(tskid); 00386 p_tcb = get_tcb_self(tskid); 00387 00388 t_lock_cpu(); 00389 if (TSTAT_DORMANT(p_tcb->tstat)) { 00390 ercd = E_OBJ; 00391 } 00392 else { 00393 *p_tskpri = EXT_TSKPRI(p_tcb->priority); 00394 ercd = E_OK; 00395 } 00396 t_unlock_cpu(); 00397 00398 error_exit: 00399 LOG_GET_PRI_LEAVE(ercd, *p_tskpri); 00400 return(ercd); 00401 } 00402 00403 #endif /* TOPPERS_get_pri */ 00404 00405 /* 00406 * 自タスクの拡張情報の参照 00407 */ 00408 #ifdef TOPPERS_get_inf 00409 00410 ER 00411 get_inf(intptr_t *p_exinf) 00412 { 00413 ER ercd; 00414 00415 LOG_GET_INF_ENTER(p_exinf); 00416 CHECK_TSKCTX_UNL(); 00417 00418 t_lock_cpu(); 00419 *p_exinf = p_runtsk->p_tinib->exinf; 00420 ercd = E_OK; 00421 t_unlock_cpu(); 00422 00423 error_exit: 00424 LOG_GET_INF_LEAVE(ercd, *p_exinf); 00425 return(ercd); 00426 } 00427 00428 #endif /* TOPPERS_get_inf */
Copyright © 2008 by Kijineko Inc.