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
* 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) {

@ -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);

@ -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);

@ -27,6 +27,11 @@
#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 */

@ -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 */

@ -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);

@ -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);
}

@ -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);
}

@ -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);

@ -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);

Loading…
Cancel
Save