1/* Copyright (c) 2008, 2011, 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/**
17 @file
18
19 Unit tests for lock-free algorithms of mysys
20*/
21
22#include "thr_template.c"
23
24#include <lf.h>
25
26int32 inserts= 0, N;
27LF_ALLOCATOR lf_allocator;
28LF_HASH lf_hash;
29
30int with_my_thread_init=0;
31
32/*
33 pin allocator - alloc and release an element in a loop
34*/
35pthread_handler_t test_lf_pinbox(void *arg)
36{
37 int m= *(int *)arg;
38 LF_PINS *pins;
39
40 if (with_my_thread_init)
41 my_thread_init();
42
43 pins= lf_pinbox_get_pins(&lf_allocator.pinbox);
44
45 for (; m ; m--)
46 {
47 lf_pinbox_put_pins(pins);
48 pins= lf_pinbox_get_pins(&lf_allocator.pinbox);
49 }
50 lf_pinbox_put_pins(pins);
51 pthread_mutex_lock(&mutex);
52 if (!--running_threads) pthread_cond_signal(&cond);
53 pthread_mutex_unlock(&mutex);
54
55 if (with_my_thread_init)
56 my_thread_end();
57
58 return 0;
59}
60
61/*
62 thread local data area, allocated using lf_alloc.
63 union is required to enforce the minimum required element size (sizeof(ptr))
64*/
65typedef union {
66 int32 data;
67 void *not_used;
68} TLA;
69
70pthread_handler_t test_lf_alloc(void *arg)
71{
72 int m= (*(int *)arg)/2;
73 int32 x,y= 0;
74 LF_PINS *pins;
75
76 if (with_my_thread_init)
77 my_thread_init();
78
79 pins= lf_alloc_get_pins(&lf_allocator);
80
81 for (x= ((int)(intptr)(&m)); m ; m--)
82 {
83 TLA *node1, *node2;
84 x= (x*m+0x87654321) & INT_MAX32;
85 node1= (TLA *)lf_alloc_new(pins);
86 node1->data= x;
87 y+= node1->data;
88 node1->data= 0;
89 node2= (TLA *)lf_alloc_new(pins);
90 node2->data= x;
91 y-= node2->data;
92 node2->data= 0;
93 lf_alloc_free(pins, node1);
94 lf_alloc_free(pins, node2);
95 }
96 lf_alloc_put_pins(pins);
97 pthread_mutex_lock(&mutex);
98 bad+= y;
99
100 if (--N == 0)
101 {
102 diag("%d mallocs, %d pins in stack",
103 lf_allocator.mallocs, lf_allocator.pinbox.pins_in_array);
104#ifdef MY_LF_EXTRA_DEBUG
105 bad|= lf_allocator.mallocs - lf_alloc_pool_count(&lf_allocator);
106#endif
107 }
108 if (!--running_threads) pthread_cond_signal(&cond);
109 pthread_mutex_unlock(&mutex);
110
111 if (with_my_thread_init)
112 my_thread_end();
113 return 0;
114}
115
116my_bool do_sum(void *num, void *acc)
117{
118 *(int *)acc += *(int *)num;
119 return 0;
120}
121
122
123#define N_TLH 1000
124pthread_handler_t test_lf_hash(void *arg)
125{
126 int m= (*(int *)arg)/(2*N_TLH);
127 int32 x,y,z,sum= 0, ins= 0, scans= 0;
128 LF_PINS *pins;
129
130 if (with_my_thread_init)
131 my_thread_init();
132
133 pins= lf_hash_get_pins(&lf_hash);
134
135 for (x= ((int)(intptr)(&m)); m ; m--)
136 {
137 int i;
138 y= x;
139 for (i= 0; i < N_TLH; i++)
140 {
141 x= (x*(m+i)+0x87654321) & INT_MAX32;
142 z= (x<0) ? -x : x;
143 if (lf_hash_insert(&lf_hash, pins, &z))
144 {
145 sum+= z;
146 ins++;
147 }
148 else
149 {
150 int unused= 0;
151 lf_hash_iterate(&lf_hash, pins, do_sum, &unused);
152 scans++;
153 }
154 }
155 for (i= 0; i < N_TLH; i++)
156 {
157 y= (y*(m+i)+0x87654321) & INT_MAX32;
158 z= (y<0) ? -y : y;
159 if (lf_hash_delete(&lf_hash, pins, (uchar *)&z, sizeof(z)))
160 sum-= z;
161 }
162 }
163 lf_hash_put_pins(pins);
164 pthread_mutex_lock(&mutex);
165 bad+= sum;
166 inserts+= ins;
167
168 if (--N == 0)
169 {
170 diag("%d mallocs, %d pins in stack, %d hash size, %d inserts, %d scans",
171 lf_hash.alloc.mallocs, lf_hash.alloc.pinbox.pins_in_array,
172 lf_hash.size, inserts, scans);
173 bad|= lf_hash.count;
174 }
175 if (!--running_threads) pthread_cond_signal(&cond);
176 pthread_mutex_unlock(&mutex);
177 if (with_my_thread_init)
178 my_thread_end();
179 return 0;
180}
181
182
183void do_tests()
184{
185 plan(6);
186
187 lf_alloc_init(&lf_allocator, sizeof(TLA), offsetof(TLA, not_used));
188 lf_hash_init(&lf_hash, sizeof(int), LF_HASH_UNIQUE, 0, sizeof(int), 0,
189 &my_charset_bin);
190
191 with_my_thread_init= 1;
192 test_concurrently("lf_pinbox (with my_thread_init)", test_lf_pinbox, N= THREADS, CYCLES);
193 test_concurrently("lf_alloc (with my_thread_init)", test_lf_alloc, N= THREADS, CYCLES);
194 test_concurrently("lf_hash (with my_thread_init)", test_lf_hash, N= THREADS, CYCLES);
195
196 with_my_thread_init= 0;
197 test_concurrently("lf_pinbox (without my_thread_init)", test_lf_pinbox, N= THREADS, CYCLES);
198 test_concurrently("lf_alloc (without my_thread_init)", test_lf_alloc, N= THREADS, CYCLES);
199 test_concurrently("lf_hash (without my_thread_init)", test_lf_hash, N= THREADS, CYCLES);
200
201 lf_hash_destroy(&lf_hash);
202 lf_alloc_destroy(&lf_allocator);
203}
204
205