]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
Use Spin locks on Tile
authorKen Steele <ken@tilera.com>
Fri, 27 Sep 2013 20:27:13 +0000 (16:27 -0400)
committerVictor Julien <victor@inliniac.net>
Tue, 1 Oct 2013 13:48:11 +0000 (15:48 +0200)
On Tile, replace pthread_mutex_locks with queued spin locks (ticket
locks) for dataplane processing code. This is safe when running on
dataplane cores with one thread per core. The condition variables are
no-ops when the thread is spinning anyway.

For control plane threads, unix-manager, stats-logs, thread startup,
use pthread_mutex_locks. For these locks replaced SCMutex with SCCtrlMutex
and SCCond with SCCtrlCond.

src/counters.c
src/flow-manager.c
src/flow-manager.h
src/threads.h
src/threadvars.h
src/tm-threads.c
src/tmqh-flow.c
src/tmqh-simple.c
src/unix-manager.c
src/unix-manager.h

index f574f742a9d6c9da702444721f87498c2fe14992..711e2710c855d111c2dfa8e53521a68b7044f9bd 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2010 Open Information Security Foundation
+/* Copyright (C) 2007-2013 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
@@ -474,9 +474,9 @@ static void *SCPerfMgmtThread(void *arg)
         cond_time.tv_sec = time(NULL) + sc_counter_tts;
         cond_time.tv_nsec = 0;
 
-        SCMutexLock(tv_local->m);
-        SCCondTimedwait(tv_local->cond, tv_local->m, &cond_time);
-        SCMutexUnlock(tv_local->m);
+        SCCtrlMutexLock(tv_local->ctrl_mutex);
+        SCCtrlCondTimedwait(tv_local->ctrl_cond, tv_local->ctrl_mutex, &cond_time);
+        SCCtrlMutexUnlock(tv_local->ctrl_mutex);
 
         SCPerfOutputCounters();
 
@@ -542,9 +542,9 @@ static void *SCPerfWakeupThread(void *arg)
         cond_time.tv_sec = time(NULL) + SC_PERF_WUT_TTS;
         cond_time.tv_nsec = 0;
 
-        SCMutexLock(tv_local->m);
-        SCCondTimedwait(tv_local->cond, tv_local->m, &cond_time);
-        SCMutexUnlock(tv_local->m);
+        SCCtrlMutexLock(tv_local->ctrl_mutex);
+        SCCtrlCondTimedwait(tv_local->ctrl_cond, tv_local->ctrl_mutex, &cond_time);
+        SCCtrlMutexUnlock(tv_local->ctrl_mutex);
 
         tv = tv_root[TVT_PPT];
         while (tv != NULL) {
index 1f2828f12c2451c1f37e39715678b1230be9ceb2..b3a49cd0ce0abc77450eedcbf7403d28a5923865 100644 (file)
@@ -94,7 +94,7 @@ void FlowKillFlowManagerThread(void)
     ThreadVars *tv = NULL;
     int cnt = 0;
 
-    SCCondSignal(&flow_manager_cond);
+    SCCtrlCondSignal(&flow_manager_ctrl_cond);
 
     SCMutexLock(&tv_root_lock);
 
@@ -538,9 +538,10 @@ void *FlowManagerThread(void *td)
 
         cond_time.tv_sec = time(NULL) + flow_update_delay_sec;
         cond_time.tv_nsec = flow_update_delay_nsec;
-        SCMutexLock(&flow_manager_mutex);
-        SCCondTimedwait(&flow_manager_cond, &flow_manager_mutex, &cond_time);
-        SCMutexUnlock(&flow_manager_mutex);
+        SCCtrlMutexLock(&flow_manager_ctrl_mutex);
+        SCCtrlCondTimedwait(&flow_manager_ctrl_cond, &flow_manager_ctrl_mutex,
+                            &cond_time);
+        SCCtrlMutexUnlock(&flow_manager_ctrl_mutex);
 
         SCLogDebug("woke up... %s", SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY ? "emergency":"");
 
@@ -566,8 +567,8 @@ void FlowManagerThreadSpawn()
 {
     ThreadVars *tv_flowmgr = NULL;
 
-    SCCondInit(&flow_manager_cond, NULL);
-    SCMutexInit(&flow_manager_mutex, NULL);
+    SCCtrlCondInit(&flow_manager_ctrl_cond, NULL);
+    SCCtrlMutexInit(&flow_manager_ctrl_mutex, NULL);
 
     tv_flowmgr = TmThreadCreateMgmtThread("FlowManagerThread",
                                           FlowManagerThread, 0);
index 6bb64b8771ca9458ee72a0adfad0be2b47b85596..090e74fbc38ab01c27d3b9e955300d83faa77df2 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2012 Open Information Security Foundation
+/* Copyright (C) 2007-2013 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
@@ -25,9 +25,9 @@
 #define __FLOW_MANAGER_H__
 
 /** flow manager scheduling condition */
