If kern.hz is >= 596524 this timeout hangs due to an integer overflow (I believe).
Details
- Reviewers
- None
- Group Reviewers
Contributor Reviews (src)
Boots in a VM at 596524Hz, can't get to 1MHz though (mps hangs).
Diff Detail
- Repository
- rS FreeBSD src repository - subversion
- Lint
Lint Skipped - Unit
Tests Skipped
Event Timeline
Looks like ND6_RECALC_REACHTM_INTERVAL is used to set nd6_recalc_reachtm_interval, which in turn sets recalctm both of which are int's.
Also callout_reset takes an int not a ULL, so not sure this is valid
Ah OK, I only changed that one because of proximity in the source.
Also callout_reset takes an int not a ULL, so not sure this is valid
Agreed.
I'm not sure what the right solution, but I wanted to point out that callout_reset does _not_ take an int. All the callout_reset functions are macros around callout_reset_sbt_on which takes a sbintime_t, which is in fact 64-bit.
If that's the case the man timeout(9) may need some work:
int callout_reset(struct callout *c, int ticks, timeout_t *func, void *arg);
I think the problem is that hz is an int, eg..
#include <stdio.h> #include <stdint.h> #include <stdlib.h> void foo(int64_t t) { printf("%jd\n", (intmax_t)t); } int main(int argc, char **argv) { int hz = 596524; foo(60 * 60 * hz); exit(0); }
... fails (it prints -2147480896). Changing hz to int64_t or adding LL to any of the 60's prints the correct result (2147486400).
ie all the variables are implicitly converted to int because nothing bigger is used, the calculation overflows, and then callout_reset gets fed a negative value.
... that said I'm not sure why callout_reset doesn't behave more sanely.