Skip to content

Commit

Permalink
Fix Jitter time measurement on Apple platforms (#722)
Browse files Browse the repository at this point in the history
On Apple platforms, Jitter RNG implementation uses `mach_absolute_time`
function to get the current value of the clock. However, this function
deals in "tick" units, not in time units. On Intel based Apple
platforms 1 tick = 1 ns, which is good enough timer resolution for
Jitter. On M1 macbooks 1 tick ~ 41.67 ns. This seems to be a problem
for Jitter since it causes frequent failures to produce enough entropy
on M1 macbooks. Another potential cause for the issue might be that
`mach_absolute_time` clock doesn't increment while they system is
asleep. I am not sure what is the definition of "asleep" on M1 macs,
how it correlates to performance and efficiency cores and different
power saving states, etc. The upstream Jitter RNG repository has
recently added support for using the system counter on `aarch64`
which seems like way to go for all 64-bit Arm platforms.

So this change:
  - Adds the system counter calls on `aarch64` platforms,
  - Removes the `__MACH__` special case.
  • Loading branch information
dkostic authored Dec 14, 2022
1 parent 1b48edc commit 9624f32
Showing 1 changed file with 17 additions and 9 deletions.
26 changes: 17 additions & 9 deletions third_party/jitterentropy/jitterentropy-base-user.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,23 @@ static inline void jent_get_nstime(uint64_t *out)
*out = EAX_EDX_VAL(val, low, high);
}

#else /* (__x86_64__) || (__i386__) */
#elif defined(__aarch64__)

static inline void jent_get_nstime(uint64_t *out)
{
/* OSX does not have clock_gettime -- taken from
* http://developer.apple.com/library/mac/qa/qa1398/_index.html */
# ifdef __MACH__
*out = mach_absolute_time();
# elif _AIX
uint64_t ctr_val;
/*
* Use the system counter for aarch64 (64 bit ARM).
*/
__asm__ volatile("mrs %0, cntvct_el0" : "=r" (ctr_val));
*out = ctr_val;
}

#else /* (__x86_64__) || (__i386__) || (__aarch64__) */

static inline void jent_get_nstime(uint64_t *out)
{
#ifdef _AIX
/* clock_gettime() on AIX returns a timer value that increments in
* steps of 1000
*/
Expand All @@ -131,7 +139,7 @@ static inline void jent_get_nstime(uint64_t *out)
tmp = tmp << 32;
tmp = tmp | aixtime.tb_low;
*out = tmp;
# else /* __MACH__ */
# else /* __AIX */
/* we could use CLOCK_MONOTONIC(_RAW), but with CLOCK_REALTIME
* we get some nice extra entropy once in a while from the NTP actions
* that we want to use as well... though, we do not rely on that
Expand All @@ -144,10 +152,10 @@ static inline void jent_get_nstime(uint64_t *out)
tmp = tmp + (uint64_t)time.tv_nsec;
}
*out = tmp;
# endif /* __MACH__ */
# endif /* __AIX */
}

#endif /* __x86_64__ */
#endif /* (__x86_64__) || (__i386__) || (__aarch64__) */

static inline void *jent_zalloc(size_t len)
{
Expand Down

0 comments on commit 9624f32

Please sign in to comment.