Use Spin locks on Tile

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.
pull/558/merge
Ken Steele 12 years ago committed by Victor Julien
parent 2f4e11b1ca
commit 592d48aab7

@ -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 * You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free * 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_sec = time(NULL) + sc_counter_tts;
cond_time.tv_nsec = 0; cond_time.tv_nsec = 0;
SCMutexLock(tv_local->m); SCCtrlMutexLock(tv_local->ctrl_mutex);
SCCondTimedwait(tv_local->cond, tv_local->m, &cond_time); SCCtrlCondTimedwait(tv_local->ctrl_cond, tv_local->ctrl_mutex, &cond_time);
SCMutexUnlock(tv_local->m); SCCtrlMutexUnlock(tv_local->ctrl_mutex);
SCPerfOutputCounters(); SCPerfOutputCounters();
@ -542,9 +542,9 @@ static void *SCPerfWakeupThread(void *arg)
cond_time.tv_sec = time(NULL) + SC_PERF_WUT_TTS; cond_time.tv_sec = time(NULL) + SC_PERF_WUT_TTS;
cond_time.tv_nsec = 0; cond_time.tv_nsec = 0;
SCMutexLock(tv_local->m); SCCtrlMutexLock(tv_local->ctrl_mutex);
SCCondTimedwait(tv_local->cond, tv_local->m, &cond_time); SCCtrlCondTimedwait(tv_local->ctrl_cond, tv_local->ctrl_mutex, &cond_time);
SCMutexUnlock(tv_local->m); SCCtrlMutexUnlock(tv_local->ctrl_mutex);
tv = tv_root[TVT_PPT]; tv = tv_root[TVT_PPT];
while (tv != NULL) { while (tv != NULL) {

@ -94,7 +94,7 @@ void FlowKillFlowManagerThread(void)
ThreadVars *tv = NULL; ThreadVars *tv = NULL;
int cnt = 0; int cnt = 0;
SCCondSignal(&flow_manager_cond); SCCtrlCondSignal(&flow_manager_ctrl_cond);
SCMutexLock(&tv_root_lock); 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_sec = time(NULL) + flow_update_delay_sec;
cond_time.tv_nsec = flow_update_delay_nsec; cond_time.tv_nsec = flow_update_delay_nsec;
SCMutexLock(&flow_manager_mutex); SCCtrlMutexLock(&flow_manager_ctrl_mutex);
SCCondTimedwait(&flow_manager_cond, &flow_manager_mutex, &cond_time); SCCtrlCondTimedwait(&flow_manager_ctrl_cond, &flow_manager_ctrl_mutex,
SCMutexUnlock(&flow_manager_mutex); &cond_time);
SCCtrlMutexUnlock(&flow_manager_ctrl_mutex);
SCLogDebug("woke up... %s", SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY ? "emergency":""); SCLogDebug("woke up... %s", SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY ? "emergency":"");
@ -566,8 +567,8 @@ void FlowManagerThreadSpawn()
{ {
ThreadVars *tv_flowmgr = NULL; ThreadVars *tv_flowmgr = NULL;
SCCondInit(&flow_manager_cond, NULL); SCCtrlCondInit(&flow_manager_ctrl_cond, NULL);
SCMutexInit(&flow_manager_mutex, NULL); SCCtrlMutexInit(&flow_manager_ctrl_mutex, NULL);
tv_flowmgr = TmThreadCreateMgmtThread("FlowManagerThread", tv_flowmgr = TmThreadCreateMgmtThread("FlowManagerThread",
FlowManagerThread, 0); FlowManagerThread, 0);

@ -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 * You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free * the GNU General Public License version 2 as published by the Free
@ -25,9 +25,9 @@
#define __FLOW_MANAGER_H__ #define __FLOW_MANAGER_H__
/** flow manager scheduling condition */ /** flow manager scheduling condition */
SCCondT flow_manager_cond; SCCtrlCondT flow_manager_ctrl_cond;
SCMutex flow_manager_mutex; SCCtrlMutex flow_manager_ctrl_mutex;
#define FlowWakeupFlowManagerThread() SCCondSignal(&flow_manager_cond) #define FlowWakeupFlowManagerThread() SCCtrlCondSignal(&flow_manager_ctrl_cond)
void FlowManagerThreadSpawn(void); void FlowManagerThreadSpawn(void);
void FlowKillFlowManagerThread(void); void FlowKillFlowManagerThread(void);

@ -27,6 +27,11 @@
#ifndef __THREADS_H__ #ifndef __THREADS_H__
#define __THREADS_H__ #define __THREADS_H__
#ifdef __tile__
#include <tmc/spin.h>
#include <arch/cycle.h>
#endif
#if HAVE_CONFIG_H #if HAVE_CONFIG_H
#include <config.h> #include <config.h>
#endif #endif
@ -101,14 +106,34 @@ enum {
//#define DBG_THREADS //#define DBG_THREADS
/** Suricata Mutex */ /** 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 SCMutex pthread_mutex_t
#define SCMutexAttr pthread_mutexattr_t #define SCMutexAttr pthread_mutexattr_t
#define SCMutexDestroy pthread_mutex_destroy #define SCMutexDestroy pthread_mutex_destroy
#define SCMUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER #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 */ /** Suricata RWLocks */
#ifdef __tile__
#define SCRWLock tmc_spin_rwlock_t
#define SCRWLockDestroy(x) ({ (void)(x); 0; })
#else
#define SCRWLock pthread_rwlock_t #define SCRWLock pthread_rwlock_t
#define SCRWLockDestroy pthread_rwlock_destroy #define SCRWLockDestroy pthread_rwlock_destroy
#endif
/** Get the Current Thread Id */ /** Get the Current Thread Id */
#ifdef OS_FREEBSD #ifdef OS_FREEBSD
@ -291,20 +316,60 @@ extern __thread uint64_t mutex_lock_cnt;
#define SCMutexLock(mut) SCMutexLock_profile(mut) #define SCMutexLock(mut) SCMutexLock_profile(mut)
#define SCMutexTrylock(mut) pthread_mutex_trylock(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 SCMutexInit(mut, mutattr ) pthread_mutex_init(mut, mutattr)
#define SCMutexLock(mut) pthread_mutex_lock(mut) #define SCMutexLock(mut) pthread_mutex_lock(mut)
#define SCMutexTrylock(mut) pthread_mutex_trylock(mut) #define SCMutexTrylock(mut) pthread_mutex_trylock(mut)
#define SCMutexUnlock(mut) pthread_mutex_unlock(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 */ /** 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 SCCondT pthread_cond_t
#define SCCondInit pthread_cond_init #define SCCondInit pthread_cond_init
#define SCCondSignal pthread_cond_signal #define SCCondSignal pthread_cond_signal
#define SCCondTimedwait pthread_cond_timedwait
#define SCCondDestroy pthread_cond_destroy #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 #ifdef DBG_THREAD
#define SCCondWait_dbg(cond, mut) ({ \ #define SCCondWait_dbg(cond, mut) ({ \
@ -319,10 +384,27 @@ extern __thread uint64_t mutex_lock_cnt;
}) })
#define SCCondWait SCondWait_dbg #define SCCondWait SCondWait_dbg
#else #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) #define SCCondWait(cond, mut) pthread_cond_wait(cond, mut)
#endif /* __tile__ */
#endif #endif
/** Spinlocks */ /** 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 not supported, use mutex */
#if ((_POSIX_SPIN_LOCKS - 200112L) < 0L) || defined HELGRIND #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... */ #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 pthread_spinlock_t
#define SCSpinLock(spin) pthread_spin_lock(spin) #define SCSpinLock(spin) pthread_spin_lock(spin)
#define SCSpinTrylock(spin) pthread_spin_trylock(spin) #define SCSpinTrylock(spin) pthread_spin_trylock(spin)
#define SCSpinUnlock(spin) pthread_spin_unlock(spin) #define SCSpinUnlock(spin) pthread_spin_unlock(spin)
#define SCSpinInit(spin, spin_attr) pthread_spin_init(spin, spin_attr) #define SCSpinInit(spin, spin_attr) pthread_spin_init(spin, spin_attr)
#define SCSpinDestroy(spin) pthread_spin_destroy(spin) #define SCSpinDestroy(spin) pthread_spin_destroy(spin)
#endif /* __tile__ */
#endif /* DBG_THREADS */ #endif /* DBG_THREADS */
@ -719,6 +810,14 @@ extern __thread uint64_t rwr_lock_cnt;
#define SCRWLockTryWRLock(rwl) pthread_rwlock_trywrlock(rwl) #define SCRWLockTryWRLock(rwl) pthread_rwlock_trywrlock(rwl)
#define SCRWLockTryRDLock(rwl) pthread_rwlock_tryrdlock(rwl) #define SCRWLockTryRDLock(rwl) pthread_rwlock_tryrdlock(rwl)
#else #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 SCRWLockInit(rwl, rwlattr ) pthread_rwlock_init(rwl, rwlattr)
#define SCRWLockWRLock(rwl) pthread_rwlock_wrlock(rwl) #define SCRWLockWRLock(rwl) pthread_rwlock_wrlock(rwl)
#define SCRWLockRDLock(rwl) pthread_rwlock_rdlock(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 SCRWLockTryRDLock(rwl) pthread_rwlock_tryrdlock(rwl)
#define SCRWLockUnlock(rwl) pthread_rwlock_unlock(rwl) #define SCRWLockUnlock(rwl) pthread_rwlock_unlock(rwl)
#endif #endif
#endif
/** End of RWLock functions */ /** End of RWLock functions */

@ -99,8 +99,8 @@ typedef struct ThreadVars_ {
SCPerfContext sc_perf_pctx; SCPerfContext sc_perf_pctx;
SCPerfCounterArray *sc_perf_pca; SCPerfCounterArray *sc_perf_pca;
SCMutex *m; SCCtrlMutex *ctrl_mutex;
SCCondT *cond; SCCtrlCondT *ctrl_cond;
uint8_t cap_flags; /**< Flags to indicate the capabilities of all the uint8_t cap_flags; /**< Flags to indicate the capabilities of all the
TmModules resgitered under this thread */ TmModules resgitered under this thread */

@ -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 * You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free * 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); SCLogDebug("signalled tv->inq->id %" PRIu32 "", tv->inq->id);
} }
if (tv->cond != NULL ) { if (tv->ctrl_cond != NULL ) {
pthread_cond_broadcast(tv->cond); pthread_cond_broadcast(tv->ctrl_cond);
} }
usleep(100); usleep(100);
@ -1952,24 +1952,24 @@ void TmThreadSetAOF(ThreadVars *tv, uint8_t aof)
*/ */
void TmThreadInitMC(ThreadVars *tv) 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. " SCLogError(SC_ERR_FATAL, "Fatal error encountered in TmThreadInitMC. "
"Exiting..."); "Exiting...");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (SCMutexInit(tv->m, NULL) != 0) { if (SCCtrlMutexInit(tv->ctrl_mutex, NULL) != 0) {
printf("Error initializing the tv->m mutex\n"); printf("Error initializing the tv->m mutex\n");
exit(0); 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. " SCLogError(SC_ERR_FATAL, "Fatal error encountered in TmThreadInitMC. "
"Exiting..."); "Exiting...");
exit(0); 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 " SCLogError(SC_ERR_FATAL, "Error initializing the tv->cond condition "
"variable"); "variable");
exit(0); exit(0);

