(toppers-users 2718) Re: UbuntuでJSPシミュレーション環境のインストールについての質問

酔漢 suikan7 @ yahoo.co.jp
2008年 1月 16日 (水) 23:13:39 JST


酔漢です

小南さんからの助けで無事動いたようで、何よりです。

動いた以上、以下は蛇足ですが調べたことだけ書き残しておきます。興味のある 
方だけ、どうぞお読みください。

銭冰 さんは書きました:
>
>
> つまり、『setjmp/longjmpの仕掛けが思いのほか複雑で、
> この二つのレジスタの設定だけで本当に良いのか』とのことですね。
>
そうです。この観点からsetjmp/longjmpが扱うjmpbuf型についてもう少し掘り下 
げてみました。

glibcのソースを見ても、このあたりはアーキテクチャ依存/独立部が入り組んで 
いて奇怪な印象を得るばかりでした。ですので、 setjmp/longjmpを使う小さな 
プログラムを組み、gdbで追いかけてバッファ内部の数値の変化を調べてみました。

その結果分かったのは、OpenSUSEが使っているgcc/glibcでは、単純にSP/PCを 
setjmpで退避するような構造になっていないということです。おそらく、 
TOPPERS/JSP linux依存部が実装された2003年頃にはすべてのレジスタをスタッ 
クにプッシュし、SPとPCのみをjmpbufに記録するような仕組みだったと思われます。

調べた範疇では、jmpbuf型変数内部にはSPそのものらしき値は保存されていませ 
んでした。かわりにFPやその他のレジスタが保存されていました。どうやらフ 
レームごと保存しているようです。

一筋縄ではいかないようなので、ためしに以下のようにactivate_context()を書 
き換えて実験してみました。

Inline void
activate_context(TCB *tcb)
{
    static jmp_buf callerContext;
    unsigned int stacktop;

    if ( ! _setjmp( callerContext ) )
    {   // immediately after setting caller context

        stacktop =(int)(tcb->tinib->stk + tcb->tinib->stksz - STACK_MERGIN);
            // enforce ESP as target stack top
        asm volatile ( "movl %0,%%esp" : :"q"(stacktop) );
            // Let's pray following works after changing stackpinter
            // The first dispatch after task start will jump to here
        if ( _setjmp( tcb->tskctxb.env ) )     // set target task context
        {                                       // arrived from dispatch()
            activate_r();                        // then, start task. 
Never return
        }
        else                                    // just after context 
setting
            _longjmp( callerContext, 1 );   // return to caller context
    }

}


元のlinux依存部の実装ではlongjmpのターゲットとして「arctivate_rを呼ぶ」 
設計だったのに対し、この変更ではactvate_r を呼ぶ手前でsetjmpを実行し、 
dispatch時にそこに戻ってくるようにしました。当然、ESPをtask stackに書き 
換えています。が、それでは実行環境も狂うため、あらかじめESPまで含めた環 
境をsetjmpで保存し、longjmpで復帰するというトリックを使っています。

STACK_MERGINを8以上にすることで、

task1 is running (015).   |
task1 is running (016).   |
#rot_rdq(three priorities)
task2 is running (001).     +
task2 is running (002).     +

という出力を得るにいたりました。が、rと打ってタスクがローテートする場合 
と、しない場合があります。する場合は常にしますが、いったん終了して ./jsp 
を再実行するとしないことが多いです。しない場合はまた終了して ./jsp を再 
実行です。

また、出力は1秒ではなく、もっと短い周期で出てきます。

もうすこし追い込むべきなのですが、残念ながら諸事情によりこれ以上この件に 
時間を避けません。興味のある方にバトンを渡します。

以下、私の環境です。

VMWare 6.0.2 build-59824
OpenSUSE 10.1
gcc 4.1.0
glibc 2.4-31.1

酔漢

-- 
酔漢
Blackfin 空挺団           http://adsp2191.hp.infoseek.co.jp/
TOPPERS/JSP for Blackfin  http://sourceforge.jp/projects/toppersjsp4bf/
Blog                      http://blackfin.g.hatena.ne.jp/suikan/

--------------------------------------
Easy + Joy + Powerful = Yahoo! Bookmarks x Toolbar
http://pr.mail.yahoo.co.jp/toolbar/