diff --git a/aclocal.m4 b/aclocal.m4 index 0044adf9..746d5df5 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,6 +1,25 @@ dnl ** Additional Autoconf tests for BIRD configure script dnl ** (c) 1999 Martin Mares +AC_DEFUN([BIRD_CHECK_THREAD_LOCAL], +[ + AC_CACHE_CHECK( + [whether _Thread_local is known], + [bird_cv_thread_local], + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM( + [ + _Thread_local static int x = 42; + ], + [] + ) + ], + [bird_cv_thread_local=yes], + [bird_cv_thread_local=no] + ) + ) +]) + AC_DEFUN([BIRD_CHECK_PTHREADS], [ bird_tmp_cflags="$CFLAGS" @@ -134,7 +153,7 @@ AC_DEFUN([BIRD_CHECK_ANDROID_LOG], AC_DEFUN([BIRD_CHECK_LTO], [ bird_tmp_cflags="$CFLAGS" - bird_tmp_ldflags="$CFLAGS" + bird_tmp_ldflags="$LDFLAGS" CFLAGS="-flto" LDFLAGS="-flto" diff --git a/configure.ac b/configure.ac index 58fdc7fe..5ec75359 100644 --- a/configure.ac +++ b/configure.ac @@ -115,6 +115,11 @@ if test -z "$GCC" ; then AC_MSG_ERROR([This program requires the GNU C Compiler.]) fi +BIRD_CHECK_THREAD_LOCAL +if test "$bird_cv_thread_local" = yes ; then + AC_DEFINE([HAVE_THREAD_LOCAL], [1], [Define to 1 if _Thread_local is available]) +fi + if test "$enable_pthreads" != no ; then BIRD_CHECK_PTHREADS diff --git a/filter/filter.c b/filter/filter.c index dbc2376b..65572583 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -51,7 +51,7 @@ #include "filter/data.h" /* Internal filter state, to be allocated on stack when executing filters */ -_Thread_local struct filter_state { +struct filter_state { /* The route we are processing. This may be NULL to indicate no route available. */ struct rte **rte; @@ -63,7 +63,14 @@ _Thread_local struct filter_state { struct linpool *pool; struct buffer buf; int flags; -} filter_state; +}; + +#if HAVE_THREAD_LOCAL +_Thread_local static struct filter_state filter_state; +#define FS_INIT(...) filter_state = (struct filter_state) { __VA_ARGS__ } +#else +#define FS_INIT(...) struct filter_state filter_state = { __VA_ARGS__ } +#endif void (*bt_assert_hook)(int result, const struct f_line_item *assert); @@ -275,11 +282,11 @@ f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, i DBG( "Running filter `%s'...", filter->name ); /* Initialize the filter state */ - filter_state = (struct filter_state) { - .rte = rte, - .pool = tmp_pool, - .flags = flags, - }; + FS_INIT( + .rte = rte, + .pool = tmp_pool, + .flags = flags, + ); LOG_BUFFER_INIT(filter_state.buf); @@ -338,10 +345,10 @@ f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, i enum filter_return f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool) { - filter_state = (struct filter_state) { - .rte = rte, - .pool = tmp_pool, - }; + FS_INIT( + .rte = rte, + .pool = tmp_pool, + ); LOG_BUFFER_INIT(filter_state.buf); @@ -360,9 +367,9 @@ f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool enum filter_return f_eval(const struct f_line *expr, struct linpool *tmp_pool, struct f_val *pres) { - filter_state = (struct filter_state) { - .pool = tmp_pool, - }; + FS_INIT( + .pool = tmp_pool, + ); LOG_BUFFER_INIT(filter_state.buf); @@ -379,9 +386,9 @@ uint f_eval_int(const struct f_line *expr) { /* Called independently in parse-time to eval expressions */ - filter_state = (struct filter_state) { - .pool = cfg_mem, - }; + FS_INIT( + .pool = cfg_mem, + ); struct f_val val; diff --git a/lib/birdlib.h b/lib/birdlib.h index 6fcc202f..9743da32 100644 --- a/lib/birdlib.h +++ b/lib/birdlib.h @@ -73,6 +73,12 @@ static inline int u64_cmp(u64 i1, u64 i2) #define UNUSED __attribute__((unused)) #define PACKED __attribute__((packed)) +#ifdef HAVE_THREAD_LOCAL +#define THREAD_LOCAL _Thread_local +#else +#define THREAD_LOCAL +#endif + /* Microsecond time */ typedef s64 btime;