jiffies
読み:ジフィーズ
外語:jiffies

 Linuxカーネルが起動してから、一定時間ごとにカウントアップされる変数。jiffyの複数形。
目次

定義
 linux/jiffies.hにおいて定義されている。

typedef unsigned long long u64; #define __jiffy_data __attribute__((section(".data"))) extern u64 __jiffy_data jiffies_64; extern unsigned long volatile __jiffy_data jiffies;

 jiffies_64の実体は、kernel/timer.cに存在する。

概要
 tick単位でカウントアップされる。
 従って、現時点でのjiffiesから、所定の数を足した分になるまで待てば、所定の時間後に処理を実行させることができる。
 Linuxは、jiffiesを基準にして処理のスケジュールを実行している。
 ただし、CPUがスリープ中(Linuxカーネルが動作していない時)はタイマー割り込み処理が発生しないため、jiffiesは増えない。スリープ時間も含めた時間を求める用途には使えない。

特徴

参照方法
 (BITS_PER_LONG < 64)の場合、jiffies_64を参照する。
 (BITS_PER_LONG >= 64)の場合、jiffies自体が64ビット(以上)なので、直接参照できる。
 なお、jiffies_64はアトミックではないため、直接参照してはならない。
 get_jiffies_64(void)関数を使用すると、環境に応じて参照先が自動的に切り替わり、u64型つまり64ビットのjiffyを得ることができる。

HZ
 1秒間に発生するタイマー割り込み回数は、マクロHZがasm/param.hで#defineされており、このためjiffies + HZは1秒後を意味する。
 HZはヘルツが語源と思われ、秒間のタイマー割り込みの回数(≒周波数)を表わす。
 asm/param.h

# define HZ CONFIG_HZ

 CONFIG_HZは、ビルドオプションで定義される(x.x.x-xはバージョン番号)。
 /usr/src/linux-headers-x.x.x-x-generic/.config
 CONFIG_HZ=100
 この環境では、1秒間に100回と定義されていることが分かる。つまりtick単位は1/100秒=10ミリ秒である。

64ビット化
 jiffiesがオーバーフローして誤作動することは仕様であり、対処方法は存在しない。
 そこで、kernel 2.6以降ではjiffiesが64ビット化され、jiffies_64が追加された。これ以降、jiffiesはjiffies_64の下位32ビットとなった。

実装

x86 PC
 x86 PCでは10msごとにタイマー割り込みを発生させている。
 つまり秒間100回の割り込みがあるので、HZ=100である。
 さらに、unsigned longは32ビットなので、約497日経過するとゼロに戻るため、64ビット化される以前のLinuxは497日以上の連続稼働で誤作動した。
 Red Hat 7.3とRed Hat 8.0の一部環境は、HZ=512で動作し、jiffiesは約97日でゼロに戻る。

ARM Android
 プロセッサーにより異なる可能性はあるが、MSMを利用した一般的なAndroid端末では、これもHZ=100が一般的である。
 Androidが用いているLinuxカーネルは全てLinux 2.6以降であるので、Androidでもjiffiesは64ビット化されている。しかしアプリ不具合など別の理由で497日以上の連続稼動など困難と見込まれるので、現実には32ビットでも充分であろう。

RHEL6
 なお、RHEL6のように、定期的なタイマ割り込みを行なわない「Ticklessカーネル」では仕様が異なる。

関数
 jiffiesと他の型を変換するため、次の関数が用意されている。
 unsigned int jiffies_to_msecs(const unsigned long j);
 unsigned int jiffies_to_usecs(const unsigned long j);
 unsigned long msecs_to_jiffies(const unsigned int m);
 unsigned long usecs_to_jiffies(const unsigned int u);
 unsigned long timespec_to_jiffies(const struct timespec *value);
 void jiffies_to_timespec(const unsigned long jiffies, struct timespec *value);
 unsigned long timeval_to_jiffies(const struct timeval *value);
 void jiffies_to_timeval(const unsigned long jiffies, struct timeval *value);
 clock_t jiffies_to_clock_t(unsigned long x);
 unsigned long clock_t_to_jiffies(unsigned long x);
 u64 jiffies_64_to_clock_t(u64 x);
 u64 nsec_to_clock_t(u64 x);
 u64 nsecs_to_jiffies64(u64 n);
 unsigned long nsecs_to_jiffies(u64 n);

再検索