-SCCondT flow_manager_cond;
-SCMutex flow_manager_mutex;
-#define FlowWakeupFlowManagerThread() SCCondSignal(&flow_manager_cond)
+SCCtrlCondT flow_manager_ctrl_cond;
+SCCtrlMutex flow_manager_ctrl_mutex;
+#define FlowWakeupFlowManagerThread() SCCtrlCondSignal(&flow_manager_ctrl_cond)
 
 void FlowManagerThreadSpawn(void);
 void FlowKillFlowManagerThread(void);
index b07457dd87157555891745744dee8d990ec0e394..68855e17b35e17053c5444fe35178f46d519b2e7 100644 (file)
 #ifndef __THREADS_H__
 #define __THREADS_H__
 
+#ifdef __tile__
+#include <tmc/spin.h>
+#include <arch/cycle.h>
+#endif
+
 #if HAVE_CONFIG_H
 #include <config.h>
 #endif
@@ -101,14 +106,34 @@ enum {
 //#define DBG_THREADS
 
 /** Suricata Mutex */
+#ifdef __tile__
+#define SCMutex tmc_spin_queued_mutex_t
+#define SCMutexAttr
+#define SCMutexDestroy(x) ({ (void)(x); 0; })
+#define SCMUTEX_INITIALIZER TMC_SPIN_QUEUED_MUTEX_INIT
+#else
 #define SCMutex pthread_mutex_t
 #define SCMutexAttr pthread_mutexattr_t
 #define SCMutexDestroy pthread_mutex_destroy
 #define SCMUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#endif
+
+/* NOTE: On Tilera datapath threads use the tmc library for mutexes
+ * while the control threads use pthread mutexes.  So the pthread
+ * mutex types are split out so they their use can be differentiated.
+ */
+#define SCCtrlMutex pthread_mutex_t
+#define SCCtrlMutexAttr pthread_mutexattr_t
+#define SCCtrlMutexDestroy pthread_mutex_destroy
 
 /** Suricata RWLocks */
+#ifdef __tile__
+#define SCRWLock tmc_spin_rwlock_t
+#define SCRWLockDestroy(x) ({ (void)(x); 0; })
+#else
 #define SCRWLock pthread_rwlock_t
 #define SCRWLockDestroy pthread_rwlock_destroy
+#endif
 
 /** Get the Current Thread Id */
 #ifdef OS_FREEBSD
@@ -291,20 +316,60 @@ extern __thread uint64_t mutex_lock_cnt;
 #define SCMutexLock(mut) SCMutexLock_profile(mut)
 #define SCMutexTrylock(mut) pthread_mutex_trylock(mut)
 
-#else
+#else /* Not Debug and Not Profile */
+#ifdef __tile__
+#define SCMutexInit(mut, mutattr) ({ \
+    int ret = 0; \
+    tmc_spin_queued_mutex_init(mut); \
+    ret; \
+})
+#define SCMutexLock(mut) ({ \
+    int ret = 0; \
+    tmc_spin_queued_mutex_lock(mut); \
+    ret; \
+})
+#define SCMutexTrylock(mut) ({ \
+    int ret = (tmc_spin_queued_mutex_trylock(mut) == 0) ? 0 : EBUSY; \
+    ret; \
+})
+#define SCMutexUnlock(mut) ({ \
+    int ret = 0; \
+    tmc_spin_queued_mutex_unlock(mut); \
+    ret; \
+})
+#else /* !__tile__ and ! DEBUG*/
 #define SCMutexInit(mut, mutattr ) pthread_mutex_init(mut, mutattr)
 #define SCMutexLock(mut) pthread_mutex_lock(mut)
 #define SCMutexTrylock(mut) pthread_mutex_trylock(mut)
 #define SCMutexUnlock(mut) pthread_mutex_unlock(mut)
