]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
threads: make thread local storage manadatory
authorVictor Julien <victor@inliniac.net>
Sun, 12 Apr 2020 12:03:24 +0000 (14:03 +0200)
committerVictor Julien <victor@inliniac.net>
Thu, 16 Apr 2020 12:37:34 +0000 (14:37 +0200)
Support either the __thread GNUism or the C11 _Thread_local.

Use 'thread_local' to point to the one that is used. Convert existing
__thread user to 'thread_local'.

Remove non-thread-local code from the packet pool code.

13 files changed:
configure.ac
src/output-filestore.c
src/suricata.c
src/threads-profile.h
src/threads.h
src/tm-threads.c
src/tmqh-packetpool.c
src/util-profiling-keywords.c
src/util-profiling-locks.c
src/util-profiling-prefilter.c
src/util-profiling.c
src/util-profiling.h
src/util-time.c

index 71de01602a938d011f4a98c4e0f404321c53977e..c65500e6221e099b55499aa378ba4de580e240c8 100644 (file)
     esac
     AC_MSG_RESULT(ok)
 
-  # disable TLS on user request
-    AC_ARG_ENABLE(threading-tls,
-           AS_HELP_STRING([--disable-threading-tls], [Disable TLS (thread local storage)]), [enable_tls="$enableval"],[enable_tls=yes])
-    AS_IF([test "x$enable_tls" = "xyes"], [
-        # check if our target supports thread local storage
-        AC_MSG_CHECKING(for thread local storage __thread support)
-        AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdlib.h>]],
-            [[ static __thread int i; i = 1; i++; ]])],
-            [AC_DEFINE([TLS], [1], [Thread local storage])
-             AC_MSG_RESULT([yes])],
-            [AC_MSG_RESULT([no])])
-    ])
+    # check if our target supports thread local storage
+    AC_MSG_CHECKING(for thread local storage c11 thread_local support)
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdlib.h>]],
+                [[ static _Thread_local int i; i = 1; i++; ]])],
+            [AC_DEFINE([TLS_C11], [1], [Thread local storage])
+            AC_MSG_RESULT([yes])],
+            [AC_MSG_RESULT([no])
+             have_c11_tls=no])
+    # check if our target supports thread local storage
+    AC_MSG_CHECKING(for thread local storage gnu __thread support)
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdlib.h>]],
+                [[ static __thread int i; i = 1; i++; ]])],
+            [AC_DEFINE([TLS_GNU], [1], [Thread local storage])
+            AC_MSG_RESULT([yes])],
+            [AC_MSG_RESULT([no])
+             have_gnu_tls=no])
+    if [ test "x$have_c11_tls" = "xno" ] && [ test "x$have_gnu_tls" = "xno" ]; then
+        AC_MSG_ERROR("no thread local support available.")
+        exit 1
+    fi
 
     #Enable support for gcc compile time security options. There is no great way to do detection of valid cflags that I have found
     #AX_CFLAGS_GCC_OPTION don't seem to do a better job than the code below and are a pain because of extra m4 files etc.
