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);
再検索