@ -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 * You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free * the GNU General Public License version 2 as published by the Free
@ -88,7 +88,7 @@ Packet *TmqhInputFlow(ThreadVars *tv)
SCPerfSyncCountersIfSignalled(tv, 0); SCPerfSyncCountersIfSignalled(tv, 0);
SCMutexLock(&q->mutex_q); SCMutexLock(&q->mutex_q);
if (q->len == 0) { while (q->len == 0) {
/* if we have no packets in queue, wait... */ /* if we have no packets in queue, wait... */
SCCondWait(&q->cond_q, &q->mutex_q); SCCondWait(&q->cond_q, &q->mutex_q);
} }

@ -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 * You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free * the GNU General Public License version 2 as published by the Free
@ -50,7 +50,7 @@ Packet *TmqhInputSimple(ThreadVars *t)
SCMutexLock(&q->mutex_q); SCMutexLock(&q->mutex_q);
if (q->len == 0) { while (q->len == 0) {
/* if we have no packets in queue, wait... */ /* if we have no packets in queue, wait... */
SCCondWait(&q->cond_q, &q->mutex_q); SCCondWait(&q->cond_q, &q->mutex_q);
} }
@ -111,7 +111,7 @@ void TmqhOutputSimple(ThreadVars *t, Packet *p)
SCDQGenericQData *TmqhInputSimpleOnQ(SCDQDataQueue *q) SCDQGenericQData *TmqhInputSimpleOnQ(SCDQDataQueue *q)
{ {
SCMutexLock(&q->mutex_q); SCMutexLock(&q->mutex_q);
if (q->len == 0) { while (q->len == 0) {
/* if we have no packets in queue, wait... */ /* if we have no packets in queue, wait... */
SCCondWait(&q->cond_q, &q->mutex_q); SCCondWait(&q->cond_q, &q->mutex_q);
} }

@ -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 * You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free * the GNU General Public License version 2 as published by the Free
@ -549,7 +549,7 @@ void UnixKillUnixManagerThread(void)
ThreadVars *tv = NULL; ThreadVars *tv = NULL;
int cnt = 0; int cnt = 0;
SCCondSignal(&unix_manager_cond); SCCtrlCondSignal(&unix_manager_ctrl_cond);
SCMutexLock(&tv_root_lock); SCMutexLock(&tv_root_lock);
@ -899,7 +899,8 @@ void UnixManagerThreadSpawn(DetectEngineCtx *de_ctx, int mode)
{ {
ThreadVars *tv_unixmgr = NULL; 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", tv_unixmgr = TmThreadCreateCmdThread("UnixManagerThread",
UnixManagerThread, 0); UnixManagerThread, 0);

@ -30,8 +30,8 @@
#define UNIX_CMD_TAKE_ARGS 1 #define UNIX_CMD_TAKE_ARGS 1
SCCondT unix_manager_cond; SCCtrlCondT unix_manager_ctrl_cond;
SCMutex unix_manager_mutex; SCCtrlMutex unix_manager_ctrl_mutex;
void UnixManagerThreadSpawn(DetectEngineCtx *de_ctx, int mode); void UnixManagerThreadSpawn(DetectEngineCtx *de_ctx, int mode);
void UnixSocketKillSocketThread(void); void UnixSocketKillSocketThread(void);

Loading…
Cancel
Save