index e9c7f7131cfb0b4635278dd2833c06e723ade820..704053182798b560a8ad0232ada973e0cc9e8188 100644 (file)
@@ -63,7 +63,7 @@ typedef struct OutputFilestoreLogThread_ {
 
 /* For WARN_ONCE, a record of warnings that have already been
  * issued. */
-static __thread bool once_errs[SC_ERR_MAX];
+static thread_local bool once_errs[SC_ERR_MAX];
 
 #define WARN_ONCE(err_code, ...)  do {                   \
         if (!once_errs[err_code]) {                      \
index a74d4065056dcb661a50a4ef07d7d291bb93223e..f2376be305440ff99b06d2a5703c59fd7c9db345 100644 (file)
@@ -650,7 +650,7 @@ static void PrintBuildInfo(void)
     const char *bits = "<unknown>-bits";
     const char *endian = "<unknown>-endian";
     char features[2048] = "";
-    const char *tls = "pthread key";
+    const char *tls;
 
     printf("This is %s version %s\n", PROG_NAME, GetProgramVersion());
 
@@ -715,9 +715,14 @@ static void PrintBuildInfo(void)
 #ifdef PROFILE_LOCKING
     strlcat(features, "PROFILE_LOCKING ", sizeof(features));
 #endif
-#ifdef TLS
+#if defined(TLS_C11) || defined(TLS_GNU)
     strlcat(features, "TLS ", sizeof(features));
 #endif
+#if defined(TLS_C11)
+    strlcat(features, "TLS_C11 ", sizeof(features));
+#elif defined(TLS_GNU)
+    strlcat(features, "TLS_GNU ", sizeof(features));
+#endif
 #ifdef HAVE_MAGIC
     strlcat(features, "MAGIC ", sizeof(features));
 #endif
@@ -810,8 +815,12 @@ static void PrintBuildInfo(void)
 #ifdef CLS
     printf("L1 cache line size (CLS)=%d\n", CLS);
 #endif
-#ifdef TLS
+#if defined(TLS_C11)
+    tls = "_Thread_local";
+#elif defined(TLS_GNU)
     tls = "__thread";
+#else
+#error "Unsupported thread local"
 #endif
     printf("thread local storage method: %s\n", tls);
 
index 6e19673b10487934cdd0c898cda9487620deeeb9..1d66997f7d3a6fac7606bb9d85512250d9abee37 100644 (file)
@@ -37,13 +37,13 @@ typedef struct ProfilingLock_ {
     uint64_t ticks;
 } ProfilingLock;
 
-extern __thread ProfilingLock locks[PROFILING_MAX_LOCKS];
-extern __thread int locks_idx;
-extern __thread int record_locks;
+extern thread_local ProfilingLock locks[PROFILING_MAX_LOCKS];
+extern thread_local int locks_idx;
+extern thread_local int record_locks;
 
-extern __thread uint64_t mutex_lock_contention;
-extern __thread uint64_t mutex_lock_wait_ticks;
-extern __thread uint64_t mutex_lock_cnt;
+extern thread_local uint64_t mutex_lock_contention;
+extern thread_local uint64_t mutex_lock_wait_ticks;
+extern thread_local uint64_t mutex_lock_cnt;
 
 /* mutex */
 
@@ -92,9 +92,9 @@ extern __thread uint64_t mutex_lock_cnt;
 
 /* spinlocks */
 
-extern __thread uint64_t spin_lock_contention;
-extern __thread uint64_t spin_lock_wait_ticks;
-extern __thread uint64_t spin_lock_cnt;
+extern thread_local uint64_t spin_lock_contention;
+extern thread_local uint64_t spin_lock_wait_ticks;
+extern thread_local uint64_t spin_lock_cnt;
 
 //printf("%16s(%s:%d): (thread:%"PRIuMAX") locked mutex %p ret %" PRId32 "\n", __FUNCTION__, __FILE__, __LINE__, (uintmax_t)pthread_self(), mut, retl);
 #define SCSpinLock_profile(spin) ({ \
@@ -131,9 +131,9 @@ extern __thread uint64_t spin_lock_cnt;
 
 /* rwlocks */
 
-extern __thread uint64_t rww_lock_contention;
-extern __thread uint64_t rww_lock_wait_ticks;
-extern __thread uint64_t rww_lock_cnt;
+extern thread_local uint64_t rww_lock_contention;
+extern thread_local uint64_t rww_lock_wait_ticks;
+extern thread_local uint64_t rww_lock_cnt;
 
 #define SCRWLockWRLock_profile(mut) ({ \
     rww_lock_cnt++; \
@@ -160,9 +160,9 @@ extern __thread uint64_t rww_lock_cnt;
     retl; \
 })
 
