From 1677f1ac06beecb2fb23f0f49d89260f86131a5c Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Fri, 27 Jan 2017 10:21:56 +0100 Subject: Use a thread local random generator. This allows accessing the per-thread random generator in a lock-free way, at the cost of additional memory per thread. The default random generator imposes around 640 bytes per thread on 64-bit architectures. Resolves: #141 Signed-off-by: Nikos Mavrogiannopoulos --- configure.ac | 3 +++ lib/random.c | 41 +++++++++-------------------------------- lib/random.h | 1 - 3 files changed, 12 insertions(+), 33 deletions(-) diff --git a/configure.ac b/configure.ac index 5779d2d584..23cbd5b7f7 100644 --- a/configure.ac +++ b/configure.ac @@ -192,6 +192,9 @@ dnl Need netinet/tcp.h for TCP_FASTOPEN AC_CHECK_HEADERS([netinet/tcp.h]) AC_CHECK_HEADERS([stdatomic.h]) +dnl We use its presence to detect C11 threads +AC_CHECK_HEADERS([threads.h]) + AC_ARG_ENABLE(padlock, AS_HELP_STRING([--disable-padlock], [unconditionally disable padlock acceleration]), use_padlock=$enableval) diff --git a/lib/random.c b/lib/random.c index ba7333dc85..73fb143d7f 100644 --- a/lib/random.c +++ b/lib/random.c @@ -29,57 +29,34 @@ #include "locks.h" #include -void *gnutls_rnd_ctx; -GNUTLS_STATIC_MUTEX(gnutls_rnd_init_mutex); +#ifdef HAVE_THREADS_H +# include +#elif defined(__GNUC__) +# define _Thread_local __thread +#else +# error Unsupported platform +#endif -#ifdef HAVE_STDATOMIC_H -static atomic_uint rnd_initialized = 0; +static _Thread_local void *gnutls_rnd_ctx; -inline static int _gnutls_rnd_init(void) -{ - if (unlikely(!rnd_initialized)) { - if (_gnutls_rnd_ops.init == NULL) { - rnd_initialized = 1; - return 0; - } - - GNUTLS_STATIC_MUTEX_LOCK(gnutls_rnd_init_mutex); - if (!rnd_initialized) { - if (_gnutls_rnd_ops.init(&gnutls_rnd_ctx) < 0) { - gnutls_assert(); - GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_init_mutex); - return GNUTLS_E_RANDOM_FAILED; - } - rnd_initialized = 1; - } - GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_init_mutex); - } - return 0; -} -#else -static unsigned rnd_initialized = 0; +static _Thread_local unsigned rnd_initialized = 0; inline static int _gnutls_rnd_init(void) { - GNUTLS_STATIC_MUTEX_LOCK(gnutls_rnd_init_mutex); if (unlikely(!rnd_initialized)) { if (_gnutls_rnd_ops.init == NULL) { rnd_initialized = 1; - GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_init_mutex); return 0; } if (_gnutls_rnd_ops.init(&gnutls_rnd_ctx) < 0) { gnutls_assert(); - GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_init_mutex); return GNUTLS_E_RANDOM_FAILED; } rnd_initialized = 1; } - GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_init_mutex); return 0; } -#endif int _gnutls_rnd_preinit(void) { diff --git a/lib/random.h b/lib/random.h index e89efb9c34..a76c8c07f6 100644 --- a/lib/random.h +++ b/lib/random.h @@ -28,7 +28,6 @@ #include "nettle/rnd-common.h" extern int crypto_rnd_prio; -extern void *gnutls_rnd_ctx; extern gnutls_crypto_rnd_st _gnutls_rnd_ops; void _gnutls_rnd_deinit(void); -- cgit v1.2.1