File tree Expand file tree Collapse file tree 1 file changed +15
-3
lines changed Expand file tree Collapse file tree 1 file changed +15
-3
lines changed Original file line number Diff line number Diff line change 26
26
27
27
#define MAX_PATH_LEN 1024
28
28
29
+ /* Calculate "x * n / d" without unnecessary overflow or loss of precision.
30
+ *
31
+ * Reference:
32
+ * https://elixir.bootlin.com/linux/v6.10.7/source/include/linux/math.h#L121
33
+ */
34
+ static inline uint64_t mult_frac (uint64_t x , uint64_t n , uint64_t d )
35
+ {
36
+ const uint64_t q = x / d ;
37
+ const uint64_t r = x % d ;
38
+
39
+ return q * n + r * n / d ;
40
+ }
41
+
29
42
static void get_time_info (int32_t * tv_sec , int32_t * tv_nsec )
30
43
{
31
44
#if defined(HAVE_POSIX_TIMER )
@@ -40,14 +53,13 @@ static void get_time_info(int32_t *tv_sec, int32_t *tv_nsec)
40
53
*/
41
54
if (info .denom == 0 )
42
55
(void ) mach_timebase_info (& info );
43
- /* Hope that the multiplication doesn't overflow. */
44
- uint64_t nsecs = mach_absolute_time () * info .numer / info .denom ;
56
+ uint64_t nsecs = mult_frac (mach_absolute_time (), info .numer , info .denom );
45
57
* tv_sec = nsecs / 1e9 ;
46
58
* tv_nsec = nsecs - (* tv_sec * 1e9 );
47
59
#else /* low resolution timer */
48
60
clock_t t = clock ();
49
61
* tv_sec = t / CLOCKS_PER_SEC ;
50
- * tv_nsec = (t % CLOCKS_PER_SEC ) * ( 1e9 / CLOCKS_PER_SEC );
62
+ * tv_nsec = mult_frac (t % CLOCKS_PER_SEC , 1e9 , CLOCKS_PER_SEC );
51
63
#endif
52
64
}
53
65
You can’t perform that action at this time.
0 commit comments