4 ms·
a better fix to use the lmin macro. libkern.h. http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/src/sys/sys/libkern.h?rev=1.56.2.1.8.1;content-type=text%2Fplai
by peterbotond 16y ago
a better fix to use the lmin macro. libkern.h.
http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/src/sys/sys/libkern.h?rev=1.56.2.1.8.1;content-type=text%2Fplain http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/src/sys/sys...
- cube13 16y agoNot 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
- peterbotond 16y agothe 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.