tlds
Transactional Operations for Linked Data Structures
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
BitFilter.hpp
Go to the documentation of this file.
1 /**
2  * Copyright (C) 2011
3  * University of Rochester Department of Computer Science
4  * and
5  * Lehigh University Department of Computer Science and Engineering
6  *
7  * License: Modified BSD
8  * Please see the file LICENSE.RSTM for licensing information
9  */
10 
11 /**
12  * This file implements a simple bit filter datatype, with SSE2 optimizations.
13  * The type is templated by size, but has only been tested at a size of 1024
14  * bits.
15  */
16 
17 #ifndef BITFILTER_HPP__
18 #define BITFILTER_HPP__
19 
20 #include <stm/config.h>
21 #include <stdint.h>
22 
23 #if defined(STM_USE_SSE)
24 #include <xmmintrin.h>
25 #define FILTER_ALLOC(x) _mm_malloc((x), 16)
26 #else
27 #define FILTER_ALLOC(x) malloc((x))
28 #endif
29 
30 namespace stm
31 {
32  /**
33  * This is a simple Bit vector class, with SSE2 optimizations
34  */
35  template <uint32_t BITS>
36  class BitFilter
37  {
38  /*** CONSTS TO ALLOW ACCESS VIA WORDS/SSE REGISTERS */
39 #ifdef STM_USE_SSE
40  static const uint32_t VEC_SIZE = 8 * sizeof(__m128i);
41  static const uint32_t VEC_BLOCKS = BITS / VEC_SIZE;
42 #endif
43  static const uint32_t WORD_SIZE = 8 * sizeof(uintptr_t);
44  static const uint32_t WORD_BLOCKS = BITS / WORD_SIZE;
45 
46  /**
47  * index this as an array of words or an array of vectors
48  */
49  union {
50 #ifdef STM_USE_SSE
51  mutable __m128i vec_filter[VEC_BLOCKS];
52 #endif
54  } TM_ALIGN(16);
55 
56  /*** simple hash function for now */
58  static uint32_t hash(const void* const key)
59  {
60  return (((uintptr_t)key) >> 3) % BITS;
61  }
62 
63  public:
64 
65  /*** constructor just clears the filter */
66  BitFilter() { clear(); }
67 
68  /*** simple bit set function */
69  TM_INLINE
70  void add(const void* const val) volatile
71  {
72  const uint32_t index = hash(val);
73  const uint32_t block = index / WORD_SIZE;
74  const uint32_t offset = index % WORD_SIZE;
75  word_filter[block] |= (1u << offset);
76  }
77 
78  /*** simple bit set function, with strong ordering guarantees */
80  void atomic_add(const void* const val) volatile
81  {
82  const uint32_t index = hash(val);
83  const uint32_t block = index / WORD_SIZE;
84  const uint32_t offset = index % WORD_SIZE;
85 #if defined(STM_CPU_X86)
86  atomicswapptr(&word_filter[block],
87  word_filter[block] | (1u << offset));
88 #else
89  word_filter[block] |= (1u << offset);
90  WBR;
91 #endif
92  }
93 
94  /*** simple lookup */
96  bool lookup(const void* const val) const volatile
97  {
98  const uint32_t index = hash(val);
99  const uint32_t block = index / WORD_SIZE;
100  const uint32_t offset = index % WORD_SIZE;
101 
102  return word_filter[block] & (1u << offset);
103  }
104 
105  /*** simple union */
106  TM_INLINE
107  void unionwith(const BitFilter<BITS>& rhs)
108  {
109 #ifdef STM_USE_SSE
110  for (uint32_t i = 0; i < VEC_BLOCKS; ++i)
111  vec_filter[i] = _mm_or_si128(vec_filter[i], rhs.vec_filter[i]);
112 #else
113  for (uint32_t i = 0; i < WORD_BLOCKS; ++i)
114  word_filter[i] |= rhs.word_filter[i];
115 #endif
116  }
117 
118  /*** a fast clearing function */
119  TM_INLINE
120  void clear() volatile
121  {
122 #ifdef STM_USE_SSE
123  // This loop gets automatically unrolled for BITS = 1024 by gcc-4.3.3
124  const __m128i zero = _mm_setzero_si128();
125  for (uint32_t i = 0; i < VEC_BLOCKS; ++i)
126  vec_filter[i] = zero;
127 #else
128  for (uint32_t i = 0; i < WORD_BLOCKS; ++i)
129  word_filter[i] = 0;
130 #endif
131  }
132 
133  /*** a bitwise copy method */
134  TM_INLINE
135  void fastcopy(const volatile BitFilter<BITS>* rhs) volatile
136  {
137 #ifdef STM_USE_SSE
138  for (uint32_t i = 0; i < VEC_BLOCKS; ++i)
139  vec_filter[i] = const_cast<BitFilter<BITS>*>(rhs)->vec_filter[i];
140 #else
141  for (uint32_t i = 0; i < WORD_BLOCKS; ++i)
142  word_filter[i] = rhs->word_filter[i];
143 #endif
144  }
145 
146  /*** intersect two vectors */
147  NOINLINE bool intersect(const BitFilter<BITS>* rhs) const volatile
148  {
149 #ifdef STM_USE_SSE
150  // There is no clean way to compare an __m128i to zero, so we have
151  // to union it with an array of uint64_ts, and then we can look at
152  // the vector 64 bits at a time
153  union {
154  __m128i v;
155  uint64_t i[2];
156  } tmp;
157  tmp.v = _mm_setzero_si128();
158  for (uint32_t i = 0; i < VEC_BLOCKS; ++i) {
159  __m128i intersect =
160  _mm_and_si128(const_cast<BitFilter<BITS>*>(this)->
161  vec_filter[i],
162  rhs->vec_filter[i]);
163  tmp.v = _mm_or_si128(tmp.v, intersect);
164  }
165 
166  return tmp.i[0]|tmp.i[1];
167 #else
168  for (uint32_t i = 0; i < WORD_BLOCKS; ++i)
169  if (word_filter[i] & rhs->word_filter[i])
170  return true;
171  return false;
172 #endif
173  }
174  }; // class stm::BitFilter
175 
176 } // namespace stm
177 
178 #endif // BITFILTER_HPP__
static const uint32_t WORD_SIZE
Definition: BitFilter.hpp:43
#define NOINLINE
Definition: platform.hpp:48
static const uint32_t WORD_BLOCKS
Definition: BitFilter.hpp:44
Definition: stm_fraser.c:61
ALWAYS_INLINE void atomic_add(const void *const val) volatile
Definition: BitFilter.hpp:80
#define ALWAYS_INLINE
Definition: platform.hpp:49
union stm::BitFilter::@1 TM_ALIGN(16)
TM_INLINE void add(const void *const val) volatile
Definition: BitFilter.hpp:70
NOINLINE bool intersect(const BitFilter< BITS > *rhs) const volatile
Definition: BitFilter.hpp:147
ALWAYS_INLINE bool lookup(const void *const val) const volatile
Definition: BitFilter.hpp:96
#define TM_INLINE
Definition: platform.hpp:77
#define BITS(x, k, j)
Definition: alg_radix_smp.c:76
uintptr_t word_filter[WORD_BLOCKS]
Definition: BitFilter.hpp:53
Definition: memory.c:88
BitFilter()
Definition: BitFilter.hpp:66
static ALWAYS_INLINE uint32_t hash(const void *const key)
Definition: BitFilter.hpp:58
Definition: BitFilter.hpp:36
TM_INLINE void fastcopy(const volatile BitFilter< BITS > *rhs) volatile
Definition: BitFilter.hpp:135
TM_INLINE void unionwith(const BitFilter< BITS > &rhs)
Definition: BitFilter.hpp:107
TM_INLINE void clear() volatile
Definition: BitFilter.hpp:120