From: Victor Julien Date: Fri, 28 Apr 2017 07:23:09 +0000 (+0200) Subject: cleanup: remove unused ringbuffer code X-Git-Tag: suricata-4.0.0-beta1~116 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=276125c1ef322363b49ae22f8b4b6a9303825fbe;p=thirdparty%2Fsuricata.git cleanup: remove unused ringbuffer code --- diff --git a/configure.ac b/configure.ac index 200052f2b4..24d8a2516e 100644 --- a/configure.ac +++ b/configure.ac @@ -56,9 +56,6 @@ if test "$gccvernum" -ge "400"; then dnl gcc 4.0 or later GCC_CFLAGS="-Wextra -Werror-implicit-function-declaration" - # remove optimization options that break our code - # VJ 2010/06/27: no-tree-pre added. It breaks ringbuffers code. - GCC_CFLAGS="$GCC_CFLAGS -fno-tree-pre" else GCC_CFLAGS="-W" fi diff --git a/src/Makefile.am b/src/Makefile.am index 57b5f40ad3..5ef109d069 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -348,7 +348,6 @@ tm-modules.c tm-modules.h \ tmqh-flow.c tmqh-flow.h \ tmqh-nfq.c tmqh-nfq.h \ tmqh-packetpool.c tmqh-packetpool.h \ -tmqh-ringbuffer.c tmqh-ringbuffer.h \ tmqh-simple.c tmqh-simple.h \ tm-queuehandlers.c tm-queuehandlers.h \ tm-queues.c tm-queues.h \ @@ -436,7 +435,6 @@ util-proto-name.c util-proto-name.h \ util-radix-tree.c util-radix-tree.h \ util-random.c util-random.h \ util-reference-config.c util-reference-config.h \ -util-ringbuffer.c util-ringbuffer.h \ util-rohash.c util-rohash.h \ util-rule-vars.c util-rule-vars.h \ util-runmodes.c util-runmodes.h \ diff --git a/src/runmode-unittests.c b/src/runmode-unittests.c index 6d1632dc4e..6bbad32cc1 100644 --- a/src/runmode-unittests.c +++ b/src/runmode-unittests.c @@ -93,7 +93,6 @@ #include "util-magic.h" #include "util-memcmp.h" #include "util-misc.h" -#include "util-ringbuffer.h" #include "util-signal.h" #include "reputation.h" @@ -190,7 +189,6 @@ static void RegisterUnittests(void) SCProfilingRegisterTests(); #endif DeStateRegisterTests(); - DetectRingBufferRegisterTests(); MemcmpRegisterTests(); DetectEngineHttpClientBodyRegisterTests(); DetectEngineHttpServerBodyRegisterTests(); diff --git a/src/tm-queuehandlers.c b/src/tm-queuehandlers.c index 007a8ab370..48d06aac61 100644 --- a/src/tm-queuehandlers.c +++ b/src/tm-queuehandlers.c @@ -34,7 +34,6 @@ #include "tmqh-nfq.h" #include "tmqh-packetpool.h" #include "tmqh-flow.h" -#include "tmqh-ringbuffer.h" void TmqhSetup (void) { @@ -44,13 +43,11 @@ void TmqhSetup (void) TmqhNfqRegister(); TmqhPacketpoolRegister(); TmqhFlowRegister(); - TmqhRingBufferRegister(); } /** \brief Clean up registration time allocs */ void TmqhCleanup(void) { - TmqhRingBufferDestroy(); } Tmqh* TmqhGetQueueHandlerByName(char *name) diff --git a/src/tm-queuehandlers.h b/src/tm-queuehandlers.h index 63249799ad..28e0ffc14b 100644 --- a/src/tm-queuehandlers.h +++ b/src/tm-queuehandlers.h @@ -29,9 +29,6 @@ enum { TMQH_NFQ, TMQH_PACKETPOOL, TMQH_FLOW, - TMQH_RINGBUFFER_MRSW, - TMQH_RINGBUFFER_SRSW, - TMQH_RINGBUFFER_SRMW, TMQH_SIZE, }; diff --git a/src/tmqh-ringbuffer.c b/src/tmqh-ringbuffer.c deleted file mode 100644 index 29228e1a74..0000000000 --- a/src/tmqh-ringbuffer.c +++ /dev/null @@ -1,151 +0,0 @@ -/* Copyright (C) 2007-2010 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 - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Victor Julien - * - * RingBuffer queue handler - */ - -#include "suricata.h" -#include "packet-queue.h" -#include "decode.h" -#include "threads.h" -#include "threadvars.h" - -#include "tm-queuehandlers.h" - -#include "util-ringbuffer.h" - -static RingBuffer8 *ringbuffers[256]; - -Packet *TmqhInputRingBufferMrSw(ThreadVars *t); -void TmqhOutputRingBufferMrSw(ThreadVars *t, Packet *p); -Packet *TmqhInputRingBufferSrSw(ThreadVars *t); -void TmqhOutputRingBufferSrSw(ThreadVars *t, Packet *p); -Packet *TmqhInputRingBufferSrMw(ThreadVars *t); -void TmqhOutputRingBufferSrMw(ThreadVars *t, Packet *p); -void TmqhInputRingBufferShutdownHandler(ThreadVars *); - -/** - * \brief TmqhRingBufferRegister - * \initonly - */ -void TmqhRingBufferRegister (void) -{ - tmqh_table[TMQH_RINGBUFFER_MRSW].name = "ringbuffer_mrsw"; - tmqh_table[TMQH_RINGBUFFER_MRSW].InHandler = TmqhInputRingBufferMrSw; - tmqh_table[TMQH_RINGBUFFER_MRSW].InShutdownHandler = TmqhInputRingBufferShutdownHandler; - tmqh_table[TMQH_RINGBUFFER_MRSW].OutHandler = TmqhOutputRingBufferMrSw; - - tmqh_table[TMQH_RINGBUFFER_SRSW].name = "ringbuffer_srsw"; - tmqh_table[TMQH_RINGBUFFER_SRSW].InHandler = TmqhInputRingBufferSrSw; - tmqh_table[TMQH_RINGBUFFER_SRSW].InShutdownHandler = TmqhInputRingBufferShutdownHandler; - tmqh_table[TMQH_RINGBUFFER_SRSW].OutHandler = TmqhOutputRingBufferSrSw; - - tmqh_table[TMQH_RINGBUFFER_SRMW].name = "ringbuffer_srmw"; - tmqh_table[TMQH_RINGBUFFER_SRMW].InHandler = TmqhInputRingBufferSrMw; - tmqh_table[TMQH_RINGBUFFER_SRMW].InShutdownHandler = TmqhInputRingBufferShutdownHandler; - tmqh_table[TMQH_RINGBUFFER_SRMW].OutHandler = TmqhOutputRingBufferSrMw; - - memset(ringbuffers, 0, sizeof(ringbuffers)); - - int i = 0; - for (i = 0; i < 256; i++) { - ringbuffers[i] = RingBuffer8Init(); - if (ringbuffers[i] == NULL) { - SCLogError(SC_ERR_FATAL, "Error allocating memory to register Ringbuffers. Exiting..."); - exit(EXIT_FAILURE); - } - } -} - -void TmqhRingBufferDestroy (void) -{ - int i = 0; - for (i = 0; i < 256; i++) { - RingBuffer8Destroy(ringbuffers[i]); - } -} - -void TmqhInputRingBufferShutdownHandler(ThreadVars *tv) -{ - if (tv == NULL || tv->inq == NULL) { - return; - } - - RingBuffer8 *rb = ringbuffers[tv->inq->id]; - if (rb == NULL) { - return; - } - - RingBuffer8Shutdown(rb); -} - -Packet *TmqhInputRingBufferMrSw(ThreadVars *t) -{ - RingBuffer8 *rb = ringbuffers[t->inq->id]; - - Packet *p = (Packet *)RingBufferMrSw8Get(rb); - - StatsSyncCountersIfSignalled(t); - - return p; -} - -void TmqhOutputRingBufferMrSw(ThreadVars *t, Packet *p) -{ - RingBuffer8 *rb = ringbuffers[t->outq->id]; - RingBufferMrSw8Put(rb, (void *)p); -} - -Packet *TmqhInputRingBufferSrSw(ThreadVars *t) -{ - RingBuffer8 *rb = ringbuffers[t->inq->id]; - - Packet *p = (Packet *)RingBufferSrSw8Get(rb); - - StatsSyncCountersIfSignalled(t); - - return p; -} - -void TmqhOutputRingBufferSrSw(ThreadVars *t, Packet *p) -{ - RingBuffer8 *rb = ringbuffers[t->outq->id]; - RingBufferSrSw8Put(rb, (void *)p); -} - -Packet *TmqhInputRingBufferSrMw(ThreadVars *t) -{ - RingBuffer8 *rb = ringbuffers[t->inq->id]; - - Packet *p = (Packet *)RingBufferSrMw8Get(rb); - - StatsSyncCountersIfSignalled(t); - - return p; -} - -void TmqhOutputRingBufferSrMw(ThreadVars *t, Packet *p) -{ - RingBuffer8 *rb = ringbuffers[t->outq->id]; - RingBufferSrMw8Put(rb, (void *)p); -} - diff --git a/src/tmqh-ringbuffer.h b/src/tmqh-ringbuffer.h deleted file mode 100644 index f38fce9971..0000000000 --- a/src/tmqh-ringbuffer.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (C) 2007-2010 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 - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Victor Julien - */ - -#ifndef __TMQH_RINGBUFFER_H__ -#define __TMQH_RINGBUFFER_H__ - -void TmqhRingBufferRegister (void); -void TmqhRingBufferDestroy (void); - -#endif /* __TMQH_RINGBUFFER_H__ */ diff --git a/src/util-ringbuffer.c b/src/util-ringbuffer.c deleted file mode 100644 index e4457f40d4..0000000000 --- a/src/util-ringbuffer.c +++ /dev/null @@ -1,1088 +0,0 @@ -/* Copyright (C) 2007-2010 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 - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Victor Julien - * - * Ringbuffer implementation that is lockless for the most part IF atomic - * operations are available. - * - * Two sizes are implemented currently: 256 and 65536. Those sizes are chosen - * for simplicity when working with the read and write indexes. Both can just - * wrap around. - * - * Implemented are: - * Single reader, single writer (lockless) - * Single reader, multi writer (partly locked) - * Multi reader, single writer (lockless) - * Multi reader, multi writer (partly locked) - */ -#include "suricata-common.h" -#include "suricata.h" -#include "util-ringbuffer.h" -#include "util-atomic.h" -#include "util-unittest.h" - -#define USLEEP_TIME 5 - -/** \brief wait function for condition where ringbuffer is either - * full or empty. - * - * \param rb ringbuffer - * - * Based on RINGBUFFER_MUTEX_WAIT define, we either sleep and spin - * or use thread condition to wait. - */ -static inline void RingBuffer8DoWait(RingBuffer8 *rb) -{ -#ifdef RINGBUFFER_MUTEX_WAIT - SCMutexLock(&rb->wait_mutex); - SCCondWait(&rb->wait_cond, &rb->wait_mutex); - SCMutexUnlock(&rb->wait_mutex); -#else - usleep(USLEEP_TIME); -#endif -} - -/** \brief wait function for condition where ringbuffer is either - * full or empty. - * - * \param rb ringbuffer - * - * Based on RINGBUFFER_MUTEX_WAIT define, we either sleep and spin - * or use thread condition to wait. - */ -static inline void RingBufferDoWait(RingBuffer16 *rb) -{ -#ifdef RINGBUFFER_MUTEX_WAIT - SCMutexLock(&rb->wait_mutex); - SCCondWait(&rb->wait_cond, &rb->wait_mutex); - SCMutexUnlock(&rb->wait_mutex); -#else - usleep(USLEEP_TIME); -#endif -} - -/** \brief wait function for condition where ringbuffer is either - * full or empty. - * - * \param rb ringbuffer - * - * Based on RINGBUFFER_MUTEX_WAIT define, we either sleep and spin - * or use thread condition to wait. - */ -void RingBufferWait(RingBuffer16 *rb) -{ - RingBufferDoWait(rb); -} - -/** \brief tell the ringbuffer to shut down - * - * \param rb ringbuffer - */ -void RingBuffer8Shutdown(RingBuffer8 *rb) -{ - rb->shutdown = 1; -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif -} - -/** \brief check the ringbuffer is empty (no data in it) - * - * \param rb ringbuffer - * - * \retval 1 empty - * \retval 0 not empty - */ -int RingBuffer8IsEmpty(RingBuffer8 *rb) -{ - if (SC_ATOMIC_GET(rb->write) == SC_ATOMIC_GET(rb->read)) { - return 1; - } - - return 0; -} - -/** \brief check the ringbuffer is full (no more data will fit) - * - * \param rb ringbuffer - * - * \retval 1 empty - * \retval 0 not empty - */ -int RingBuffer8IsFull(RingBuffer8 *rb) -{ - if ((unsigned char)(SC_ATOMIC_GET(rb->write) + 1) == SC_ATOMIC_GET(rb->read)) { - return 1; - } - - return 0; -} - -/** \brief tell the ringbuffer to shut down - * - * \param rb ringbuffer - */ -void RingBufferShutdown(RingBuffer16 *rb) -{ - rb->shutdown = 1; -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif -} - -/** \brief get number of items in the ringbuffer */ -uint16_t RingBufferSize(RingBuffer16 *rb) -{ - SCEnter(); - uint16_t size = (uint16_t)(SC_ATOMIC_GET(rb->write) - SC_ATOMIC_GET(rb->read)); - SCReturnUInt(size); -} - -/** \brief check the ringbuffer is empty (no data in it) - * - * \param rb ringbuffer - * - * \retval 1 empty - * \retval 0 not empty - */ -int RingBufferIsEmpty(RingBuffer16 *rb) -{ - if (SC_ATOMIC_GET(rb->write) == SC_ATOMIC_GET(rb->read)) { - return 1; - } - - return 0; -} - -/** \brief check the ringbuffer is full (no more data will fit) - * - * \param rb ringbuffer - * - * \retval 1 empty - * \retval 0 not empty - */ -int RingBufferIsFull(RingBuffer16 *rb) -{ - if ((unsigned short)(SC_ATOMIC_GET(rb->write) + 1) == SC_ATOMIC_GET(rb->read)) { - return 1; - } - - return 0; -} - -/* Single Reader, Single Writer, 8 bits */ - -void *RingBufferSrSw8Get(RingBuffer8 *rb) -{ - void *ptr = NULL; - - /* buffer is empty, wait... */ - while (SC_ATOMIC_GET(rb->write) == SC_ATOMIC_GET(rb->read)) { - /* break out if the engine wants to shutdown */ - if (rb->shutdown != 0) - return NULL; - - RingBuffer8DoWait(rb); - } - - ptr = rb->array[SC_ATOMIC_GET(rb->read)]; - (void) SC_ATOMIC_ADD(rb->read, 1); - -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif - return ptr; -} - -int RingBufferSrSw8Put(RingBuffer8 *rb, void *ptr) -{ - /* buffer is full, wait... */ - while ((unsigned char)(SC_ATOMIC_GET(rb->write) + 1) == SC_ATOMIC_GET(rb->read)) { - /* break out if the engine wants to shutdown */ - if (rb->shutdown != 0) - return -1; - - RingBuffer8DoWait(rb); - } - - rb->array[SC_ATOMIC_GET(rb->write)] = ptr; - (void) SC_ATOMIC_ADD(rb->write, 1); - -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif - return 0; -} - -/* Single Reader, Multi Writer, 8 bites */ - -void *RingBufferSrMw8Get(RingBuffer8 *rb) -{ - void *ptr = NULL; - - /* buffer is empty, wait... */ - while (SC_ATOMIC_GET(rb->write) == SC_ATOMIC_GET(rb->read)) { - /* break out if the engine wants to shutdown */ - if (rb->shutdown != 0) - return NULL; - - RingBuffer8DoWait(rb); - } - - ptr = rb->array[SC_ATOMIC_GET(rb->read)]; - (void) SC_ATOMIC_ADD(rb->read, 1); - -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif - return ptr; -} - -/** - * \brief put a ptr in the RingBuffer. - * - * As we support multiple writers we need to protect 2 things: - * 1. writing the ptr to the array - * 2. incrementing the rb->write idx - * - * We can't do both at the same time in one atomic operation, so - * we need to (spin) lock it. We do increment rb->write atomically - * after that, so that we don't need to use the lock in our *Get - * function. - * - * \param rb the ringbuffer - * \param ptr ptr to store - * - * \retval 0 ok - * \retval -1 wait loop interrupted because of engine flags - */ -int RingBufferSrMw8Put(RingBuffer8 *rb, void *ptr) -{ - SCLogDebug("ptr %p", ptr); - - /* buffer is full, wait... */ -retry: - while ((unsigned char)(SC_ATOMIC_GET(rb->write) + 1) == SC_ATOMIC_GET(rb->read)) { - /* break out if the engine wants to shutdown */ - if (rb->shutdown != 0) - return -1; - - RingBuffer8DoWait(rb); - } - - /* get our lock */ - SCSpinLock(&rb->spin); - /* if while we got our lock the buffer changed, we need to retry */ - if ((unsigned char)(SC_ATOMIC_GET(rb->write) + 1) == SC_ATOMIC_GET(rb->read)) { - SCSpinUnlock(&rb->spin); - goto retry; - } - - SCLogDebug("rb->write %u, ptr %p", SC_ATOMIC_GET(rb->write), ptr); - - /* update the ring buffer */ - rb->array[SC_ATOMIC_GET(rb->write)] = ptr; - (void) SC_ATOMIC_ADD(rb->write, 1); - SCSpinUnlock(&rb->spin); - SCLogDebug("ptr %p, done", ptr); - -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif - return 0; -} - -/* Multi Reader, Single Writer, 8 bits */ - -/** - * \brief get the next ptr from the ring buffer - * - * Because we allow for multiple readers we take great care in making sure - * that the threads don't interfere with one another. - * - */ -void *RingBufferMrSw8Get(RingBuffer8 *rb) -{ - void *ptr; - /** local pointer for data races. If SCAtomicCompareAndSwap (CAS) - * fails we increase our local array idx to try the next array member - * until we succeed. Or when the buffer is empty again we jump back - * to the waiting loop. */ - unsigned char readp; - - /* buffer is empty, wait... */ -retry: - while (SC_ATOMIC_GET(rb->write) == SC_ATOMIC_GET(rb->read)) { - /* break out if the engine wants to shutdown */ - if (rb->shutdown != 0) - return NULL; - - RingBuffer8DoWait(rb); - } - - /* atomically update rb->read */ - readp = SC_ATOMIC_GET(rb->read) - 1; - do { - /* with multiple readers we can get in the situation that we exitted - * from the wait loop but the rb is empty again once we get here. */ - if (SC_ATOMIC_GET(rb->write) == SC_ATOMIC_GET(rb->read)) - goto retry; - - readp++; - ptr = rb->array[readp]; - } while (!(SC_ATOMIC_CAS(&rb->read, readp, (readp + 1)))); - - SCLogDebug("ptr %p", ptr); - -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif - return ptr; -} - -/** - * \brief put a ptr in the RingBuffer - */ -int RingBufferMrSw8Put(RingBuffer8 *rb, void *ptr) -{ - SCLogDebug("ptr %p", ptr); - - /* buffer is full, wait... */ - while ((unsigned char)(SC_ATOMIC_GET(rb->write) + 1) == SC_ATOMIC_GET(rb->read)) { - /* break out if the engine wants to shutdown */ - if (rb->shutdown != 0) - return -1; - - RingBuffer8DoWait(rb); - } - - rb->array[SC_ATOMIC_GET(rb->write)] = ptr; - (void) SC_ATOMIC_ADD(rb->write, 1); - -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif - return 0; -} - - -/* Multi Reader, Single Writer */ - -/** - * \brief get the next ptr from the ring buffer - * - * Because we allow for multiple readers we take great care in making sure - * that the threads don't interfere with one another. - * - */ -void *RingBufferMrSwGet(RingBuffer16 *rb) -{ - void *ptr; - /** local pointer for data races. If SCAtomicCompareAndSwap (CAS) - * fails we increase our local array idx to try the next array member - * until we succeed. Or when the buffer is empty again we jump back - * to the waiting loop. */ - unsigned short readp; - - /* buffer is empty, wait... */ -retry: - while (SC_ATOMIC_GET(rb->write) == SC_ATOMIC_GET(rb->read)) { - /* break out if the engine wants to shutdown */ - if (rb->shutdown != 0) - return NULL; - - RingBufferDoWait(rb); - } - - /* atomically update rb->read */ - readp = SC_ATOMIC_GET(rb->read) - 1; - do { - /* with multiple readers we can get in the situation that we exitted - * from the wait loop but the rb is empty again once we get here. */ - if (SC_ATOMIC_GET(rb->write) == SC_ATOMIC_GET(rb->read)) - goto retry; - - readp++; - ptr = rb->array[readp]; - } while (!(SC_ATOMIC_CAS(&rb->read, readp, (readp + 1)))); - - SCLogDebug("ptr %p", ptr); - -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif - return ptr; -} - -/** - * \brief put a ptr in the RingBuffer - */ -int RingBufferMrSwPut(RingBuffer16 *rb, void *ptr) -{ - SCLogDebug("ptr %p", ptr); - - /* buffer is full, wait... */ - while ((unsigned short)(SC_ATOMIC_GET(rb->write) + 1) == SC_ATOMIC_GET(rb->read)) { - /* break out if the engine wants to shutdown */ - if (rb->shutdown != 0) - return -1; - - RingBufferDoWait(rb); - } - - rb->array[SC_ATOMIC_GET(rb->write)] = ptr; - (void) SC_ATOMIC_ADD(rb->write, 1); - -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif - return 0; -} - - -/* Single Reader, Single Writer */ - -void *RingBufferSrSwGet(RingBuffer16 *rb) -{ - void *ptr = NULL; - - /* buffer is empty, wait... */ - while (SC_ATOMIC_GET(rb->write) == SC_ATOMIC_GET(rb->read)) { - /* break out if the engine wants to shutdown */ - if (rb->shutdown != 0) - return NULL; - - RingBufferDoWait(rb); - } - - ptr = rb->array[SC_ATOMIC_GET(rb->read)]; - (void) SC_ATOMIC_ADD(rb->read, 1); - -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif - return ptr; -} - -int RingBufferSrSwPut(RingBuffer16 *rb, void *ptr) -{ - /* buffer is full, wait... */ - while ((unsigned short)(SC_ATOMIC_GET(rb->write) + 1) == SC_ATOMIC_GET(rb->read)) { - /* break out if the engine wants to shutdown */ - if (rb->shutdown != 0) - return -1; - - RingBufferDoWait(rb); - } - - rb->array[SC_ATOMIC_GET(rb->write)] = ptr; - (void) SC_ATOMIC_ADD(rb->write, 1); - -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif - return 0; -} - -/* Multi Reader, Multi Writer, 8 bits */ - -RingBuffer8 *RingBuffer8Init(void) -{ - RingBuffer8 *rb = SCMalloc(sizeof(RingBuffer8)); - if (unlikely(rb == NULL)) { - return NULL; - } - - memset(rb, 0x00, sizeof(RingBuffer8)); - - SC_ATOMIC_INIT(rb->write); - SC_ATOMIC_INIT(rb->read); - - SCSpinInit(&rb->spin, 0); -#ifdef RINGBUFFER_MUTEX_WAIT - SCMutexInit(&rb->wait_mutex, NULL); - SCCondInit(&rb->wait_cond, NULL); -#endif - return rb; -} - -void RingBuffer8Destroy(RingBuffer8 *rb) -{ - if (rb != NULL) { - SC_ATOMIC_DESTROY(rb->write); - SC_ATOMIC_DESTROY(rb->read); - - SCSpinDestroy(&rb->spin); - -#ifdef RINGBUFFER_MUTEX_WAIT - SCMutexDestroy(&rb->wait_mutex); - SCCondDestroy(&rb->wait_cond); -#endif - SCFree(rb); - } -} - -/** - * \brief get the next ptr from the ring buffer - * - * Because we allow for multiple readers we take great care in making sure - * that the threads don't interfere with one another. - * - */ -void *RingBufferMrMw8Get(RingBuffer8 *rb) -{ - void *ptr; - /** local pointer for data races. If SCAtomicCompareAndSwap (CAS) - * fails we increase our local array idx to try the next array member - * until we succeed. Or when the buffer is empty again we jump back - * to the waiting loop. */ - unsigned char readp; - - /* buffer is empty, wait... */ -retry: - while (SC_ATOMIC_GET(rb->write) == SC_ATOMIC_GET(rb->read)) { - /* break out if the engine wants to shutdown */ - if (rb->shutdown != 0) - return NULL; - - RingBuffer8DoWait(rb); - } - - /* atomically update rb->read */ - readp = SC_ATOMIC_GET(rb->read) - 1; - do { - /* with multiple readers we can get in the situation that we exitted - * from the wait loop but the rb is empty again once we get here. */ - if (SC_ATOMIC_GET(rb->write) == SC_ATOMIC_GET(rb->read)) - goto retry; - - readp++; - ptr = rb->array[readp]; - } while (!(SC_ATOMIC_CAS(&rb->read, readp, (readp + 1)))); - - SCLogDebug("ptr %p", ptr); -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif - return ptr; -} - -/** - * \brief put a ptr in the RingBuffer. - * - * As we support multiple writers we need to protect 2 things: - * 1. writing the ptr to the array - * 2. incrementing the rb->write idx - * - * We can't do both at the same time in one atomic operation, so - * we need to (spin) lock it. We do increment rb->write atomically - * after that, so that we don't need to use the lock in our *Get - * function. - * - * \param rb the ringbuffer - * \param ptr ptr to store - * - * \retval 0 ok - * \retval -1 wait loop interrupted because of engine flags - */ -int RingBufferMrMw8Put(RingBuffer8 *rb, void *ptr) -{ - SCLogDebug("ptr %p", ptr); - - /* buffer is full, wait... */ -retry: - while ((unsigned char)(SC_ATOMIC_GET(rb->write) + 1) == SC_ATOMIC_GET(rb->read)) { - /* break out if the engine wants to shutdown */ - if (rb->shutdown != 0) - return -1; - - RingBuffer8DoWait(rb); - } - - /* get our lock */ - SCSpinLock(&rb->spin); - /* if while we got our lock the buffer changed, we need to retry */ - if ((unsigned char)(SC_ATOMIC_GET(rb->write) + 1) == SC_ATOMIC_GET(rb->read)) { - SCSpinUnlock(&rb->spin); - goto retry; - } - - SCLogDebug("rb->write %u, ptr %p", SC_ATOMIC_GET(rb->write), ptr); - - /* update the ring buffer */ - rb->array[SC_ATOMIC_GET(rb->write)] = ptr; - (void) SC_ATOMIC_ADD(rb->write, 1); - SCSpinUnlock(&rb->spin); - SCLogDebug("ptr %p, done", ptr); - -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif - return 0; -} - -/* Multi Reader, Multi Writer, 16 bits */ - -RingBuffer16 *RingBufferInit(void) -{ - RingBuffer16 *rb = SCMalloc(sizeof(RingBuffer16)); - if (unlikely(rb == NULL)) { - return NULL; - } - - memset(rb, 0x00, sizeof(RingBuffer16)); - - SC_ATOMIC_INIT(rb->write); - SC_ATOMIC_INIT(rb->read); - - SCSpinInit(&rb->spin, 0); -#ifdef RINGBUFFER_MUTEX_WAIT - SCMutexInit(&rb->wait_mutex, NULL); - SCCondInit(&rb->wait_cond, NULL); -#endif - return rb; -} - -void RingBufferDestroy(RingBuffer16 *rb) -{ - if (rb != NULL) { - SC_ATOMIC_DESTROY(rb->write); - SC_ATOMIC_DESTROY(rb->read); - - SCSpinDestroy(&rb->spin); - -#ifdef RINGBUFFER_MUTEX_WAIT - SCMutexDestroy(&rb->wait_mutex); - SCCondDestroy(&rb->wait_cond); -#endif - - SCFree(rb); - } -} - -/** - * \brief get the next ptr from the ring buffer - * - * Because we allow for multiple readers we take great care in making sure - * that the threads don't interfere with one another. - * - */ -void *RingBufferMrMwGet(RingBuffer16 *rb) -{ - void *ptr; - /** local pointer for data races. If SCAtomicCompareAndSwap (CAS) - * fails we increase our local array idx to try the next array member - * until we succeed. Or when the buffer is empty again we jump back - * to the waiting loop. */ - unsigned short readp; - - /* buffer is empty, wait... */ -retry: - while (SC_ATOMIC_GET(rb->write) == SC_ATOMIC_GET(rb->read)) { - /* break out if the engine wants to shutdown */ - if (rb->shutdown != 0) - return NULL; - - RingBufferDoWait(rb); - } - - /* atomically update rb->read */ - readp = SC_ATOMIC_GET(rb->read) - 1; - do { - /* with multiple readers we can get in the situation that we exitted - * from the wait loop but the rb is empty again once we get here. */ - if (SC_ATOMIC_GET(rb->write) == SC_ATOMIC_GET(rb->read)) - goto retry; - - readp++; - ptr = rb->array[readp]; - } while (!(SC_ATOMIC_CAS(&rb->read, readp, (readp + 1)))); - - SCLogDebug("ptr %p", ptr); - -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif - return ptr; -} - -/** - * \brief get the next ptr from the ring buffer - * - * Because we allow for multiple readers we take great care in making sure - * that the threads don't interfere with one another. - * - * This version does NOT enter a wait if the buffer is empty loop. - * - * \retval ptr pointer to the data, or NULL if buffer is empty - */ -void *RingBufferMrMwGetNoWait(RingBuffer16 *rb) -{ - void *ptr; - /** local pointer for data races. If SCAtomicCompareAndSwap (CAS) - * fails we increase our local array idx to try the next array member - * until we succeed. Or when the buffer is empty again we jump back - * to the waiting loop. */ - unsigned short readp; - - /* buffer is empty, wait... */ -retry: - while (SC_ATOMIC_GET(rb->write) == SC_ATOMIC_GET(rb->read)) { - /* break if buffer is empty */ - return NULL; - } - - /* atomically update rb->read */ - readp = SC_ATOMIC_GET(rb->read) - 1; - do { - /* with multiple readers we can get in the situation that we exitted - * from the wait loop but the rb is empty again once we get here. */ - if (SC_ATOMIC_GET(rb->write) == SC_ATOMIC_GET(rb->read)) - goto retry; - - readp++; - ptr = rb->array[readp]; - } while (!(SC_ATOMIC_CAS(&rb->read, readp, (readp + 1)))); - - SCLogDebug("ptr %p", ptr); - -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif - return ptr; -} - -/** - * \brief put a ptr in the RingBuffer. - * - * As we support multiple writers we need to protect 2 things: - * 1. writing the ptr to the array - * 2. incrementing the rb->write idx - * - * We can't do both at the same time in one atomic operation, so - * we need to (spin) lock it. We do increment rb->write atomically - * after that, so that we don't need to use the lock in our *Get - * function. - * - * \param rb the ringbuffer - * \param ptr ptr to store - * - * \retval 0 ok - * \retval -1 wait loop interrupted because of engine flags - */ -int RingBufferMrMwPut(RingBuffer16 *rb, void *ptr) -{ - SCLogDebug("ptr %p", ptr); - - /* buffer is full, wait... */ -retry: - while ((unsigned short)(SC_ATOMIC_GET(rb->write) + 1) == SC_ATOMIC_GET(rb->read)) { - /* break out if the engine wants to shutdown */ - if (rb->shutdown != 0) - return -1; - - RingBufferDoWait(rb); - } - - /* get our lock */ - SCSpinLock(&rb->spin); - /* if while we got our lock the buffer changed, we need to retry */ - if ((unsigned short)(SC_ATOMIC_GET(rb->write) + 1) == SC_ATOMIC_GET(rb->read)) { - SCSpinUnlock(&rb->spin); - goto retry; - } - - SCLogDebug("rb->write %u, ptr %p", SC_ATOMIC_GET(rb->write), ptr); - - /* update the ring buffer */ - rb->array[SC_ATOMIC_GET(rb->write)] = ptr; - (void) SC_ATOMIC_ADD(rb->write, 1); - SCSpinUnlock(&rb->spin); - SCLogDebug("ptr %p, done", ptr); - -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondSignal(&rb->wait_cond); -#endif - return 0; -} - -#ifdef UNITTESTS -static int RingBuffer8SrSwInit01 (void) -{ - int result = 0; - - RingBuffer8 *rb = NULL; - - rb = RingBuffer8Init(); - if (rb == NULL) { - printf("rb == NULL: "); - goto end; - } - - int r = SCSpinLock(&rb->spin); - if (r != 0) { - printf("r = %d, expected %d: ", r, 0); - goto end; - } - SCSpinUnlock(&rb->spin); - - if (SC_ATOMIC_GET(rb->read) != 0) { - printf("read %u, expected 0: ", SC_ATOMIC_GET(rb->read)); - goto end; - } - - if (SC_ATOMIC_GET(rb->write) != 0) { - printf("write %u, expected 0: ", SC_ATOMIC_GET(rb->write)); - goto end; - } - - result = 1; -end: - if (rb != NULL) { - RingBuffer8Destroy(rb); - } - return result; -} - -static int RingBuffer8SrSwPut01 (void) -{ - int result = 0; - - RingBuffer8 *rb = NULL; - - rb = RingBuffer8Init(); - if (rb == NULL) { - printf("rb == NULL: "); - goto end; - } - - if (SC_ATOMIC_GET(rb->read) != 0) { - printf("read %u, expected 0: ", SC_ATOMIC_GET(rb->read)); - goto end; - } - - if (SC_ATOMIC_GET(rb->write) != 0) { - printf("write %u, expected 0: ", SC_ATOMIC_GET(rb->write)); - goto end; - } - - void *ptr = &result; - - RingBufferSrSw8Put(rb, ptr); - - if (SC_ATOMIC_GET(rb->read) != 0) { - printf("read %u, expected 0: ", SC_ATOMIC_GET(rb->read)); - goto end; - } - - if (SC_ATOMIC_GET(rb->write) != 1) { - printf("write %u, expected 1: ", SC_ATOMIC_GET(rb->write)); - goto end; - } - - if (rb->array[0] != ptr) { - printf("ptr is %p, expected %p: ", rb->array[0], ptr); - goto end; - } - - result = 1; -end: - if (rb != NULL) { - RingBuffer8Destroy(rb); - } - return result; -} - -static int RingBuffer8SrSwPut02 (void) -{ - int result = 0; - RingBuffer8 *rb = NULL; - - int array[255]; - int cnt = 0; - for (cnt = 0; cnt < 255; cnt++) { - array[cnt] = cnt; - } - - rb = RingBuffer8Init(); - if (rb == NULL) { - printf("rb == NULL: "); - goto end; - } - - for (cnt = 0; cnt < 255; cnt++) { - RingBufferSrSw8Put(rb, (void *)&array[cnt]); - - if (SC_ATOMIC_GET(rb->read) != 0) { - printf("read %u, expected 0: ", SC_ATOMIC_GET(rb->read)); - goto end; - } - - if (SC_ATOMIC_GET(rb->write) != (unsigned char)(cnt+1)) { - printf("write %u, expected %u: ", SC_ATOMIC_GET(rb->write), (unsigned char)(cnt+1)); - goto end; - } - - if (rb->array[cnt] != (void *)&array[cnt]) { - printf("ptr is %p, expected %p: ", rb->array[cnt], (void *)&array[cnt]); - goto end; - } - } - - if (!(RingBuffer8IsFull(rb))) { - printf("ringbuffer should be full, isn't: "); - goto end; - } - - result = 1; -end: - if (rb != NULL) { - RingBuffer8Destroy(rb); - } - return result; -} - -static int RingBuffer8SrSwGet01 (void) -{ - int result = 0; - - RingBuffer8 *rb = NULL; - - rb = RingBuffer8Init(); - if (rb == NULL) { - printf("rb == NULL: "); - goto end; - } - - void *ptr = &result; - - RingBufferSrSw8Put(rb, ptr); - void *ptr2 = RingBufferSrSw8Get(rb); - - if (ptr != ptr2) { - printf("ptr %p != ptr2 %p: ", ptr, ptr2); - goto end; - } - - if (SC_ATOMIC_GET(rb->read) != 1) { - printf("read %u, expected 1: ", SC_ATOMIC_GET(rb->read)); - goto end; - } - - if (SC_ATOMIC_GET(rb->write) != 1) { - printf("write %u, expected 1: ", SC_ATOMIC_GET(rb->write)); - goto end; - } - - result = 1; -end: - if (rb != NULL) { - RingBuffer8Destroy(rb); - } - return result; -} - -static int RingBuffer8SrSwGet02 (void) -{ - int result = 0; - RingBuffer8 *rb = NULL; - - int array[255]; - int cnt = 0; - for (cnt = 0; cnt < 255; cnt++) { - array[cnt] = cnt; - } - - rb = RingBuffer8Init(); - if (rb == NULL) { - printf("rb == NULL: "); - goto end; - } - - for (cnt = 0; cnt < 255; cnt++) { - RingBufferSrSw8Put(rb, (void *)&array[cnt]); - - if (SC_ATOMIC_GET(rb->read) != 0) { - printf("read %u, expected 0: ", SC_ATOMIC_GET(rb->read)); - goto end; - } - - if (SC_ATOMIC_GET(rb->write) != (unsigned char)(cnt+1)) { - printf("write %u, expected %u: ", SC_ATOMIC_GET(rb->write), (unsigned char)(cnt+1)); - goto end; - } - - if (rb->array[cnt] != (void *)&array[cnt]) { - printf("ptr is %p, expected %p: ", rb->array[cnt], (void *)&array[cnt]); - goto end; - } - } - - if (!(RingBuffer8IsFull(rb))) { - printf("ringbuffer should be full, isn't: "); - goto end; - } - - for (cnt = 0; cnt < 255; cnt++) { - void *ptr = RingBufferSrSw8Get(rb); - - if (SC_ATOMIC_GET(rb->read) != (unsigned char)(cnt+1)) { - printf("read %u, expected %u: ", SC_ATOMIC_GET(rb->read), (unsigned char)(cnt+1)); - goto end; - } - - if (SC_ATOMIC_GET(rb->write) != 255) { - printf("write %u, expected %u: ", SC_ATOMIC_GET(rb->write), 255); - goto end; - } - - if (ptr != (void *)&array[cnt]) { - printf("ptr is %p, expected %p: ", ptr, (void *)&array[cnt]); - goto end; - } - } - - if (!(RingBuffer8IsEmpty(rb))) { - printf("ringbuffer should be empty, isn't: "); - goto end; - } - - result = 1; -end: - if (rb != NULL) { - RingBuffer8Destroy(rb); - } - return result; -} - -#endif /* UNITTESTS */ - -void DetectRingBufferRegisterTests(void) -{ -#ifdef UNITTESTS /* UNITTESTS */ - UtRegisterTest("RingBuffer8SrSwInit01", RingBuffer8SrSwInit01); - UtRegisterTest("RingBuffer8SrSwPut01", RingBuffer8SrSwPut01); - UtRegisterTest("RingBuffer8SrSwPut02", RingBuffer8SrSwPut02); - UtRegisterTest("RingBuffer8SrSwGet01", RingBuffer8SrSwGet01); - UtRegisterTest("RingBuffer8SrSwGet02", RingBuffer8SrSwGet02); -#endif /* UNITTESTS */ -} - diff --git a/src/util-ringbuffer.h b/src/util-ringbuffer.h deleted file mode 100644 index c92723308d..0000000000 --- a/src/util-ringbuffer.h +++ /dev/null @@ -1,136 +0,0 @@ -/* Copyright (C) 2007-2010 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 - * Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -/** - * \file - * - * \author Victor Julien - * - * See the .c file for a full explanation. - */ - -#ifndef __UTIL_RINGBUFFER_H__ - -#include "util-atomic.h" -#include "threads.h" - -/** When the ringbuffer is full we have two options, either we spin & sleep - * or we use a pthread condition to wait. - * - * \warning this approach isn't working due to a race condition between the - * time it takes for a thread to enter the condwait and the - * signalling. I've obverved the following case: T1 sees that the - * ringbuffer is empty, so it decides to start the wait condition. - * While it is acquiring the lock and entering the wait, T0 puts a - * number of items in the buffer. For each of these it signals T1. - * However, as that thread isn't in the "wait" mode yet, the signals - * are lost. T0 now is done as well and enters it's own wait - * condition. T1 completes it's "wait" initialization. It waits for - * signals, but T0 won't be able to send them as it's waiting itself. - */ -//#define RINGBUFFER_MUTEX_WAIT - -/** \brief ring buffer api - * - * Ring buffer api for a single writer and a single reader. It uses a - * read and write pointer. Only the read ptr needs atomic updating. - */ - -#define RING_BUFFER_8_SIZE 256 -typedef struct RingBuffer8_ { - SC_ATOMIC_DECLARE(unsigned char, write); /**< idx where we put data */ - SC_ATOMIC_DECLARE(unsigned char, read); /**< idx where we read data */ - uint8_t shutdown; -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondT wait_cond; - SCMutex wait_mutex; -#endif /* RINGBUFFER_MUTEX_WAIT */ - SCSpinlock spin; /**< lock protecting writes for multi writer mode*/ - void *array[RING_BUFFER_8_SIZE]; -} RingBuffer8; - -#define RING_BUFFER_16_SIZE 65536 -typedef struct RingBuffer16_ { - SC_ATOMIC_DECLARE(unsigned short, write); /**< idx where we put data */ - SC_ATOMIC_DECLARE(unsigned short, read); /**< idx where we read data */ - uint8_t shutdown; -#ifdef RINGBUFFER_MUTEX_WAIT - SCCondT wait_cond; - SCMutex wait_mutex; -#endif /* RINGBUFFER_MUTEX_WAIT */ - SCSpinlock spin; /**< lock protecting writes for multi writer mode*/ - void *array[RING_BUFFER_16_SIZE]; -} RingBuffer16; - -RingBuffer8 *RingBuffer8Init(void); -void RingBuffer8Destroy(RingBuffer8 *); -RingBuffer16 *RingBufferInit(void); -void RingBufferDestroy(RingBuffer16 *); - -int RingBufferIsEmpty(RingBuffer16 *); -int RingBufferIsFull(RingBuffer16 *); -uint16_t RingBufferSize(RingBuffer16 *); - -void RingBuffer8Shutdown(RingBuffer8 *); -void RingBufferShutdown(RingBuffer16 *); - -void RingBufferWait(RingBuffer16 *rb); - -/** Single Reader, Single Writer ring buffer, fixed at - * 256 items so we can use unsigned char's that just - * wrap around */ -void *RingBufferSrSw8Get(RingBuffer8 *); -int RingBufferSrSw8Put(RingBuffer8 *, void *); - -/** Multiple Reader, Single Writer ring buffer, fixed at - * 256 items so we can use unsigned char's that just - * wrap around */ -void *RingBufferMrSw8Get(RingBuffer8 *); -int RingBufferMrSw8Put(RingBuffer8 *, void *); - -/** Multiple Reader, Single Writer ring buffer, fixed at - * 65536 items so we can use unsigned shorts that just - * wrap around */ -void *RingBufferMrSwGet(RingBuffer16 *); -int RingBufferMrSwPut(RingBuffer16 *, void *); - -/** Single Reader, Single Writer ring buffer, fixed at - * 65536 items so we can use unsigned shorts that just - * wrap around */ -void *RingBufferSrSwGet(RingBuffer16 *); -int RingBufferSrSwPut(RingBuffer16 *, void *); - -/** Multiple Reader, Multi Writer ring buffer, fixed at - * 256 items so we can use unsigned char's that just - * wrap around */ -void *RingBufferMrMw8Get(RingBuffer8 *); -int RingBufferMrMw8Put(RingBuffer8 *, void *); - -/** Multiple Reader, Multi Writer ring buffer, fixed at - * 65536 items so we can use unsigned char's that just - * wrap around */ -void *RingBufferMrMwGet(RingBuffer16 *); -void *RingBufferMrMwGetNoWait(RingBuffer16 *); -int RingBufferMrMwPut(RingBuffer16 *, void *); - -void *RingBufferSrMw8Get(RingBuffer8 *); -int RingBufferSrMw8Put(RingBuffer8 *, void *); - -void DetectRingBufferRegisterTests(void); - -#endif /* __UTIL_RINGBUFFER_H__ */ -