-extern __thread uint64_t rwr_lock_contention;
-extern __thread uint64_t rwr_lock_wait_ticks;
-extern __thread uint64_t rwr_lock_cnt;
+extern thread_local uint64_t rwr_lock_contention;
+extern thread_local uint64_t rwr_lock_wait_ticks;
+extern thread_local uint64_t rwr_lock_cnt;
 
 #define SCRWLockRDLock_profile(mut) ({ \
     rwr_lock_cnt++; \
index 4eb1a73606dacaec642feb75cab10cb64c67bed1..17513cc5b40ffb422f781665ead6e05223631ea2 100644 (file)
 #include <config.h>
 #endif
 
+#if defined(TLS_C11)
+#define thread_local _Thread_local
+#elif defined(TLS_GNU)
+#define thread_local __thread
+#else
+#error "No supported thread local type found"
+#endif
+
 /* need this for the _POSIX_SPIN_LOCKS define */
 #if HAVE_UNISTD_H
 #include <unistd.h>
index b049b7ed6544414cbf42b0eb894ee60fc9be4e05..dd68b2feaf70b7d8ef180eee7c69835a17e73983 100644 (file)
 #include "queue.h"
 
 #ifdef PROFILE_LOCKING
-__thread uint64_t mutex_lock_contention;
-__thread uint64_t mutex_lock_wait_ticks;
-__thread uint64_t mutex_lock_cnt;
+thread_local uint64_t mutex_lock_contention;
+thread_local uint64_t mutex_lock_wait_ticks;
+thread_local uint64_t mutex_lock_cnt;
 
-__thread uint64_t spin_lock_contention;
-__thread uint64_t spin_lock_wait_ticks;
-__thread uint64_t spin_lock_cnt;
+thread_local uint64_t spin_lock_contention;
+thread_local uint64_t spin_lock_wait_ticks;
+thread_local uint64_t spin_lock_cnt;
 
-__thread uint64_t rww_lock_contention;
-__thread uint64_t rww_lock_wait_ticks;
-__thread uint64_t rww_lock_cnt;
+thread_local uint64_t rww_lock_contention;
+thread_local uint64_t rww_lock_wait_ticks;
+thread_local uint64_t rww_lock_cnt;
 
-__thread uint64_t rwr_lock_contention;
-__thread uint64_t rwr_lock_wait_ticks;
-__thread uint64_t rwr_lock_cnt;
+thread_local uint64_t rwr_lock_contention;
+thread_local uint64_t rwr_lock_wait_ticks;
+thread_local uint64_t rwr_lock_cnt;
 #endif
 
 #ifdef OS_FREEBSD
index b8b963022347319c93b638813833bec19c545913..ead8d0106ac5d1af8d65315f8405d3de274a2824 100644 (file)
 #define MAX_PENDING_RETURN_PACKETS 32
 static uint32_t max_pending_return_packets = MAX_PENDING_RETURN_PACKETS;
 
-#ifdef TLS
-__thread PktPool thread_pkt_pool;
+thread_local PktPool thread_pkt_pool;
 
 static inline PktPool *GetThreadPacketPool(void)
 {
     return &thread_pkt_pool;
 }
