Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

a better fix to use the lmin macro. libkern.h.

http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/src/sys/sys...



Not really. The line is this: long adv = min(recwin, (long)TCP_MAXWIN << tp->rcv_scale) - (tp->rcv_adv - tp->rcv_nxt);

So it's really: long = uint(long, (long)uint32) - (uint32-uint32)

Here's the problem on x64: you're converting a 64-bit long to a uint, then doing a subtraction with another uint, then placing that result into a 64-bit long. Since the compiler is just doing an assignment rather than a sign extension, which is why there is a large positive number rather than -1.

Changing it to use the lmin macro would make it: long = long(long, (long)uint32) - (uint32-uint32)

This still has the underlying issue(using 32-bit values in 64-bit buckets), which should work out fine, but may have issues down the road.

It makes more sense to change all the long types to int32/uint32 types rather than just cast longs everywhere. If recwin and adv were changed to int32, it would be: int32 = uint32(int32, uint32) - (uint32 - uint32)

While this potentially has issues if the uints are between 0x80000000 and 0xfffffff, it's a safer solution than using longs.

EDIT: added some explanation


the lmin[1] macro will convert the uints to a long int and then do the arithmetic.

[1]static __inline long lmin(long a, long b) { return (a < b ? a : b); }

[2]static __inline u_int min(u_int a, u_int b) { return (a < b ? a : b); }

Edit: 6.3.1.8 Usualarithmetic conversions in the c-99 standard.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: