xtimeはどこ?

xtime とは

1970年1月1日00:00:00(GMT)からの経過時間を、ナノ秒単位で保持している変数だそうです。

xtime とは別に、jiffies という変数もあって、こちらは Linux を起動後に一定時間ごとのタイマ割り込みによりインクリメントされます。

xtime はどこにいる?

わけあって、xtime がどこで定義されているのか調べてみたのですが、Linux 3.16.3 のソースコードには、xtime らしき変数が見当たらず。。

Linux 2.6.32 だと、"kernel/time/timekeeping.c" に宣言されているところがあります。

struct timespec xtime __attribute__ ((aligned (16)));

xtime は消え去ってしまったのでしょうか。。。。色々考えたあげく、gettimeofday(2)がxtimeの値を利用しているということなので、2.6の方でgettimeofdayがどのように実装されているか確認して見ました。

sys_gettimeofdayからdo_gettimeofdayを呼び出していました。その中で、以下のように、

void do_gettimeofday(struct timeval *tv)
{
    struct timespec now;

    getnstimeofday(&now);
    tv->tv_sec = now.tv_sec;
    tv->tv_usec = now.tv_nsec/1000;
}

"getnstimeofday"という関数を読んでいます。ここで、"getnstimeofday"は以下のような感じです。

void getnstimeofday(struct timespec *ts)
{
        unsigned long seq;
        s64 nsecs;

        WARN_ON(timekeeping_suspended);

        do {
                seq = read_seqbegin(&xtime_lock);

                *ts = xtime;
                nsecs = timekeeping_get_ns();

                /* If arch requires, add in gettimeoffset() */
                nsecs += arch_gettimeoffset();

        } while (read_seqretry(&xtime_lock, seq));

        timespec_add_ns(ts, nsecs);
}

ここで、渡された引数に、xtime を代入しています。

3.16ではどうなっているのしょう。

3.16でも、"sys_gettimeofday"から"do_gettimeofday"を呼び出しています。そして、"do_gettimeofday"から"getnstimeofday"を呼び出しています。ここまでは、2.6の時と同じ感じです。

void do_gettimeofday(struct timeval *tv)
{
    struct timespec now;

    getnstimeofday(&now);
    tv->tv_sec = now.tv_sec;
    tv->tv_usec = now.tv_nsec/1000;
}

ここで、"getnstimeofday"は以下のようになっています。

void getnstimeofday(struct timespec *ts)
{
    WARN_ON(__getnstimeofday(ts));
}

"__getnstimeofday"は以下のようになっていて、

int __getnstimeofday(struct timespec *ts)
{
    struct timekeeper *tk = &timekeeper;
    unsigned long seq;
    s64 nsecs = 0;

    do {
        seq = read_seqcount_begin(&timekeeper_seq);

        ts->tv_sec = tk->xtime_sec;
        nsecs = timekeeping_get_ns(tk);

    } while (read_seqcount_retry(&timekeeper_seq, seq));

    ts->tv_nsec = 0;
    timespec_add_ns(ts, nsecs);

    /*
     * Do not bail out early, in case there were callers still using
     * the value, even in the face of the WARN_ON.
     */
    if (unlikely(timekeeping_suspended))
        return -EAGAIN;
    return 0;
}

ここで、渡された引数に、"tk->xtime_sec"を代入しました。ということはこの"tk"にxtimeの代わりとなる値が入っているのでしょう。ということで、探してみると、"linux/timekeeper_internal.h"に以下のような定義がされています。

struct timekeeper {
    ... 略 ...
    /* Current CLOCK_REALTIME time in seconds */
    u64                     xtime_sec;
    /* Clock shifted nano seconds */
    u64                     xtime_nsec;
    ... 略 ...
}

とうことで、ここにxtimeがいました。