-#else
-/* __thread not supported. */
-static pthread_key_t pkt_pool_thread_key;
-static SCMutex pkt_pool_thread_key_mutex = SCMUTEX_INITIALIZER;
-static int pkt_pool_thread_key_initialized = 0;
-
-static void PktPoolThreadDestroy(void * buf)
-{
-    SCFreeAligned(buf);
-}
-
-static void TmqhPacketPoolInit(void)
-{
-    SCMutexLock(&pkt_pool_thread_key_mutex);
-    if (pkt_pool_thread_key_initialized) {
-        /* Key has already been created. */
-        SCMutexUnlock(&pkt_pool_thread_key_mutex);
-        return;
-    }
-
-    /* Create the pthread Key that is used to look up thread specific
-     * data buffer. Needs to be created only once.
-     */
-    int r = pthread_key_create(&pkt_pool_thread_key, PktPoolThreadDestroy);
-    if (r != 0) {
-        SCLogError(SC_ERR_MEM_ALLOC, "pthread_key_create failed with %d", r);
-        exit(EXIT_FAILURE);
-    }
-
-    pkt_pool_thread_key_initialized = 1;
-    SCMutexUnlock(&pkt_pool_thread_key_mutex);
-}
-
-static PktPool *ThreadPacketPoolCreate(void)
-{
-    TmqhPacketPoolInit();
-
-    /* Create a new pool for this thread. */
-    PktPool* pool = (PktPool*)SCMallocAligned(sizeof(PktPool), CLS);
-    if (pool == NULL) {
-        SCLogError(SC_ERR_MEM_ALLOC, "malloc failed");
-        exit(EXIT_FAILURE);
-    }
-    memset(pool,0x0,sizeof(*pool));
-
-    int r = pthread_setspecific(pkt_pool_thread_key, pool);
-    if (r != 0) {
-        SCLogError(SC_ERR_MEM_ALLOC, "pthread_setspecific failed with %d", r);
-        exit(EXIT_FAILURE);
-    }
-
-    return pool;
-}
-
-static inline PktPool *GetThreadPacketPool(void)
-{
-    PktPool* pool = (PktPool*)pthread_getspecific(pkt_pool_thread_key);
-    if (pool == NULL)
-        pool = ThreadPacketPoolCreate();
-
-    return pool;
-}
-#endif
 
 /**
  * \brief TmqhPacketpoolRegister
@@ -350,10 +286,6 @@ void PacketPoolReturnPacket(Packet *p)
 
 void PacketPoolInitEmpty(void)
 {
-#ifndef TLS
-    TmqhPacketPoolInit();
-#endif
-
     PktPool *my_pool = GetThreadPacketPool();
 
 #ifdef DEBUG_VALIDATION
@@ -371,10 +303,6 @@ void PacketPoolInit(void)
 {
     extern intmax_t max_pending_packets;
 
-#ifndef TLS
-    TmqhPacketPoolInit();
-#endif
-
     PktPool *my_pool = GetThreadPacketPool();
 
 #ifdef DEBUG_VALIDATION
index a96555451ff3388dcb8f9951934bfa9aeb599445..feee266d57e19087646c64c248cf17cf32568642 100644 (file)
@@ -62,7 +62,7 @@ typedef struct SCProfileKeywordDetectCtx_ {
 
 static int profiling_keywords_output_to_file = 0;
 int profiling_keyword_enabled = 0;
-__thread int profiling_keyword_entered = 0;
+thread_local int profiling_keyword_entered = 0;
 static char profiling_file_name[PATH_MAX];
 static const char *profiling_file_mode = "a";
 
index efbe9720fb266b0eafc36b67895d56c91c98a602..0840750596047d2531c5176c848abd489d854005 100644 (file)
@@ -31,9 +31,9 @@
 #ifdef PROFILING
 #ifdef PROFILE_LOCKING
 
-__thread ProfilingLock locks[PROFILING_MAX_LOCKS];
-__thread int locks_idx = 0;
-__thread int record_locks = 0;
+thread_local ProfilingLock locks[PROFILING_MAX_LOCKS];
+thread_local int locks_idx = 0;
+thread_local int record_locks = 0;
 
 int profiling_locks_enabled = 0;
 int profiling_locks_output_to_file = 0;
index cb5e34e35339acfae507e1ffb3f844fd8122b82b..bf8b38d99b1159f907319fc0c5141efb4f4bb047 100644 (file)
@@ -56,7 +56,7 @@ typedef struct SCProfilePrefilterDetectCtx_ {
 
 static int profiling_prefilter_output_to_file = 0;
 int profiling_prefilter_enabled = 0;
-__thread int profiling_prefilter_entered = 0;
+thread_local int profiling_prefilter_entered = 0;
 static char profiling_file_name[PATH_MAX];
 static const char *profiling_file_mode = "a";
 
index 7a590a5573089229bf02fdb4fb6e0fb796e475f1..0fc1958ab8e212b04378e26ce1cc2b48d4e70be0 100644 (file)
@@ -114,7 +114,7 @@ static SC_ATOMIC_DECLARE(uint64_t, samples);
 /**
  * Used as a check so we don't double enter a profiling run.
  */