-#endif
+#endif /* __tile__ */
+/* Control threads locks. Not Debug. */
+#define SCCtrlMutexInit(mut, mutattr ) pthread_mutex_init(mut, mutattr)
+#define SCCtrlMutexLock(mut) pthread_mutex_lock(mut)
+#define SCCtrlMutexTrylock(mut) pthread_mutex_trylock(mut)
+#define SCCtrlMutexUnlock(mut) pthread_mutex_unlock(mut)
+#endif /* DBG_THREADS */
 
 /** Conditions/Signals */
-/* Here we don't need to do nothing atm */
+/* Here we don't need to do anything at the moment */
+#ifdef __tile__
+/* Ignore signals when using spin locks */
+#define SCCondT uint8_t
+#define SCCondInit(x,y) ({ 0; })
+#define SCCondSignal(x)
+#define SCCondDestroy(x)
+#else /* !__tile__ */
 #define SCCondT pthread_cond_t
 #define SCCondInit pthread_cond_init
 #define SCCondSignal pthread_cond_signal
-#define SCCondTimedwait pthread_cond_timedwait
 #define SCCondDestroy pthread_cond_destroy
+#endif /* __tile__ */
+
+#define SCCtrlCondT pthread_cond_t
+#define SCCtrlCondInit pthread_cond_init
+#define SCCtrlCondSignal pthread_cond_signal
+#define SCCtrlCondTimedwait pthread_cond_timedwait
+#define SCCtrlCondDestroy pthread_cond_destroy
 
 #ifdef DBG_THREAD
 #define SCCondWait_dbg(cond, mut) ({ \
@@ -319,10 +384,27 @@ extern __thread uint64_t mutex_lock_cnt;
 })
 #define SCCondWait SCondWait_dbg
 #else
+#ifdef __tile__
+static inline void cycle_sleep(int cycles)
+{
+  uint64_t end = get_cycle_count() + cycles;
+  while (get_cycle_count() < end)
+    ;
+}
+#define SCCondWait(x,y) cycle_sleep(300)
+#else
 #define SCCondWait(cond, mut) pthread_cond_wait(cond, mut)
+#endif /* __tile__ */
 #endif
 
 /** Spinlocks */
+#if 0
+#ifdef __tile__
+#define SCSpinlock               tmc_spin_queued_mutex_t
+#else
+#define SCSpinlock               pthread_spinlock_t
+#endif
+#endif
 
 /** If posix spin not supported, use mutex */
 #if ((_POSIX_SPIN_LOCKS - 200112L) < 0L) || defined HELGRIND
@@ -472,12 +554,21 @@ extern __thread uint64_t spin_lock_cnt;
 
 #else /* if no dbg threads defined... */
 
+#ifdef __tile__
+#define SCSpinlock                              tmc_spin_queued_mutex_t
+#define SCSpinLock(spin)                        ({ tmc_spin_queued_mutex_lock(spin); 0; })
+#define SCSpinTrylock(spin)                     (tmc_spin_queued_mutex_trylock(spin) ? EBUSY : 0)
+#define SCSpinUnlock(spin)                      ({ tmc_spin_queued_mutex_unlock(spin); 0; })
+#define SCSpinInit(spin, spin_attr)             ({ tmc_spin_queued_mutex_init(spin); 0; })
+#define SCSpinDestroy(spin)                     ({ (void)(spin); 0; })
+#else
 #define SCSpinlock                              pthread_spinlock_t
 #define SCSpinLock(spin)                        pthread_spin_lock(spin)
 #define SCSpinTrylock(spin)                     pthread_spin_trylock(spin)
 #define SCSpinUnlock(spin)                      pthread_spin_unlock(spin)
 #define SCSpinInit(spin, spin_attr)             pthread_spin_init(spin, spin_attr)
 #define SCSpinDestroy(spin)                     pthread_spin_destroy(spin)
