linux jiffies的比较

jiffies的定义:

// include/linux/jiffies.h
extern u64 __jiffy_data jiffies_64;
extern unsigned long volatile __jiffy_data jiffies;

Gcc defines __ARMEB__ for big-endian ARM and __ARMEL__ for little-endian ARM. 

以小端为例,arch/arm/kernel/vmlinux.lds 中将jiffies定义为jiffies_64的低4位。


以arm平台为例,jiffies变量是unsigned long类型的,那么最大为0xffffffff=4294967295L, 若HZ为100,

则4294967295L/100/60/60/24=497,大约在497天后jiffies会溢出。kernel里为了比较两个时间戳的先后提供了几个宏,

这几个宏在溢出时仍然能得到正确的结果:

// include/linux/jiffies.h
#define time_after(a,b)		\
	(typecheck(unsigned long, a) && \
	 typecheck(unsigned long, b) && \
	 ((long)(b) - (long)(a) < 0))
#define time_before(a,b)	time_after(b,a)

#define time_after_eq(a,b)	\
	(typecheck(unsigned long, a) && \
	 typecheck(unsigned long, b) && \
	 ((long)(a) - (long)(b) >= 0))
#define time_before_eq(a,b)	time_after_eq(b,a)

分析 time_after(a,b):

1. a = 2, b = 1

    b - a = 1 - 2 = 1 + (0xffff,fffe) = 0xffff,ffff = -1 < 0, 所以 timer_after(a,b) 返回真(1)

2. a = 1, b = 2

    b - a = 2 - 1 = 2 + (0xffff,ffff) = 0x0000,0001 > 0 , 所以 timer_after(a,b) 返回假(0)

3. a = 1, b = 0x8000,0000

    b - a = 0x8000,0000 - 1 = 0x7fff,ffff > 0, => timer_after(a,b) 返回假(0)

4. a = 1, b = 0x8000,0001 

    b - a = 0x8000,0001 - 1 = 0x8000,0000 < 0, => timer_after(a,b) 返回真(1)

5. a = 1, b = 0xffff,ffff

    b - a = 0xffff,ffff - 1 = 0xffff,ffff + 0xffff,ffff = 0xffff,fffe = -1 < 0, => timer_after(a,b) 返回真(1)

由上3,4,5可见timer_after(a,b)仍然有一定局限定,相比较的两个时间戳在逻辑上相差时间不大于MAX_ULONG/2(0x7fff,ffff). 如果相差大于此值则比较结果就是错的。

Basically it assumes that the two values you are comparing will never be
more than MAX_ULONG/2 apart. Which for jiffies means 270 some odd days
on 32-bit platforms.

好在我们通常使用jiffies和相关宏的使用场景都相对单一,时间跨度不可能这么大。所以一般直接使用没什么问题。

posted @ 2012-11-05 18:13  sammei  阅读(787)  评论(0编辑  收藏  举报