Index Home About Blog
Date: 	Wed, 7 Nov 2001 17:22:35 -0800 (PST)
From: Linus Torvalds <torvalds@transmeta.com>
Subject: Re: [PATCH] net/ipv4/*, net/core/neighbour.c jiffies cleanup
Newsgroups: fa.linux.kernel

On Wed, 7 Nov 2001, Andreas Dilger wrote:
>
> No, only a limited number of them cast to a signed value, which means
> that a large number of them get the comparison wrong in the case of
> jiffies wrap (where the difference is a large unsigned value, and not
> a small negative number).

No.

Unsigned arithmetic is fine. The _correct_ way to test whether something
is in within

	[ start , start+HZ ]

is to do

	if (jiffies - start <= HZ)

try it. The C language guarantees that unsigned arithmetic works in a
"modulo power of two" fashion, which means that it _is_ ok to do
arithmetic on unsigned longs, and jiffy wrapping does not matter. No need
to cast to "signed" or anything else.

In short: It is wrong to do

	if (jiffies <= start+HZ)

and it is _right_ to do

	if (jiffies - start <= HZ)

(as long as "start" is "unsigned long" like jiffies).

		Linus



Date: 	Thu, 8 Nov 2001 09:10:41 -0800 (PST)
From: Linus Torvalds <torvalds@transmeta.com>
Subject: Re: [PATCH] net/ipv4/*, net/core/neighbour.c jiffies cleanup
Newsgroups: fa.linux.kernel

On Thu, 8 Nov 2001, Krishna Kumar wrote:
> > >
> > > In short: It is wrong to do
> > >
> > >          if (jiffies <= start+HZ)
> > >
> > > and it is _right_ to do
> > >
> > >          if (jiffies - start <= HZ)
>
> I am sorry, but I still don't see the difference. I wrote a small
> program with different cases, but the values still come same
> irrespective of the input arguments to the checks. Could you tell
> under what conditions the checks wuold fail ? The 2's complement works
> the same for addition and subtraction. I have included the test
> program below.

Ok.

Let's give an example. HZ is 100, and we started just before jiffies
wrapped, and we want to check that we're within one second.

So "start" equals 0xfffffff0, and "jiffies" equals 0xfffffff5.

The first if-statement will say

	if (0xfffffff5 <= 0xfffffff0+100)

which is the same as

	if (0xfffffff5 <= 0x54)

which is

	if (0)

in short, the first statement will say that jiffies is _not_ within 100
ticks of "start", which is obviously wrong. Jiffies _is_ within 100 ticks,
it is in fact just 5 ticks after "start".

The second statement will say

	if (0xfffffff5 - 0xfffffff0 <= 100)

which is

	if (5 <= 100)

which is

	if (1)

which is _correct_. We _are_ within 100 ticks.

See?

Ok, that was wrap-around one way: the "+HZ" wrapped. Let's see the other
case, which is that "jiffies" has wrapped: start is still 0xfffffff0, but
jiffies has wrapped around and is 0x00000001.

The first if-statement will say

	if (0x00000001 <= 0xfffffff0+100)

which is

	if (0x00000001 <= 0x54)

which is

	if (1)

which is correct. The second one will say

	if (0x00000001 - 0xfffffff0 <= 100)

which is

	if (11 <= 100)

which is

	if (1)

which is correct.

In short, the _correct_ one ALWAYS gets the right answer. Even when the
subtraction overflows.

While the first (and incorrect one) gets the wrong answer when the
addition overflows.

Do you see the difference now?

		Linus



Index Home About Blog