+#endif /* __tile__ */
 
 #endif /* DBG_THREADS */
 
@@ -719,6 +810,14 @@ extern __thread uint64_t rwr_lock_cnt;
 #define SCRWLockTryWRLock(rwl) pthread_rwlock_trywrlock(rwl)
 #define SCRWLockTryRDLock(rwl) pthread_rwlock_tryrdlock(rwl)
 #else
+#ifdef __tile__
+#define SCRWLockInit(rwl, rwlattr ) ({ tmc_spin_rwlock_init(rwl); 0; })
+#define SCRWLockWRLock(rwl) ({ tmc_spin_rwlock_wrlock(rwl); 0; })
+#define SCRWLockRDLock(rwl) ({ tmc_spin_rwlock_rdlock(rwl); 0; })
+#define SCRWLockTryWRLock(rwl) (tmc_spin_rwlock_trywrlock(rwl) ? EBUSY : 0)
+#define SCRWLockTryRDLock(rwl) (tmc_spin_rwlock_tryrdlock(rwl) ? EBUSY : 0)
+#define SCRWLockUnlock(rwl) ({ tmc_spin_rwlock_unlock(rwl); 0; })
+#else
 #define SCRWLockInit(rwl, rwlattr ) pthread_rwlock_init(rwl, rwlattr)
 #define SCRWLockWRLock(rwl) pthread_rwlock_wrlock(rwl)
 #define SCRWLockRDLock(rwl) pthread_rwlock_rdlock(rwl)
@@ -726,6 +825,7 @@ extern __thread uint64_t rwr_lock_cnt;
 #define SCRWLockTryRDLock(rwl) pthread_rwlock_tryrdlock(rwl)
 #define SCRWLockUnlock(rwl) pthread_rwlock_unlock(rwl)
 #endif
+#endif
 
 /** End of RWLock functions */
 
