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; }
/** * \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; }
void FlowHashDebugPrint(uint32_t ts) { #ifdef FLOW_DEBUG_STATS if (flow_hash_count_fp == NULL) return; float avg_all = 0, avg_tcp = 0, avg_udp = 0, avg_icmp = 0, avg_other = 0; SCSpinLock(&flow_hash_count_lock); if (flow_hash_loop_count[FLOW_DEBUG_STATS_PROTO_ALL] != 0) avg_all = (float)(flow_hash_loop_count[FLOW_DEBUG_STATS_PROTO_ALL]/(float)(flow_hash_count[FLOW_DEBUG_STATS_PROTO_ALL])); if (flow_hash_loop_count[FLOW_DEBUG_STATS_PROTO_TCP] != 0) avg_tcp = (float)(flow_hash_loop_count[FLOW_DEBUG_STATS_PROTO_TCP]/(float)(flow_hash_count[FLOW_DEBUG_STATS_PROTO_TCP])); if (flow_hash_loop_count[FLOW_DEBUG_STATS_PROTO_UDP] != 0) avg_udp = (float)(flow_hash_loop_count[FLOW_DEBUG_STATS_PROTO_UDP]/(float)(flow_hash_count[FLOW_DEBUG_STATS_PROTO_UDP])); if (flow_hash_loop_count[FLOW_DEBUG_STATS_PROTO_ICMP] != 0) avg_icmp= (float)(flow_hash_loop_count[FLOW_DEBUG_STATS_PROTO_ICMP]/(float)(flow_hash_count[FLOW_DEBUG_STATS_PROTO_ICMP])); if (flow_hash_loop_count[FLOW_DEBUG_STATS_PROTO_OTHER] != 0) avg_other= (float)(flow_hash_loop_count[FLOW_DEBUG_STATS_PROTO_OTHER]/(float)(flow_hash_count[FLOW_DEBUG_STATS_PROTO_OTHER])); fprintf(flow_hash_count_fp, "%"PRIu32",%02.3f,%02.3f,%02.3f,%02.3f,%02.3f\n", ts, avg_all, avg_tcp, avg_udp, avg_icmp, avg_other); fflush(flow_hash_count_fp); memset(&flow_hash_count, 0, sizeof(flow_hash_count)); memset(&flow_hash_loop_count, 0, sizeof(flow_hash_loop_count)); SCSpinUnlock(&flow_hash_count_lock); #endif }
void TimeGet(struct timeval *tv) { if (tv == NULL) return; if (live == TRUE) { gettimeofday(tv, NULL); } else { #ifdef UNITTESTS if (unlikely(RunmodeIsUnittests())) { SCSpinLock(¤t_time_spinlock); tv->tv_sec = current_time.tv_sec; tv->tv_usec = current_time.tv_usec; SCSpinUnlock(¤t_time_spinlock); } else { #endif TmreadsGetMinimalTimestamp(tv); #ifdef UNITTESTS } #endif } SCLogDebug("time we got is %" PRIuMAX " sec, %" PRIuMAX " usec", (uintmax_t)tv->tv_sec, (uintmax_t)tv->tv_usec); }
/** * \brief Test Spinlock Macros * * Valgrind's DRD tool (valgrind-3.5.0-Debian) reports: * * ==31156== Recursive locking not allowed: mutex 0x7fefff97c, recursion count 1, owner 1. * ==31156== at 0x4C2C77E: pthread_spin_trylock (drd_pthread_intercepts.c:829) * ==31156== by 0x40EB3E: ThreadMacrosTest02Spinlocks (threads.c:40) * ==31156== by 0x532E8A: UtRunTests (util-unittest.c:182) * ==31156== by 0x4065C3: main (suricata.c:789) * * To me this is a false positve, as the whole point of "trylock" is to see * if a spinlock is actually locked. * */ int ThreadMacrosTest02Spinlocks(void) { SCSpinlock mut; int r = 0; r |= SCSpinInit(&mut, 0); r |= SCSpinLock(&mut); #ifndef __OpenBSD__ r |= (SCSpinTrylock(&mut) == EBUSY)? 0 : 1; #else r |= (SCSpinTrylock(&mut) == EDEADLK)? 0 : 1; #endif r |= SCSpinUnlock(&mut); r |= SCSpinDestroy(&mut); return (r == 0)? 1 : 0; }
void TimeSet(struct timeval *tv) { if (live == TRUE) return; if (tv == NULL) return; SCSpinLock(¤t_time_spinlock); current_time.tv_sec = tv->tv_sec; current_time.tv_usec = tv->tv_usec; SCLogDebug("time set to %" PRIuMAX " sec, %" PRIuMAX " usec", (uintmax_t)current_time.tv_sec, (uintmax_t)current_time.tv_usec); SCSpinUnlock(¤t_time_spinlock); }
static int ProfilingGenericTicksTest01(void) { #define TEST_RUNS 1024 uint64_t ticks_start = 0; uint64_t ticks_end = 0; void *ptr[TEST_RUNS]; int i; ticks_start = UtilCpuGetTicks(); for (i = 0; i < TEST_RUNS; i++) { ptr[i] = SCMalloc(1024); } ticks_end = UtilCpuGetTicks(); printf("malloc(1024) %"PRIu64"\n", (ticks_end - ticks_start)/TEST_RUNS); ticks_start = UtilCpuGetTicks(); for (i = 0; i < TEST_RUNS; i++) { SCFree(ptr[i]); } ticks_end = UtilCpuGetTicks(); printf("SCFree(1024) %"PRIu64"\n", (ticks_end - ticks_start)/TEST_RUNS); SCMutex m[TEST_RUNS]; ticks_start = UtilCpuGetTicks(); for (i = 0; i < TEST_RUNS; i++) { SCMutexInit(&m[i], NULL); } ticks_end = UtilCpuGetTicks(); printf("SCMutexInit() %"PRIu64"\n", (ticks_end - ticks_start)/TEST_RUNS); ticks_start = UtilCpuGetTicks(); for (i = 0; i < TEST_RUNS; i++) { SCMutexLock(&m[i]); } ticks_end = UtilCpuGetTicks(); printf("SCMutexLock() %"PRIu64"\n", (ticks_end - ticks_start)/TEST_RUNS); ticks_start = UtilCpuGetTicks(); for (i = 0; i < TEST_RUNS; i++) { SCMutexUnlock(&m[i]); } ticks_end = UtilCpuGetTicks(); printf("SCMutexUnlock() %"PRIu64"\n", (ticks_end - ticks_start)/TEST_RUNS); ticks_start = UtilCpuGetTicks(); for (i = 0; i < TEST_RUNS; i++) { SCMutexDestroy(&m[i]); } ticks_end = UtilCpuGetTicks(); printf("SCMutexDestroy() %"PRIu64"\n", (ticks_end - ticks_start)/TEST_RUNS); SCSpinlock s[TEST_RUNS]; ticks_start = UtilCpuGetTicks(); for (i = 0; i < TEST_RUNS; i++) { SCSpinInit(&s[i], 0); } ticks_end = UtilCpuGetTicks(); printf("SCSpinInit() %"PRIu64"\n", (ticks_end - ticks_start)/TEST_RUNS); ticks_start = UtilCpuGetTicks(); for (i = 0; i < TEST_RUNS; i++) { SCSpinLock(&s[i]); } ticks_end = UtilCpuGetTicks(); printf("SCSpinLock() %"PRIu64"\n", (ticks_end - ticks_start)/TEST_RUNS); ticks_start = UtilCpuGetTicks(); for (i = 0; i < TEST_RUNS; i++) { SCSpinUnlock(&s[i]); } ticks_end = UtilCpuGetTicks(); printf("SCSpinUnlock() %"PRIu64"\n", (ticks_end - ticks_start)/TEST_RUNS); ticks_start = UtilCpuGetTicks(); for (i = 0; i < TEST_RUNS; i++) { SCSpinDestroy(&s[i]); } ticks_end = UtilCpuGetTicks(); printf("SCSpinDestroy() %"PRIu64"\n", (ticks_end - ticks_start)/TEST_RUNS); SC_ATOMIC_DECL_AND_INIT(unsigned int, test); ticks_start = UtilCpuGetTicks(); for (i = 0; i < TEST_RUNS; i++) { (void) SC_ATOMIC_ADD(test,1); } ticks_end = UtilCpuGetTicks(); printf("SC_ATOMIC_ADD %"PRIu64"\n", (ticks_end - ticks_start)/TEST_RUNS); ticks_start = UtilCpuGetTicks(); for (i = 0; i < TEST_RUNS; i++) { SC_ATOMIC_CAS(&test,i,i+1); } ticks_end = UtilCpuGetTicks(); printf("SC_ATOMIC_CAS %"PRIu64"\n", (ticks_end - ticks_start)/TEST_RUNS); return 1; }