MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mysys_lf-t.cc
Go to the documentation of this file.
1 /* Copyright (c) 2008, 2012, 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 
22 // First include (the generated) my_config.h, to get correct platform defines.
23 #include "my_config.h"
24 #include <gtest/gtest.h>
25 
26 #include <my_global.h>
27 #include <my_sys.h>
28 #include <my_atomic.h>
29 
30 
31 namespace mysys_lf_unittest {
32 
33 #include "thr_template.cc"
34 
35 #include <lf.h>
36 
37 int32 inserts= 0, N;
38 LF_ALLOCATOR lf_allocator;
39 LF_HASH lf_hash;
40 
41 int with_my_thread_init=0;
42 
43 /*
44  pin allocator - alloc and release an element in a loop
45 */
46 pthread_handler_t test_lf_pinbox(void *arg)
47 {
48  int m= *(int *)arg;
49  LF_PINS *pins;
50 
51  if (with_my_thread_init)
52  my_thread_init();
53 
54  pins= lf_pinbox_get_pins(&lf_allocator.pinbox);
55 
56  for (; m ; m--)
57  {
58  lf_pinbox_put_pins(pins);
59  pins= lf_pinbox_get_pins(&lf_allocator.pinbox);
60  }
61  lf_pinbox_put_pins(pins);
62  mysql_mutex_lock(&mutex);
63  if (!--running_threads) mysql_cond_signal(&cond);
64  mysql_mutex_unlock(&mutex);
65 
66  if (with_my_thread_init)
67  my_thread_end();
68 
69  return 0;
70 }
71 
72 /*
73  thread local data area, allocated using lf_alloc.
74  union is required to enforce the minimum required element size (sizeof(ptr))
75 */
76 typedef union {
77  int32 data;
78  void *not_used;
79 } TLA;
80 
81 pthread_handler_t test_lf_alloc(void *arg)
82 {
83  int m= (*(int *)arg)/2;
84  int32 x,y= 0;
85  LF_PINS *pins;
86 
87  if (with_my_thread_init)
88  my_thread_init();
89 
90  pins= lf_alloc_get_pins(&lf_allocator);
91 
92  for (x= ((int)(intptr)(&m)); m ; m--)
93  {
94  TLA *node1, *node2;
95  x= (x*m+0x87654321) & INT_MAX32;
96  node1= (TLA *)lf_alloc_new(pins);
97  node1->data= x;
98  y+= node1->data;
99  node1->data= 0;
100  node2= (TLA *)lf_alloc_new(pins);
101  node2->data= x;
102  y-= node2->data;
103  node2->data= 0;
104  lf_alloc_free(pins, node1);
105  lf_alloc_free(pins, node2);
106  }
107  lf_alloc_put_pins(pins);
108  mysql_mutex_lock(&mutex);
109  bad+= y;
110 
111  if (--N == 0)
112  {
113 #ifdef MY_LF_EXTRA_DEBUG
114  bad|= lf_allocator.mallocs - lf_alloc_pool_count(&lf_allocator);
115 #endif
116  }
117  if (!--running_threads) mysql_cond_signal(&cond);
118  mysql_mutex_unlock(&mutex);
119 
120  if (with_my_thread_init)
121  my_thread_end();
122  return 0;
123 }
124 
125 const int N_TLH= 1000;
126 pthread_handler_t test_lf_hash(void *arg)
127 {
128  int m= (*(int *)arg)/(2*N_TLH);
129  int32 x,y,z,sum= 0, ins= 0;
130  LF_PINS *pins;
131 
132  if (with_my_thread_init)
133  my_thread_init();
134 
135  pins= lf_hash_get_pins(&lf_hash);
136 
137  for (x= ((int)(intptr)(&m)); m ; m--)
138  {
139  int i;
140  y= x;
141  for (i= 0; i < N_TLH; i++)
142  {
143  x= (x*(m+i)+0x87654321) & INT_MAX32;
144  z= (x<0) ? -x : x;
145  if (lf_hash_insert(&lf_hash, pins, &z))
146  {
147  sum+= z;
148  ins++;
149  }
150  }
151  for (i= 0; i < N_TLH; i++)
152  {
153  y= (y*(m+i)+0x87654321) & INT_MAX32;
154  z= (y<0) ? -y : y;
155  if (lf_hash_delete(&lf_hash, pins, (uchar *)&z, sizeof(z)))
156  sum-= z;
157  }
158  }
159  lf_hash_put_pins(pins);
160  mysql_mutex_lock(&mutex);
161  bad+= sum;
162  inserts+= ins;
163 
164  if (--N == 0)
165  {
166  bad|= lf_hash.count;
167  }
168  if (!--running_threads) mysql_cond_signal(&cond);
169  mysql_mutex_unlock(&mutex);
170  if (with_my_thread_init)
171  my_thread_end();
172  return 0;
173 }
174 
175 
176 void do_tests()
177 {
178  lf_alloc_init(&lf_allocator, sizeof(TLA), offsetof(TLA, not_used));
179  lf_hash_init(&lf_hash, sizeof(int), LF_HASH_UNIQUE, 0, sizeof(int), 0,
180  &my_charset_bin);
181 
182  bad= my_atomic_initialize();
183  EXPECT_FALSE(bad) << "my_atomic_initialize() returned " << bad;
184 
185  with_my_thread_init= 1;
186  test_concurrently("lf_pinbox (with my_thread_init)",
187  test_lf_pinbox, N= THREADS, CYCLES);
188  test_concurrently("lf_alloc (with my_thread_init)",
189  test_lf_alloc, N= THREADS, CYCLES);
190  test_concurrently("lf_hash (with my_thread_init)",
191  test_lf_hash, N= THREADS, CYCLES/10);
192 
193  with_my_thread_init= 0;
194  test_concurrently("lf_pinbox (without my_thread_init)",
195  test_lf_pinbox, N= THREADS, CYCLES);
196  test_concurrently("lf_alloc (without my_thread_init)",
197  test_lf_alloc, N= THREADS, CYCLES);
198  test_concurrently("lf_hash (without my_thread_init)",
199  test_lf_hash, N= THREADS, CYCLES/10);
200 
201  lf_hash_destroy(&lf_hash);
202  lf_alloc_destroy(&lf_allocator);
203 }
204 
205 
206 TEST(Mysys, LockFree)
207 {
208  mysql_mutex_init(0, &mutex, 0);
209  mysql_cond_init(0, &cond, NULL);
210  pthread_attr_init(&thr_attr);
211  pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_DETACHED);
212 
213  do_tests();
214 
215  mysql_mutex_destroy(&mutex);
216  mysql_cond_destroy(&cond);
217  pthread_attr_destroy(&thr_attr);
218 }
219 
220 }