1 /*
2  * ufdblocks.c - URLfilterDB
3  *
4  * ufdbGuard is copyrighted (C) 2005-2020 by URLfilterDB with all rights reserved.
5  *
6  * Parts of ufdbGuard are based on squidGuard.
7  * This module is NOT based on squidGuard.
8  *
9  * RCS $Id: ufdblocks.c,v 1.6 2020/07/12 07:48:51 root Exp root $
10  */
11 
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15 
16 /* This module is well tested and stable for a long time.
17  * For maximum performance _FORTIFY_SOURCE is undefined.
18  */
19 #undef _FORTIFY_SOURCE
20 
21 #if (__GNUC__ > 4)  ||  (__GNUC__ == 4  &&  __GNUC_MINOR__ >= 4)
22 #pragma GCC push_options
23 #pragma GCC optimize ("O3")
24 #endif
25 
26 #include "ufdb.h"
27 #include "ufdblocks.h"
28 
29 #if UFDB_SPINLOCK_SUPPORT
30 #include <immintrin.h>   // defines _mm_pause()
31 #endif
32 
33 #if UFDB_PTHREAD_SUPPORT
34 #include <pthread.h>
35 #endif
36 
37 #if UFDB_DPDK_SUPPORT
38 #include "rte_spinlock.h"
39 #endif
40 
41 #if UFDB_CVMX_SPINLOCK_SUPPORT
42 #include <cvmx-spinlock.h>
43 #endif
44 
45 
ufdb_mutex_init(ufdb_mutex * m)46 void  ufdb_mutex_init( ufdb_mutex * m )
47 {
48 #if UFDB_PTHREAD_SUPPORT
49    pthread_mutex_init( (pthread_mutex_t*) m, NULL );
50 #elif UFDB_DPDK_SUPPORT
51    rte_spinlock_init( (rte_spinlock_t*) m );
52 #elif UFDB_SPINLOCK_SUPPORT
53    *m = 0;
54 #elif UFDB_CVMX_SPINLOCK_SUPPORT
55    cvmx_spinlock_init( (cvmx_spinlock_t*) m );
56 #else
57    *m = 0;
58 #endif
59 }
60 
61 
ufdb_mutex_lock(ufdb_mutex * m)62 int ufdb_mutex_lock( ufdb_mutex * m )
63 {
64 #if UFDB_PTHREAD_SUPPORT
65    return pthread_mutex_lock( (pthread_mutex_t*) m );
66 #elif UFDB_DPDK_SUPPORT
67    rte_spinlock_lock( (rte_spinlock_t*) m );
68    return 0;
69 #elif UFDB_SPINLOCK_SUPPORT
70    int32_t volatile * slp = (int32_t*) m;
71    // spin read-only until a cmpxchg might succeed
72    while(!__sync_bool_compare_and_swap( slp, 0, 1))
73    {
74       while (*slp)
75          _mm_pause();   // micro-pause to make unlocking easier
76    }
77    return 0;
78 #elif UFDB_CVMX_SPINLOCK_SUPPORT
79    cvmx_spinlock_lock( (cvmx_spinlock_t*) m );
80    return 0;
81 #else
82    return ENOSYS;       // futex not implemented
83 #endif
84 }
85 
86 
ufdb_mutex_trylock(ufdb_mutex * m)87 int ufdb_mutex_trylock( ufdb_mutex * m )
88 {
89 #if UFDB_PTHREAD_SUPPORT
90    return pthread_mutex_trylock( (pthread_mutex_t*) m );
91 #elif UFDB_DPDK_SUPPORT
92    int rv = rte_spinlock_trylock( (rte_spinlock_t*) m );
93    return !rv;
94 #elif UFDB_SPINLOCK_SUPPORT
95    int32_t volatile * slp = (int32_t*) m;
96    int rv = __sync_bool_compare_and_swap( slp, 0, 1 );
97    return !rv;
98 #elif UFDB_CVMX_SPINLOCK_SUPPORT
99    return cvmx_spinlock_trylock( (cvmx_spinlock_t*) m );
100 #else
101    return ENOSYS;       // futex not implemented
102 #endif
103 }
104 
105 
ufdb_mutex_unlock(ufdb_mutex * m)106 int ufdb_mutex_unlock( ufdb_mutex * m )
107 {
108 #if UFDB_PTHREAD_SUPPORT
109    return pthread_mutex_unlock( (pthread_mutex_t*) m );
110 #elif UFDB_DPDK_SUPPORT
111    rte_spinlock_unlock( (rte_spinlock_t*) m );
112    return 0;
113 #elif UFDB_SPINLOCK_SUPPORT
114    __asm__ volatile("": : :"memory");  // soft memory barrier for the compiler
115    *m = 0;
116    return 0;
117 #elif UFDB_CVMX_SPINLOCK_SUPPORT
118    cvmx_spinlock_unlock( (cvmx_spinlock_t*) m );
119    return 0;
120 #else
121    return ENOSYS;       // futex not implemented
122 #endif
123 }
124 
125 
126 #ifdef __cplusplus
127 }
128 #endif
129