(toppers-users 773) Re: 割込みハンドラ出口処理について
SHUKUGUCHI Masahiro
ms89019 @ mms.co.jp
2003年 3月 11日 (火) 17:50:04 JST
たちさん ご無沙汰しております。
フォローありがとうございます。ご指摘の通りだと思います。
# 添削なんて。。。。
> TOPPERS(の公開されているCPU依存部)は、idleタスクのかわりに
> exit_and_dispatchの中で待ちに入ってます。
> M68Kの場合、割り込みモードで待ちに入っているので、割り込みハ
> ンドラの出入り口処理からret_intは呼び出されません。
カレントタスクが無い状態の処理は以下ですね。
cpu_suppoer.S 73行目あたり
exit_and_dispatch:
or.w #0x1000, %sr /* マスタモード */
dispatcher:
/*
* ここではマスタモード・割込み禁止状態でなければならない.
*/
move.l schedtsk, %a0
move.l %a0, runtsk /* schedtsk を runtsk に */
jbeq dispatcher_1 /* runtsk があるか? */
move.l TCB_msp(%a0), %sp /* タスクスタックを復帰 */
move.l TCB_pc(%a0), %a1 /* 実行再開番地を復帰 */
jmp (%a1)
dispatcher_1:
stop #0x2000 /* 割込み待ち(割込みモード) */
/*
* ここで割込みモードに切り換えるのは,ここで発生する割込み処理
* にどのスタックを使うかという問題の解決と,割込みハンドラ内で
* のタスクディスパッチの防止という2つの意味がある.
* この stop 命令は,IPM を 0 にするが,本来は task_intmask に
* 設定すべきである.M68040 では,stop 命令のパラメータに定数し
* かとれないため,やむをえず 0 にしている(stop 命令を 8つ並べ
* て,task_intmask の値で飛び分ける手はあるが,そこまでやる意
* 義はないと考えた).
*/
or.w #0x1700, %sr /* マスタモード・割込み禁止 */
tst.l reqflg /* reqflg が FALSE なら */
jbeq dispatcher_1 /* dispatcher_1 へ */
clr.l reqflg /* reqflg を FALSE に */
jbra dispatcher
CPUが割込み状態(=%srが0x2000)でSTOP状態になるので、ここで割込みが
入ると、割込みからの戻り先が割込み状態になりますね。
で、
> 「戻り先
> が割り込みモードならすぐにリターン」という流れになります。
cpu_config.h:227行目あたり
#define INTHDR_ENTRY(inthdr) \
extern void inthdr##_entry(void); \
asm(".text \n" \
#inthdr "_entry: \n" \
" movem.l %d0-%d1/%a0-%a1, -(%sp) \n" /* スクラッチレジスタを保存 */ \
" jsr " #inthdr " \n" /* 割込みハンドラを呼び出す */ \
" movem.l (%sp)+, %d0-%d1/%a0-%a1 \n" /* スクラッチレジスタを復帰 */ \
" btst.b #4, (%sp) \n" /* 戻り先が割込みモードなら */ \
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
この命令が効いてくるのですね。
" jbeq 1f \n" /* すぐにリターン */ \
" or.w #0x0700, %sr \n" /* 割込み禁止 */ \
" tst.l _kernel_reqflg \n" /* reqflg が TRUE であれば */ \
" jbne _kernel_ret_int \n" /* ret_int へ */ \
"1: rte \n")
> その後、exit_and_dispatchの中からdispatchへ飛びます。
> また、exit_and_dispatchはruntsk==NULLを考慮しています。
はい。そうなると思います。
exit_and_dispatch:
or.w #0x1000, %sr /* マスタモード */
dispatcher:
/*
* ここではマスタモード・割込み禁止状態でなければならない.
*/
move.l schedtsk, %a0
move.l %a0, runtsk /* schedtsk を runtsk に */
jbeq dispatcher_1 /* runtsk があるか? */
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ここで、runtsk==NULL を考慮していますね。
# MC68Kのmove命令は、0の移動で ZEROフラグがセットされるので、次の
# 条件分岐が有効になりますね。
## runtsk=NULLならば、dispatcher_1に分岐します。
move.l TCB_msp(%a0), %sp /* タスクスタックを復帰 */
move.l TCB_pc(%a0), %a1 /* 実行再開番地を復帰 */
jmp (%a1)
dispatcher_1:
stop #0x2000 /* 割込み待ち(割込みモード) */
宿口雅弘