diff options
| author | Hans Petter Selasky <hselasky@FreeBSD.org> | 2020-02-27 15:21:05 +0000 |
|---|---|---|
| committer | Hans Petter Selasky <hselasky@FreeBSD.org> | 2020-02-27 15:21:05 +0000 |
| commit | 77632fc70f4219bbc0cf2c9a8646df5906e0d13f (patch) | |
| tree | b59c60ebc57710d32ad7a0c2de8f342b76fb42ae | |
| parent | 40b1e0dc0e90abebccf916fa362849c770f5a74e (diff) | |
Notes
| -rw-r--r-- | sys/compat/linuxkpi/common/include/linux/jiffies.h | 55 | ||||
| -rw-r--r-- | sys/compat/linuxkpi/common/src/linux_compat.c | 50 |
2 files changed, 83 insertions, 22 deletions
diff --git a/sys/compat/linuxkpi/common/include/linux/jiffies.h b/sys/compat/linuxkpi/common/include/linux/jiffies.h index 6813ea7a3010..c8fc57725e54 100644 --- a/sys/compat/linuxkpi/common/include/linux/jiffies.h +++ b/sys/compat/linuxkpi/common/include/linux/jiffies.h @@ -54,6 +54,18 @@ #define HZ hz +extern uint64_t lkpi_nsec2hz_rem; +extern uint64_t lkpi_nsec2hz_div; +extern uint64_t lkpi_nsec2hz_max; + +extern uint64_t lkpi_usec2hz_rem; +extern uint64_t lkpi_usec2hz_div; +extern uint64_t lkpi_usec2hz_max; + +extern uint64_t lkpi_msec2hz_rem; +extern uint64_t lkpi_msec2hz_div; +extern uint64_t lkpi_msec2hz_max; + static inline int timespec_to_jiffies(const struct timespec *ts) { @@ -70,12 +82,11 @@ timespec_to_jiffies(const struct timespec *ts) static inline int msecs_to_jiffies(uint64_t msec) { - uint64_t msec_max, result; + uint64_t result; - msec_max = -1ULL / (uint64_t)hz; - if (msec > msec_max) - msec = msec_max; - result = howmany(msec * (uint64_t)hz, 1000ULL); + if (msec > lkpi_msec2hz_max) + msec = lkpi_msec2hz_max; + result = howmany(msec * lkpi_msec2hz_rem, lkpi_msec2hz_div); if (result > MAX_JIFFY_OFFSET) result = MAX_JIFFY_OFFSET; @@ -85,12 +96,11 @@ msecs_to_jiffies(uint64_t msec) static inline int usecs_to_jiffies(uint64_t usec) { - uint64_t usec_max, result; + uint64_t result; - usec_max = -1ULL / (uint64_t)hz; - if (usec > usec_max) - usec = usec_max; - result = howmany(usec * (uint64_t)hz, 1000000ULL); + if (usec > lkpi_usec2hz_max) + usec = lkpi_usec2hz_max; + result = howmany(usec * lkpi_usec2hz_rem, lkpi_usec2hz_div); if (result > MAX_JIFFY_OFFSET) result = MAX_JIFFY_OFFSET; @@ -100,23 +110,24 @@ usecs_to_jiffies(uint64_t usec) static inline uint64_t nsecs_to_jiffies64(uint64_t nsec) { - uint64_t nsec_max, result; - nsec_max = -1ULL / (uint64_t)hz; - if (nsec > nsec_max) - nsec = nsec_max; - result = howmany(nsec * (uint64_t)hz, 1000000000ULL); - if (result > MAX_JIFFY_OFFSET) - result = MAX_JIFFY_OFFSET; - - return (result); + if (nsec > lkpi_nsec2hz_max) + nsec = lkpi_nsec2hz_max; + return (howmany(nsec * lkpi_nsec2hz_rem, lkpi_nsec2hz_div)); } -static inline uint64_t -nsecs_to_jiffies(uint64_t n) +static inline unsigned long +nsecs_to_jiffies(uint64_t nsec) { - return (usecs_to_jiffies(howmany(n, 1000ULL))); + if (sizeof(unsigned long) >= sizeof(uint64_t)) { + if (nsec > lkpi_nsec2hz_max) + nsec = lkpi_nsec2hz_max; + } else { + if (nsec > (lkpi_nsec2hz_max >> 32)) + nsec = (lkpi_nsec2hz_max >> 32); + } + return (howmany(nsec * lkpi_nsec2hz_rem, lkpi_nsec2hz_div)); } static inline uint64_t diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c index ba5e28d04f9d..498b05cdc203 100644 --- a/sys/compat/linuxkpi/common/src/linux_compat.c +++ b/sys/compat/linuxkpi/common/src/linux_compat.c @@ -1934,9 +1934,38 @@ del_timer(struct timer_list *timer) return (1); } +/* greatest common divisor, Euclid equation */ +static uint64_t +lkpi_gcd_64(uint64_t a, uint64_t b) +{ + uint64_t an; + uint64_t bn; + + while (b != 0) { + an = b; + bn = a % b; + a = an; + b = bn; + } + return (a); +} + +uint64_t lkpi_nsec2hz_rem; +uint64_t lkpi_nsec2hz_div = 1000000000ULL; +uint64_t lkpi_nsec2hz_max; + +uint64_t lkpi_usec2hz_rem; +uint64_t lkpi_usec2hz_div = 1000000ULL; +uint64_t lkpi_usec2hz_max; + +uint64_t lkpi_msec2hz_rem; +uint64_t lkpi_msec2hz_div = 1000ULL; +uint64_t lkpi_msec2hz_max; + static void linux_timer_init(void *arg) { + uint64_t gcd; /* * Compute an internal HZ value which can divide 2**32 to @@ -1947,6 +1976,27 @@ linux_timer_init(void *arg) while (linux_timer_hz_mask < (unsigned long)hz) linux_timer_hz_mask *= 2; linux_timer_hz_mask--; + + /* compute some internal constants */ + + lkpi_nsec2hz_rem = hz; + lkpi_usec2hz_rem = hz; + lkpi_msec2hz_rem = hz; + + gcd = lkpi_gcd_64(lkpi_nsec2hz_rem, lkpi_nsec2hz_div); + lkpi_nsec2hz_rem /= gcd; + lkpi_nsec2hz_div /= gcd; + lkpi_nsec2hz_max = -1ULL / lkpi_nsec2hz_rem; + + gcd = lkpi_gcd_64(lkpi_usec2hz_rem, lkpi_usec2hz_div); + lkpi_usec2hz_rem /= gcd; + lkpi_usec2hz_div /= gcd; + lkpi_usec2hz_max = -1ULL / lkpi_usec2hz_rem; + + gcd = lkpi_gcd_64(lkpi_msec2hz_rem, lkpi_msec2hz_div); + lkpi_msec2hz_rem /= gcd; + lkpi_msec2hz_div /= gcd; + lkpi_msec2hz_max = -1ULL / lkpi_msec2hz_rem; } SYSINIT(linux_timer, SI_SUB_DRIVERS, SI_ORDER_FIRST, linux_timer_init, NULL); |
