Skip to contentSkip to conversation

Wrong use of MAX_JIFFY_OFFSET?

DISCUSSION Liu Yu 2 participants 3 messages Mar 28, 2012 – Apr 9, 2012

lore
Share & tools
lore

Liu Yu

author
#0 lore raw

Hi guys,

I saw a couple of places in current kernel have this kind of code:

Quoted 9 lines

static inline unsigned int elapsed_jiffies_msecs(unsigned long start)

{
        unsigned long end = jiffies;

        if (end >= start)
               return jiffies_to_msecs(end - start);

        return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1);
}

As you know, jiffies has a type of unsigned long, so if we know which is the end and
which is the start, then (end - start) can simply figure out how much jiffies flies,
without worry about the overflow.

Look at the code above, assume that there is just an overflow happening on
jiffies: end=0 and start=~0UL.
Since end < start, then the return value of the function is jiffies_to_msecs(MAX_JIFFY_OFFSET+2).
But shouldn't the correct value be jiffies_to_msecs(1)?

could someone tell me that am I missing anything?

Thanks,
Yu

#1 lore raw
Quoted 20 lines · On Wed, 28 Mar 2012 15:12:24 +0800 "Liu Yu" <[email protected]> wrote:

Hi guys,

I saw a couple of places in current kernel have this kind of code:

Quoted 9 lines

static inline unsigned int elapsed_jiffies_msecs(unsigned long start)

{
        unsigned long end = jiffies;

        if (end >= start)
               return jiffies_to_msecs(end - start);

        return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1);
}

As you know, jiffies has a type of unsigned long, so if we know which is the end and
which is the start, then (end - start) can simply figure out how much jiffies flies,
without worry about the overflow.

Quoted 8 lines

Look at the code above, assume that there is just an overflow happening on
jiffies: end=0 and start=~0UL.
Since end < start, then the return value of the function is jiffies_to_msecs(MAX_JIFFY_OFFSET+2).
But shouldn't the correct value be jiffies_to_msecs(1)?

could someone tell me that am I missing anything?

Seems right. The code should be

static inline unsigned long elapsed_jiffies_msecs(unsigned long start)

{
	return jiffies_to_msecs(jiffies - start);
}

Note the return type. jiffies_to_msecs() currently returns unsigned int. I think it should return unsigned long. Even then, it can still overflow with valid inputs on HZ=100 32-bit machines.

author
#2 lore raw
Quoted 7 lines

-----邮件原件-----
发件人: Andrew Morton [mailto:[email protected]] 发送时间: 2012年4月7日 3:05
收件人: Liu Yu
抄送: [email protected]
主题: Re: Wrong use of MAX_JIFFY_OFFSET?

Quoted 18 lines
Quoted 15 lines · On Wed, 28 Mar 2012 15:12:24 +0800 "Liu Yu" <[email protected]> wrote:

Hi guys,

I saw a couple of places in current kernel have this kind of code:

Quoted 9 lines

static inline unsigned int elapsed_jiffies_msecs(unsigned long start)

{
        unsigned long end = jiffies;

        if (end >= start)
               return jiffies_to_msecs(end - start);

        return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1);
}

As you know, jiffies has a type of unsigned long, so if we know which is

the

Quoted 6 lines
Quoted 6 lines

end and
which is the start, then (end - start) can simply figure out how much jiffies flies,
without worry about the overflow.

Look at the code above, assume that there is just an overflow happening

on

Quoted 10 lines
Quoted 7 lines

jiffies: end=0 and start=~0UL.
Since end < start, then the return value of the function is jiffies_to_msecs(MAX_JIFFY_OFFSET+2).
But shouldn't the correct value be jiffies_to_msecs(1)?

could someone tell me that am I missing anything?

Seems right. The code should be

Quoted 8 lines

static inline unsigned long elapsed_jiffies_msecs(unsigned long start)

{
	return jiffies_to_msecs(jiffies - start);
}

Note the return type. jiffies_to_msecs() currently returns unsigned int. I think it should return unsigned long. Even then, it can still overflow with valid inputs on HZ=100 32-bit machines.

Thanks a lot for your reply :)

I saw similar code in
drivers/net/wireless/ipw2x00/libipw_wx.c
net/wireless/scan.c
include/linux/jbd2.h

hope someone can fix this. :)

Thanks,
Yu