From 6fd172f599e8d798e68974a786dd930d876f182e Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 18 Oct 2017 16:55:18 -0400 Subject: [PATCH] Use initial-exec tls model The initial-exec tls model removes requirement on performing memory allocation the first time a tls variable is touched by any given thread. This is needed to ensure usage of the TLS from a signal handler works fine. Given that the link-editor figures out the right model to use at runtime, we can change the tls model without changing the soname major version. This also brings interesting speedups over the GD model. This does not affects TLS accesses performed by executables, but does affect TLS accesses performed by libraries. * Executable (no change) ./test_urcu 1 0 10 SUMMARY /media/truecrypt1/compudj/doc/userspace-rcu/tests/benchmark/.libs/test_urcu testdur 10 nr_readers 1 rdur 0 wdur 0 nr_writers 0 wdelay 0 nr_reads 4420328692 nr_writes 0 nr_ops 4420328692 (with initial-exec) ./test_urcu 1 0 10 SUMMARY /media/truecrypt1/compudj/doc/userspace-rcu/tests/benchmark/.libs/test_urcu testdur 10 nr_readers 1 rdur 0 wdur 0 nr_writers 0 wdelay 0 nr_reads 4424925864 nr_writes 0 nr_ops 4424925864 * Library (with global-dynamic) ./test_urcu_dynamic_link 1 0 10 SUMMARY /media/truecrypt1/compudj/doc/userspace-rcu/tests/benchmark/.libs/test_urcu_dynamic_link testdur 10 nr_readers 1 rdur 0 wdur 0 nr_writers 0 wdelay 0 nr_reads 573209491 nr_writes 0 nr_ops 573209491 (with initial-exec) ./test_urcu_dynamic_link 1 0 10 SUMMARY /media/truecrypt1/compudj/doc/userspace-rcu/tests/benchmark/.libs/test_urcu_dynamic_link testdur 10 nr_readers 1 rdur 0 wdur 0 nr_writers 0 wdelay 0 nr_reads 1088836185 nr_writes 0 nr_ops 1088836185 Link: https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter8-20.html Link: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#Common-Variable-Attributes Signed-off-by: Mathieu Desnoyers --- include/urcu/tls-compat.h | 6 ++++++ src/urcu-bp.c | 2 +- src/urcu-call-rcu-impl.h | 2 +- src/urcu-defer-impl.h | 2 +- src/urcu-qsbr.c | 2 +- src/urcu.c | 2 +- 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/urcu/tls-compat.h b/include/urcu/tls-compat.h index 8ac1ea0..3a31eeb 100644 --- a/include/urcu/tls-compat.h +++ b/include/urcu/tls-compat.h @@ -72,6 +72,9 @@ extern "C" { # define URCU_TLS(name) (name) +# define DEFINE_URCU_TLS_IE(type, name) \ + CONFIG_RCU_TLS __attribute__((tls_model("initial-exec"))) type name + #else /* #ifndef CONFIG_RCU_TLS */ /* @@ -127,6 +130,9 @@ struct urcu_tls { # define DEFINE_URCU_TLS(type, name) \ DEFINE_URCU_TLS_1(type, name) +# define DEFINE_URCU_TLS_IE(type, name) \ + DEFINE_URCU_TLS_1(type, name) + # define URCU_TLS_1(name) (*__tls_access_ ## name()) # define URCU_TLS(name) URCU_TLS_1(name) diff --git a/src/urcu-bp.c b/src/urcu-bp.c index ebe96c5..675b5d6 100644 --- a/src/urcu-bp.c +++ b/src/urcu-bp.c @@ -142,7 +142,7 @@ struct rcu_gp rcu_gp = { .ctr = RCU_GP_COUNT }; * Pointer to registry elements. Written to only by each individual reader. Read * by both the reader and the writers. */ -DEFINE_URCU_TLS(struct rcu_reader *, rcu_reader); +DEFINE_URCU_TLS_IE(struct rcu_reader *, rcu_reader); static CDS_LIST_HEAD(registry); diff --git a/src/urcu-call-rcu-impl.h b/src/urcu-call-rcu-impl.h index 4562ba4..56fe943 100644 --- a/src/urcu-call-rcu-impl.h +++ b/src/urcu-call-rcu-impl.h @@ -88,7 +88,7 @@ static CDS_LIST_HEAD(call_rcu_data_list); /* Link a thread using call_rcu() to its call_rcu thread. */ -static DEFINE_URCU_TLS(struct call_rcu_data *, thread_call_rcu_data); +static DEFINE_URCU_TLS_IE(struct call_rcu_data *, thread_call_rcu_data); /* * Guard call_rcu thread creation and atfork handlers. diff --git a/src/urcu-defer-impl.h b/src/urcu-defer-impl.h index f965533..b2e1b3c 100644 --- a/src/urcu-defer-impl.h +++ b/src/urcu-defer-impl.h @@ -126,7 +126,7 @@ static int32_t defer_thread_stop; * Written to only by each individual deferer. Read by both the deferer and * the reclamation tread. */ -static DEFINE_URCU_TLS(struct defer_queue, defer_queue); +static DEFINE_URCU_TLS_IE(struct defer_queue, defer_queue); static CDS_LIST_HEAD(registry_defer); static pthread_t tid_defer; diff --git a/src/urcu-qsbr.c b/src/urcu-qsbr.c index e029ace..f343f0d 100644 --- a/src/urcu-qsbr.c +++ b/src/urcu-qsbr.c @@ -77,7 +77,7 @@ struct rcu_gp rcu_gp = { .ctr = RCU_GP_ONLINE }; * Written to only by each individual reader. Read by both the reader and the * writers. */ -DEFINE_URCU_TLS(struct rcu_reader, rcu_reader); +DEFINE_URCU_TLS_IE(struct rcu_reader, rcu_reader); static CDS_LIST_HEAD(registry); diff --git a/src/urcu.c b/src/urcu.c index a81b129..af8a2ce 100644 --- a/src/urcu.c +++ b/src/urcu.c @@ -118,7 +118,7 @@ struct rcu_gp rcu_gp = { .ctr = RCU_GP_COUNT }; * Written to only by each individual reader. Read by both the reader and the * writers. */ -DEFINE_URCU_TLS(struct rcu_reader, rcu_reader); +DEFINE_URCU_TLS_IE(struct rcu_reader, rcu_reader); static CDS_LIST_HEAD(registry); -- 2.34.1