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.
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.
/* 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]) { \
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());
#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
#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);
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 */
/* 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) ({ \
/* 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++; \
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++; \
#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>
#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
#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
void PacketPoolInitEmpty(void)
{
-#ifndef TLS
- TmqhPacketPoolInit();
-#endif
-
PktPool *my_pool = GetThreadPacketPool();
#ifdef DEBUG_VALIDATION
{
extern intmax_t max_pending_packets;
-#ifndef TLS
- TmqhPacketPoolInit();
-#endif
-
PktPool *my_pool = GetThreadPacketPool();
#ifdef DEBUG_VALIDATION
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";
#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;
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";
/**
* 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);
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 *);
}
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); \
}
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; \
*/
#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)
{
#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.
* 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.