index 58581a0f7919aaf60e01609e6babadeff9828f09..6502072b90cd1c25617e923c8ea46314320a896d 100644 (file)
@@ -99,8 +99,8 @@ typedef struct ThreadVars_ {
     SCPerfContext sc_perf_pctx;
     SCPerfCounterArray *sc_perf_pca;
 
-    SCMutex *m;
-    SCCondT *cond;
+    SCCtrlMutex *ctrl_mutex;
+    SCCtrlCondT *ctrl_cond;
 
     uint8_t cap_flags; /**< Flags to indicate the capabilities of all the
                             TmModules resgitered under this thread */
index 0bc8fe4f5202473da05ae0596ed04ee3d5948a59..e15e218597722ecd1deee16c43d7a3df662ee832 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2012 Open Information Security Foundation
+/* Copyright (C) 2007-2013 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
@@ -1678,8 +1678,8 @@ void TmThreadKillThread(ThreadVars *tv)
             SCLogDebug("signalled tv->inq->id %" PRIu32 "", tv->inq->id);
         }
 
-        if (tv->cond != NULL ) {
-            pthread_cond_broadcast(tv->cond);
+        if (tv->ctrl_cond != NULL ) {
+            pthread_cond_broadcast(tv->ctrl_cond);
         }
 
         usleep(100);
@@ -1952,24 +1952,24 @@ void TmThreadSetAOF(ThreadVars *tv, uint8_t aof)
  */
 void TmThreadInitMC(ThreadVars *tv)
 {
-    if ( (tv->m = SCMalloc(sizeof(SCMutex))) == NULL) {
+    if ( (tv->ctrl_mutex = SCMalloc(sizeof(*tv->ctrl_mutex))) == NULL) {
         SCLogError(SC_ERR_FATAL, "Fatal error encountered in TmThreadInitMC.  "
                    "Exiting...");
         exit(EXIT_FAILURE);
     }
 
-    if (SCMutexInit(tv->m, NULL) != 0) {
+    if (SCCtrlMutexInit(tv->ctrl_mutex, NULL) != 0) {
         printf("Error initializing the tv->m mutex\n");
         exit(0);
     }
 
-    if ( (tv->cond = SCMalloc(sizeof(SCCondT))) == NULL) {
+    if ( (tv->ctrl_cond = SCMalloc(sizeof(*tv->ctrl_cond))) == NULL) {
         SCLogError(SC_ERR_FATAL, "Fatal error encountered in TmThreadInitMC.  "
                    "Exiting...");
         exit(0);
     }
 
-    if (SCCondInit(tv->cond, NULL) != 0) {
+    if (SCCtrlCondInit(tv->ctrl_cond, NULL) != 0) {
         SCLogError(SC_ERR_FATAL, "Error initializing the tv->cond condition "
                    "variable");
         exit(0);
index 207ddc71ab04593ab3c8941029e00e07e387c8ff..d25fab619eaa4407d086e3b7805cd7f8d3db9b4b 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2010 Open Information Security Foundation
+/* Copyright (C) 2007-2013 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
@@ -88,7 +88,7 @@ Packet *TmqhInputFlow(ThreadVars *tv)
     SCPerfSyncCountersIfSignalled(tv, 0);
 
     SCMutexLock(&q->mutex_q);
-    if (q->len == 0) {
+    while (q->len == 0) {
         /* if we have no packets in queue, wait... */
         SCCondWait(&q->cond_q, &q->mutex_q);
     }
index 3a1feafbaa9c17be306c193f551aa6dd5bc4d68f..cc5b69c06820383b7189463a135b8f9dab5efd48 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2010 Open Information Security Foundation
+/* Copyright (C) 2007-2013 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
@@ -50,7 +50,7 @@ Packet *TmqhInputSimple(ThreadVars *t)
 
     SCMutexLock(&q->mutex_q);
 
-    if (q->len == 0) {
+    while (q->len == 0) {
         /* if we have no packets in queue, wait... */
         SCCondWait(&q->cond_q, &q->mutex_q);
     }
@@ -111,7 +111,7 @@ void TmqhOutputSimple(ThreadVars *t, Packet *p)
 SCDQGenericQData *TmqhInputSimpleOnQ(SCDQDataQueue *q)
 {
     SCMutexLock(&q->mutex_q);
-    if (q->len == 0) {
+    while (q->len == 0) {
         /* if we have no packets in queue, wait... */
         SCCondWait(&q->cond_q, &q->mutex_q);
     }
index 6bf01ef878db58a5d7c101e7a3e85ddf961382e9..45540e1069efbb1600648a12cc3f838554b8dc08 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2012 Open Information Security Foundation
+/* Copyright (C) 2013 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
@@ -549,7 +549,7 @@ void UnixKillUnixManagerThread(void)
     ThreadVars *tv = NULL;
     int cnt = 0;
 
-    SCCondSignal(&unix_manager_cond);
+    SCCtrlCondSignal(&unix_manager_ctrl_cond);
 
     SCMutexLock(&tv_root_lock);
 
@@ -899,7 +899,8 @@ void UnixManagerThreadSpawn(DetectEngineCtx *de_ctx, int mode)
 {
     ThreadVars *tv_unixmgr = NULL;
 
-    SCCondInit(&unix_manager_cond, NULL);
+    SCCtrlCondInit(&unix_manager_ctrl_cond, NULL);
+    SCCtrlMutexInit(&unix_manager_ctrl_mutex, NULL);
 
     tv_unixmgr = TmThreadCreateCmdThread("UnixManagerThread",
                                           UnixManagerThread, 0);
index 97145a59bffe40cfe3e07b751dac0ea17f5e84e5..937737ef110a74f4a22e39db6eaf3a016c055036 100644 (file)
@@ -30,8 +30,8 @@
 
 #define UNIX_CMD_TAKE_ARGS 1
 
-SCCondT unix_manager_cond;
-SCMutex unix_manager_mutex;
+SCCtrlCondT unix_manager_ctrl_cond;
+SCCtrlMutex unix_manager_ctrl_mutex;
 
 void UnixManagerThreadSpawn(DetectEngineCtx *de_ctx, int mode);
 void UnixSocketKillSocketThread(void);