-__thread int profiling_rules_entered = 0;
+thread_local int profiling_rules_entered = 0;
 
 void SCProfilingDumpPacketStats(void);
 const char * PacketProfileDetectIdToString(PacketProfileDetectId id);
index 6ecdbdc145f7d81257ee17f5ccdca1f9949831f1..ee0a88b5a5c3a4cd4ad011d288b0ab4ddc5051ed 100644 (file)
@@ -33,7 +33,7 @@
 extern int profiling_rules_enabled;
 extern int profiling_packets_enabled;
 extern int profiling_sghs_enabled;
-extern __thread int profiling_rules_entered;
+extern thread_local int profiling_rules_entered;
 
 void SCProfilingPrintPacketProfile(Packet *);
 void SCProfilingAddPacket(Packet *);
@@ -60,7 +60,7 @@ int SCProfileRuleStart(Packet *p);
     }
 
 extern int profiling_keyword_enabled;
-extern __thread int profiling_keyword_entered;
+extern thread_local int profiling_keyword_entered;
 
 #define KEYWORD_PROFILING_SET_LIST(ctx, list) { \
     (ctx)->keyword_perf_list = (list); \
@@ -275,7 +275,7 @@ PktProfiling *SCProfilePacketStart(void);
     }
 
 extern int profiling_prefilter_enabled;
-extern __thread int profiling_prefilter_entered;
+extern thread_local int profiling_prefilter_entered;
 
 #define PREFILTER_PROFILING_START \
     uint64_t profile_prefilter_start_ = 0; \
index 2d63196e774a839e9e3774e68a16cffab2db4ea3..71b9ca12c32bb76247395acd112a8d0e5291cbc3 100644 (file)
@@ -242,7 +242,7 @@ struct tm *SCUtcTime(time_t timep, struct tm *result)
  */
 
 #ifndef TLS
-/* OpenBSD does not support __thread, so don't use time caching on BSD
+/* OpenBSD does not support thread_local, so don't use time caching on BSD
  */
 struct tm *SCLocalTime(time_t timep, struct tm *result)
 {
@@ -266,7 +266,7 @@ void CreateTimeString (const struct timeval *ts, char *str, size_t size)
 
 #else
 
-/* On systems supporting __thread, use Per-thread values for caching
+/* On systems supporting thread_local, use Per-thread values for caching
  * in CreateTimeString */
 
 /* The maximum possible length of the time string.
@@ -274,16 +274,16 @@ void CreateTimeString (const struct timeval *ts, char *str, size_t size)
  * Or "01/01/2013-15:42:21.123456", which is 26, so round up to 32. */
 #define MAX_LOCAL_TIME_STRING 32
 
-static __thread int mru_time_slot; /* Most recently used cached value */
-static __thread time_t last_local_time[2];
-static __thread short int cached_local_time_len[2];
-static __thread char cached_local_time[2][MAX_LOCAL_TIME_STRING];
+static thread_local int mru_time_slot; /* Most recently used cached value */
+static thread_local time_t last_local_time[2];
+static thread_local short int cached_local_time_len[2];
+static thread_local char cached_local_time[2][MAX_LOCAL_TIME_STRING];
 
 /* Per-thread values for caching SCLocalTime() These cached values are
  * independent from the CreateTimeString cached values. */
-static __thread int mru_tm_slot; /* Most recently used local tm */
-static __thread time_t cached_minute_start[2];
-static __thread struct tm cached_local_tm[2];
+static thread_local int mru_tm_slot; /* Most recently used local tm */
+static thread_local time_t cached_minute_start[2];
+static thread_local struct tm cached_local_tm[2];
 
 /** \brief Convert time_t into Year, month, day, hour and minutes.
  * \param timep Time in seconds since defined date.