今はまっているバグ

Linuxカーネルタイマを使う簡単なサンプルなんだけど、なぜか上手く動かない. 何が上手く動いていないのかというと、コールバック時に、何故か登録した情報が飛んでしまっている. (timer->functionと、timer->dataが何故がふっとぶ). 実はこれはゲスト上で動作させているコードで、ホストOS(VM)上でtimer_list 構造体に向かってR/Wしてるから、これが上手くいっていないのかな. 原因の切り分けのために、まずこれを実機上で動作させるのが良い気がする.

static struct timer_list test_timer[3];

static void timer_fn(unsigned long data)
{
    printk("timer_fn callded. data %ld\n",data);
}

static int test_mod_timer(unsigned long expires)
{
    static int cnt = 0;
    int ret;
    struct timer_list *t; 

    dputs("ENTER.");
    t = (struct timer_list*)(test_timer + cnt);

    init_timer(t);

    t->function = timer_fn;
    t->data = cnt;
    printk("timer addr %p t->function %p t->data %ld\n",t,t->function,t->data);

    ret = mod_timer(t,expires);
    printk("timer addr %p t->function %p t->data %ld\n",t,t->function,t->data);

    cnt++;
    dputs("EXIT.");

    return ret;
}

static int test_tmo_mod_timer(void)
{
    int ret;
    unsigned long jiffies,expires;

    dputs("ENTER.");
    expires = jiffies + 5*HZ ;
    ret = test_mod_timer(expires);

    if ( ret < 0 ){
        BUG();
    }

    expires = jiffies + 3*HZ ;
    ret = test_mod_timer(expires);

    if ( ret < 0 ){
        BUG();
    }

    expires = jiffies + 10*HZ ;
    ret = test_mod_timer(expires);

    if ( ret < 0 ){
        BUG();
    }

    ret = del_timer( test_timer + 2 );
    if ( ret < 0 ){
        BUG();
    }

    ret = 0;
    dputs("EXIT.");
    return ret;
}