MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
lf.h
1 /* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 #ifndef _lf_h
17 #define _lf_h
18 
19 #include <my_atomic.h>
20 
21 C_MODE_START
22 
23 /*
24  Helpers to define both func() and _func(), where
25  func() is a _func() protected by my_atomic_rwlock_wrlock()
26 */
27 
28 #define lock_wrap(f, t, proto_args, args, lock) \
29 t _ ## f proto_args; \
30 static inline t f proto_args \
31 { \
32  t ret; \
33  my_atomic_rwlock_wrlock(lock); \
34  ret= _ ## f args; \
35  my_atomic_rwlock_wrunlock(lock); \
36  return ret; \
37 }
38 
39 #define lock_wrap_void(f, proto_args, args, lock) \
40 void _ ## f proto_args; \
41 static inline void f proto_args \
42 { \
43  my_atomic_rwlock_wrlock(lock); \
44  _ ## f args; \
45  my_atomic_rwlock_wrunlock(lock); \
46 }
47 
48 #define nolock_wrap(f, t, proto_args, args) \
49 t _ ## f proto_args; \
50 static inline t f proto_args \
51 { \
52  return _ ## f args; \
53 }
54 
55 #define nolock_wrap_void(f, proto_args, args) \
56 void _ ## f proto_args; \
57 static inline void f proto_args \
58 { \
59  _ ## f args; \
60 }
61 
62 /*
63  wait-free dynamic array, see lf_dynarray.c
64 
65  4 levels of 256 elements each mean 4311810304 elements in an array - it
66  should be enough for a while
67 */
68 #define LF_DYNARRAY_LEVEL_LENGTH 256
69 #define LF_DYNARRAY_LEVELS 4
70 
71 typedef struct {
72  void * volatile level[LF_DYNARRAY_LEVELS];
73  uint size_of_element;
74  my_atomic_rwlock_t lock;
75 } LF_DYNARRAY;
76 
77 typedef int (*lf_dynarray_func)(void *, void *);
78 
79 void lf_dynarray_init(LF_DYNARRAY *array, uint element_size);
80 void lf_dynarray_destroy(LF_DYNARRAY *array);
81 
82 nolock_wrap(lf_dynarray_value, void *,
83  (LF_DYNARRAY *array, uint idx),
84  (array, idx))
85 lock_wrap(lf_dynarray_lvalue, void *,
86  (LF_DYNARRAY *array, uint idx),
87  (array, idx),
88  &array->lock)
89 nolock_wrap(lf_dynarray_iterate, int,
90  (LF_DYNARRAY *array, lf_dynarray_func func, void *arg),
91  (array, func, arg))
92 
93 /*
94  pin manager for memory allocator, lf_alloc-pin.c
95 */
96 
97 #define LF_PINBOX_PINS 4
98 #define LF_PURGATORY_SIZE 10
99 
100 typedef void lf_pinbox_free_func(void *, void *, void*);
101 
102 typedef struct {
103  LF_DYNARRAY pinarray;
104  lf_pinbox_free_func *free_func;
105  void *free_func_arg;
106  uint free_ptr_offset;
107  uint32 volatile pinstack_top_ver; /* this is a versioned pointer */
108  uint32 volatile pins_in_array; /* number of elements in array */
109 } LF_PINBOX;
110 
111 typedef struct {
112  void * volatile pin[LF_PINBOX_PINS];
113  LF_PINBOX *pinbox;
114  void **stack_ends_here;
115  void *purgatory;
116  uint32 purgatory_count;
117  uint32 volatile link;
118 /* we want sizeof(LF_PINS) to be 64 to avoid false sharing */
119 #if SIZEOF_INT*2+SIZEOF_CHARP*(LF_PINBOX_PINS+3) != 64
120  char pad[64-sizeof(uint32)*2-sizeof(void*)*(LF_PINBOX_PINS+3)];
121 #endif
122 } LF_PINS;
123 
124 /*
125  shortcut macros to do an atomic_wrlock on a structure that uses pins
126  (e.g. lf_hash).
127 */
128 #define lf_rwlock_by_pins(PINS) \
129  my_atomic_rwlock_wrlock(&(PINS)->pinbox->pinarray.lock)
130 #define lf_rwunlock_by_pins(PINS) \
131  my_atomic_rwlock_wrunlock(&(PINS)->pinbox->pinarray.lock)
132 
133 /*
134  compile-time assert, to require "no less than N" pins
135  it's enough if it'll fail on at least one compiler, so
136  we'll enable it on GCC only, which supports zero-length arrays.
137 */
138 #if defined(__GNUC__) && defined(MY_LF_EXTRA_DEBUG)
139 #define LF_REQUIRE_PINS(N) \
140  static const char require_pins[LF_PINBOX_PINS-N] \
141  __attribute__ ((unused)); \
142  static const int LF_NUM_PINS_IN_THIS_FILE= N;
143 #define _lf_pin(PINS, PIN, ADDR) \
144  ( \
145  assert(PIN < LF_NUM_PINS_IN_THIS_FILE), \
146  my_atomic_storeptr(&(PINS)->pin[PIN], (ADDR)) \
147  )
148 #else
149 #define LF_REQUIRE_PINS(N)
150 #define _lf_pin(PINS, PIN, ADDR) my_atomic_storeptr(&(PINS)->pin[PIN], (ADDR))
151 #endif
152 
153 #define _lf_unpin(PINS, PIN) _lf_pin(PINS, PIN, NULL)
154 #define lf_pin(PINS, PIN, ADDR) \
155  do { \
156  lf_rwlock_by_pins(PINS); \
157  _lf_pin(PINS, PIN, ADDR); \
158  lf_rwunlock_by_pins(PINS); \
159  } while (0)
160 #define lf_unpin(PINS, PIN) lf_pin(PINS, PIN, NULL)
161 #define _lf_assert_pin(PINS, PIN) assert((PINS)->pin[PIN] != 0)
162 #define _lf_assert_unpin(PINS, PIN) assert((PINS)->pin[PIN] == 0)
163 
164 void lf_pinbox_init(LF_PINBOX *pinbox, uint free_ptr_offset,
165  lf_pinbox_free_func *free_func, void * free_func_arg);
166 void lf_pinbox_destroy(LF_PINBOX *pinbox);
167 
168 lock_wrap(lf_pinbox_get_pins, LF_PINS *,
169  (LF_PINBOX *pinbox),
170  (pinbox),
171  &pinbox->pinarray.lock)
172 lock_wrap_void(lf_pinbox_put_pins,
173  (LF_PINS *pins),
174  (pins),
175  &pins->pinbox->pinarray.lock)
176 lock_wrap_void(lf_pinbox_free,
177  (LF_PINS *pins, void *addr),
178  (pins, addr),
179  &pins->pinbox->pinarray.lock)
180 
181 /*
182  memory allocator, lf_alloc-pin.c
183 */
184 
185 typedef struct st_lf_allocator {
186  LF_PINBOX pinbox;
187  uchar * volatile top;
188  uint element_size;
189  uint32 volatile mallocs;
190  void (*constructor)(uchar *); /* called, when an object is malloc()'ed */
191  void (*destructor)(uchar *); /* called, when an object is free()'d */
192 } LF_ALLOCATOR;
193 
194 void lf_alloc_init(LF_ALLOCATOR *allocator, uint size, uint free_ptr_offset);
195 void lf_alloc_destroy(LF_ALLOCATOR *allocator);
196 uint lf_alloc_pool_count(LF_ALLOCATOR *allocator);
197 /*
198  shortcut macros to access underlying pinbox functions from an LF_ALLOCATOR
199  see _lf_pinbox_get_pins() and _lf_pinbox_put_pins()
200 */
201 #define _lf_alloc_free(PINS, PTR) _lf_pinbox_free((PINS), (PTR))
202 #define lf_alloc_free(PINS, PTR) lf_pinbox_free((PINS), (PTR))
203 #define _lf_alloc_get_pins(A) _lf_pinbox_get_pins(&(A)->pinbox)
204 #define lf_alloc_get_pins(A) lf_pinbox_get_pins(&(A)->pinbox)
205 #define _lf_alloc_put_pins(PINS) _lf_pinbox_put_pins(PINS)
206 #define lf_alloc_put_pins(PINS) lf_pinbox_put_pins(PINS)
207 #define lf_alloc_direct_free(ALLOC, ADDR) my_free((ADDR))
208 
209 lock_wrap(lf_alloc_new, void *,
210  (LF_PINS *pins),
211  (pins),
212  &pins->pinbox->pinarray.lock)
213 
214 C_MODE_END
215 
216 /*
217  extendible hash, lf_hash.c
218 */
219 #include <hash.h>
220 
221 C_MODE_START
222 
223 #define LF_HASH_UNIQUE 1
224 
225 /* lf_hash overhead per element (that is, sizeof(LF_SLIST) */
226 extern const int LF_HASH_OVERHEAD;
227 
228 typedef struct {
229  LF_DYNARRAY array; /* hash itself */
230  LF_ALLOCATOR alloc; /* allocator for elements */
231  my_hash_get_key get_key; /* see HASH */
232  CHARSET_INFO *charset; /* see HASH */
233  uint key_offset, key_length; /* see HASH */
234  uint element_size; /* size of memcpy'ed area on insert */
235  uint flags; /* LF_HASH_UNIQUE, etc */
236  int32 volatile size; /* size of array */
237  int32 volatile count; /* number of elements in the hash */
238 } LF_HASH;
239 
240 void lf_hash_init(LF_HASH *hash, uint element_size, uint flags,
241  uint key_offset, uint key_length, my_hash_get_key get_key,
242  CHARSET_INFO *charset);
243 void lf_hash_destroy(LF_HASH *hash);
244 int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data);
245 void *lf_hash_search(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen);
246 int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen);
247 /*
248  shortcut macros to access underlying pinbox functions from an LF_HASH
249  see _lf_pinbox_get_pins() and _lf_pinbox_put_pins()
250 */
251 #define _lf_hash_get_pins(HASH) _lf_alloc_get_pins(&(HASH)->alloc)
252 #define lf_hash_get_pins(HASH) lf_alloc_get_pins(&(HASH)->alloc)
253 #define _lf_hash_put_pins(PINS) _lf_pinbox_put_pins(PINS)
254 #define lf_hash_put_pins(PINS) lf_pinbox_put_pins(PINS)
255 #define lf_hash_search_unpin(PINS) lf_unpin((PINS), 2)
256 /*
257  cleanup
258 */
259 
260 #undef lock_wrap_void
261 #undef lock_wrap
262 #undef nolock_wrap_void
263 #undef nolock_wrap
264 
265 C_MODE_END
266 
267 #endif
268