]>
Commit | Line | Data |
---|---|---|
d0da6fe5 ER |
1 | diff -ruN a/innobase/configure b/innobase/configure |
2 | --- a/innobase/configure 2009-01-30 06:56:31.000000000 +0900 | |
3 | +++ b/innobase/configure 2009-05-06 15:40:47.000000000 +0900 | |
4 | @@ -21306,6 +21306,88 @@ | |
5 | fi | |
6 | done | |
7 | ||
8 | + | |
9 | +# as http://lists.mysql.com/commits/40686 does | |
10 | +{ echo "$as_me:$LINENO: checking whether the compiler provides atomic builtins" >&5 | |
11 | +echo $ECHO_N "checking whether the compiler provides atomic builtins... $ECHO_C" >&6; } | |
12 | +if test "${mysql_cv_atomic_builtins+set}" = set; then | |
13 | + echo $ECHO_N "(cached) $ECHO_C" >&6 | |
14 | +else | |
15 | + if test "$cross_compiling" = yes; then | |
16 | + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling | |
17 | +See \`config.log' for more details." >&5 | |
18 | +echo "$as_me: error: cannot run test program while cross compiling | |
19 | +See \`config.log' for more details." >&2;} | |
20 | + { (exit 1); exit 1; }; } | |
21 | +else | |
22 | + cat >conftest.$ac_ext <<_ACEOF | |
23 | +/* confdefs.h. */ | |
24 | +_ACEOF | |
25 | +cat confdefs.h >>conftest.$ac_ext | |
26 | +cat >>conftest.$ac_ext <<_ACEOF | |
27 | +/* end confdefs.h. */ | |
28 | + | |
29 | + int main() | |
30 | + { | |
31 | + int foo= -10; int bar= 10; | |
32 | + __sync_fetch_and_add(&foo, bar); | |
33 | + if (foo) | |
34 | + return -1; | |
35 | + bar= __sync_lock_test_and_set(&foo, bar); | |
36 | + if (bar || foo != 10) | |
37 | + return -1; | |
38 | + bar= __sync_val_compare_and_swap(&bar, foo, 15); | |
39 | + if (bar) | |
40 | + return -1; | |
41 | + return 0; | |
42 | + } | |
43 | + | |
44 | +_ACEOF | |
45 | +rm -f conftest$ac_exeext | |
46 | +if { (ac_try="$ac_link" | |
47 | +case "(($ac_try" in | |
48 | + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; | |
49 | + *) ac_try_echo=$ac_try;; | |
50 | +esac | |
51 | +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 | |
52 | + (eval "$ac_link") 2>&5 | |
53 | + ac_status=$? | |
54 | + echo "$as_me:$LINENO: \$? = $ac_status" >&5 | |
55 | + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' | |
56 | + { (case "(($ac_try" in | |
57 | + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; | |
58 | + *) ac_try_echo=$ac_try;; | |
59 | +esac | |
60 | +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 | |
61 | + (eval "$ac_try") 2>&5 | |
62 | + ac_status=$? | |
63 | + echo "$as_me:$LINENO: \$? = $ac_status" >&5 | |
64 | + (exit $ac_status); }; }; then | |
65 | + mysql_cv_atomic_builtins=yes | |
66 | +else | |
67 | + echo "$as_me: program exited with status $ac_status" >&5 | |
68 | +echo "$as_me: failed program was:" >&5 | |
69 | +sed 's/^/| /' conftest.$ac_ext >&5 | |
70 | + | |
71 | +( exit $ac_status ) | |
72 | +mysql_cv_atomic_builtins=no | |
73 | +fi | |
74 | +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext | |
75 | +fi | |
76 | + | |
77 | + | |
78 | +fi | |
79 | +{ echo "$as_me:$LINENO: result: $mysql_cv_atomic_builtins" >&5 | |
80 | +echo "${ECHO_T}$mysql_cv_atomic_builtins" >&6; } | |
81 | + | |
82 | +if test "x$mysql_cv_atomic_builtins" = xyes; then | |
83 | + | |
84 | +cat >>confdefs.h <<\_ACEOF | |
85 | +#define HAVE_ATOMIC_BUILTINS 1 | |
86 | +_ACEOF | |
87 | + | |
88 | +fi | |
89 | + | |
90 | #AC_CHECK_FUNCS(readdir_r) MySQL checks that it has also the right args. | |
91 | # Some versions of Unix only take 2 arguments. | |
92 | #AC_C_INLINE Already checked in MySQL | |
93 | diff -ruN a/innobase/configure.in b/innobase/configure.in | |
94 | --- a/innobase/configure.in 2009-01-30 06:42:15.000000000 +0900 | |
95 | +++ b/innobase/configure.in 2009-05-06 15:40:47.000000000 +0900 | |
96 | @@ -42,6 +42,31 @@ | |
97 | AC_CHECK_FUNCS(sched_yield) | |
98 | AC_CHECK_FUNCS(fdatasync) | |
99 | AC_CHECK_FUNCS(localtime_r) | |
100 | + | |
101 | +# as http://lists.mysql.com/commits/40686 does | |
102 | +AC_CACHE_CHECK([whether the compiler provides atomic builtins], | |
103 | + [mysql_cv_atomic_builtins], [AC_TRY_RUN([ | |
104 | + int main() | |
105 | + { | |
106 | + int foo= -10; int bar= 10; | |
107 | + __sync_fetch_and_add(&foo, bar); | |
108 | + if (foo) | |
109 | + return -1; | |
110 | + bar= __sync_lock_test_and_set(&foo, bar); | |
111 | + if (bar || foo != 10) | |
112 | + return -1; | |
113 | + bar= __sync_val_compare_and_swap(&bar, foo, 15); | |
114 | + if (bar) | |
115 | + return -1; | |
116 | + return 0; | |
117 | + } | |
118 | +], [mysql_cv_atomic_builtins=yes], [mysql_cv_atomic_builtins=no])]) | |
119 | + | |
120 | +if test "x$mysql_cv_atomic_builtins" = xyes; then | |
121 | + AC_DEFINE(HAVE_ATOMIC_BUILTINS, 1, | |
122 | + [Define to 1 if compiler provides atomic builtins.]) | |
123 | +fi | |
124 | + | |
125 | #AC_CHECK_FUNCS(readdir_r) MySQL checks that it has also the right args. | |
126 | # Some versions of Unix only take 2 arguments. | |
127 | #AC_C_INLINE Already checked in MySQL | |
128 | diff -ruN a/innobase/ib_config.h b/innobase/ib_config.h | |
129 | --- a/innobase/ib_config.h 2009-01-30 07:05:03.000000000 +0900 | |
130 | +++ b/innobase/ib_config.h 2009-05-06 15:40:47.000000000 +0900 | |
131 | @@ -7,6 +7,9 @@ | |
132 | /* Define to 1 if you have the <aio.h> header file. */ | |
133 | #define HAVE_AIO_H 1 | |
134 | ||
135 | +/* Define to 1 if compiler provides atomic builtins. */ | |
136 | +#define HAVE_ATOMIC_BUILTINS 1 | |
137 | + | |
138 | /* Define to 1 if you have the <dlfcn.h> header file. */ | |
139 | #define HAVE_DLFCN_H 1 | |
140 | ||
141 | diff -ruN a/innobase/ib_config.h.in b/innobase/ib_config.h.in | |
142 | --- a/innobase/ib_config.h.in 2009-01-30 06:56:11.000000000 +0900 | |
143 | +++ b/innobase/ib_config.h.in 2009-05-06 15:40:47.000000000 +0900 | |
144 | @@ -6,6 +6,9 @@ | |
145 | /* Define to 1 if you have the <aio.h> header file. */ | |
146 | #undef HAVE_AIO_H | |
147 | ||
148 | +/* Define to 1 if compiler provides atomic builtins. */ | |
149 | +#undef HAVE_ATOMIC_BUILTINS | |
150 | + | |
151 | /* Define to 1 if you have the <dlfcn.h> header file. */ | |
152 | #undef HAVE_DLFCN_H | |
153 | ||
154 | diff -ruN a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h | |
155 | --- a/innobase/include/srv0srv.h 2009-05-06 15:38:01.000000000 +0900 | |
156 | +++ b/innobase/include/srv0srv.h 2009-05-06 16:04:36.000000000 +0900 | |
157 | @@ -90,6 +90,8 @@ | |
158 | extern ulint srv_mem_pool_size; | |
159 | extern ulint srv_lock_table_size; | |
160 | ||
161 | +extern ibool srv_thread_concurrency_timer_based; | |
162 | + | |
163 | extern ulint srv_n_file_io_threads; | |
164 | extern ulint srv_n_read_io_threads; | |
165 | extern ulint srv_n_write_io_threads; | |
166 | diff -ruN a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c | |
167 | --- a/innobase/srv/srv0srv.c 2009-05-06 15:38:01.000000000 +0900 | |
168 | +++ b/innobase/srv/srv0srv.c 2009-05-06 17:12:54.000000000 +0900 | |
169 | @@ -267,6 +267,7 @@ | |
170 | computer. Bigger computers need bigger values. Value 0 will disable the | |
171 | concurrency check. */ | |
172 | ||
173 | +ibool srv_thread_concurrency_timer_based = TRUE; | |
174 | ulong srv_thread_concurrency = 0; | |
175 | ulong srv_commit_concurrency = 0; | |
176 | ||
177 | @@ -1020,6 +1021,74 @@ | |
178 | Puts an OS thread to wait if there are too many concurrent threads | |
179 | (>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */ | |
180 | ||
181 | +#ifdef HAVE_ATOMIC_BUILTINS | |
182 | +static void | |
183 | +enter_innodb_with_tickets(trx_t* trx) | |
184 | +{ | |
185 | + trx->declared_to_be_inside_innodb = TRUE; | |
186 | + trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER; | |
187 | + return; | |
188 | +} | |
189 | + | |
190 | +static void | |
191 | +srv_conc_enter_innodb_timer_based(trx_t* trx) | |
192 | +{ | |
193 | + lint conc_n_threads; | |
194 | + ibool has_yielded = FALSE; | |
195 | + ulint has_slept = 0; | |
196 | + | |
197 | + if (trx->declared_to_be_inside_innodb) { | |
198 | + ut_print_timestamp(stderr); | |
199 | + fputs( | |
200 | +" InnoDB: Error: trying to declare trx to enter InnoDB, but\n" | |
201 | +"InnoDB: it already is declared.\n", stderr); | |
202 | + trx_print(stderr, trx, 0); | |
203 | + putc('\n', stderr); | |
204 | + } | |
205 | +retry: | |
206 | + if (srv_conc_n_threads < (lint) srv_thread_concurrency) { | |
207 | + conc_n_threads = __sync_add_and_fetch(&srv_conc_n_threads, 1); | |
208 | + if (conc_n_threads <= (lint) srv_thread_concurrency) { | |
209 | + enter_innodb_with_tickets(trx); | |
210 | + return; | |
211 | + } | |
212 | + __sync_add_and_fetch(&srv_conc_n_threads, -1); | |
213 | + } | |
214 | + if (!has_yielded) | |
215 | + { | |
216 | + has_yielded = TRUE; | |
217 | + os_thread_yield(); | |
218 | + goto retry; | |
219 | + } | |
220 | + if (trx->has_search_latch | |
221 | + || NULL != UT_LIST_GET_FIRST(trx->trx_locks)) { | |
222 | + | |
223 | + conc_n_threads = __sync_add_and_fetch(&srv_conc_n_threads, 1); | |
224 | + enter_innodb_with_tickets(trx); | |
225 | + return; | |
226 | + } | |
227 | + if (has_slept < 2) | |
228 | + { | |
229 | + trx->op_info = "sleeping before entering InnoDB"; | |
230 | + os_thread_sleep(10000); | |
231 | + trx->op_info = ""; | |
232 | + has_slept++; | |
233 | + } | |
234 | + conc_n_threads = __sync_add_and_fetch(&srv_conc_n_threads, 1); | |
235 | + enter_innodb_with_tickets(trx); | |
236 | + return; | |
237 | +} | |
238 | + | |
239 | +static void | |
240 | +srv_conc_exit_innodb_timer_based(trx_t* trx) | |
241 | +{ | |
242 | + __sync_add_and_fetch(&srv_conc_n_threads, -1); | |
243 | + trx->declared_to_be_inside_innodb = FALSE; | |
244 | + trx->n_tickets_to_enter_innodb = 0; | |
245 | + return; | |
246 | +} | |
247 | +#endif | |
248 | + | |
249 | void | |
250 | srv_conc_enter_innodb( | |
251 | /*==================*/ | |
252 | @@ -1043,6 +1112,13 @@ | |
253 | return; | |
254 | } | |
255 | ||
256 | +#ifdef HAVE_ATOMIC_BUILTINS | |
257 | + if (srv_thread_concurrency_timer_based) { | |
258 | + srv_conc_enter_innodb_timer_based(trx); | |
259 | + return; | |
260 | + } | |
261 | +#endif | |
262 | + | |
263 | os_fast_mutex_lock(&srv_conc_mutex); | |
264 | retry: | |
265 | if (trx->declared_to_be_inside_innodb) { | |
266 | @@ -1196,6 +1272,15 @@ | |
267 | return; | |
268 | } | |
269 | ||
270 | + ut_ad(srv_conc_n_threads >= 0); | |
271 | +#ifdef HAVE_ATOMIC_BUILTINS | |
272 | + if (srv_thread_concurrency_timer_based) { | |
273 | + __sync_add_and_fetch(&srv_conc_n_threads, 1); | |
274 | + trx->declared_to_be_inside_innodb = TRUE; | |
275 | + trx->n_tickets_to_enter_innodb = 1; | |
276 | + return; | |
277 | + } | |
278 | +#endif | |
279 | os_fast_mutex_lock(&srv_conc_mutex); | |
280 | ||
281 | srv_conc_n_threads++; | |
282 | @@ -1227,8 +1312,16 @@ | |
283 | return; | |
284 | } | |
285 | ||
286 | +#ifdef HAVE_ATOMIC_BUILTINS | |
287 | + if (srv_thread_concurrency_timer_based) { | |
288 | + srv_conc_exit_innodb_timer_based(trx); | |
289 | + return; | |
290 | + } | |
291 | +#endif | |
292 | + | |
293 | os_fast_mutex_lock(&srv_conc_mutex); | |
294 | ||
295 | + ut_ad(srv_conc_n_threads > 0); | |
296 | srv_conc_n_threads--; | |
297 | trx->declared_to_be_inside_innodb = FALSE; | |
298 | trx->n_tickets_to_enter_innodb = 0; | |
299 | diff -ruN a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c | |
300 | --- a/innobase/srv/srv0start.c 2009-05-06 15:38:01.000000000 +0900 | |
301 | +++ b/innobase/srv/srv0start.c 2009-05-06 17:22:26.000000000 +0900 | |
302 | @@ -1040,6 +1040,11 @@ | |
303 | return(DB_ERROR); | |
304 | } | |
305 | ||
306 | +#ifdef HAVE_ATOMIC_BUILTINS | |
307 | + fprintf(stderr, | |
308 | + "InnoDB: use atomic builtins.\n"); | |
309 | +#endif | |
310 | + | |
311 | /* Since InnoDB does not currently clean up all its internal data | |
312 | structures in MySQL Embedded Server Library server_end(), we | |
313 | print an error message if someone tries to start up InnoDB a | |
314 | diff -ruN a/patch_info/innodb_thread_concurrency_timer_based.info b/patch_info/innodb_thread_concurrency_timer_based.info | |
315 | --- /dev/null 1970-01-01 09:00:00.000000000 +0900 | |
316 | +++ b/patch_info/innodb_thread_concurrency_timer_based.info 2009-05-06 17:17:12.000000000 +0900 | |
317 | @@ -0,0 +1,6 @@ | |
318 | +File=thread_concurrency_timer_based.patch | |
319 | +Name=Use InnoDB timer based concurrency throttling (backport from MySQL 5.4.0) | |
320 | +Version=1.0 | |
321 | +Author=Percona <info@percona.com> | |
322 | +License=GPL | |
323 | +Comment | |
324 | diff -ruN a/sql/ha_innodb.cc b/sql/ha_innodb.cc | |
325 | --- a/sql/ha_innodb.cc 2009-05-06 15:38:01.000000000 +0900 | |
326 | +++ b/sql/ha_innodb.cc 2009-05-06 15:54:08.000000000 +0900 | |
327 | @@ -152,6 +152,7 @@ | |
328 | innobase_open_files; | |
329 | ||
330 | long innobase_read_io_threads, innobase_write_io_threads; | |
331 | +my_bool innobase_thread_concurrency_timer_based; | |
332 | long innobase_extra_rsegments; | |
333 | longlong innobase_buffer_pool_size, innobase_log_file_size; | |
334 | ||
335 | @@ -1477,6 +1478,9 @@ | |
336 | srv_n_log_files = (ulint) innobase_log_files_in_group; | |
337 | srv_log_file_size = (ulint) innobase_log_file_size; | |
338 | ||
339 | + srv_thread_concurrency_timer_based = | |
340 | + (ibool) innobase_thread_concurrency_timer_based; | |
341 | + | |
342 | #ifdef UNIV_LOG_ARCHIVE | |
343 | srv_log_archive_on = (ulint) innobase_log_archive; | |
344 | #endif /* UNIV_LOG_ARCHIVE */ | |
345 | diff -ruN a/sql/ha_innodb.h b/sql/ha_innodb.h | |
346 | --- a/sql/ha_innodb.h 2009-05-06 15:38:01.000000000 +0900 | |
347 | +++ b/sql/ha_innodb.h 2009-05-06 15:55:50.000000000 +0900 | |
348 | @@ -205,6 +205,7 @@ | |
349 | extern long innobase_buffer_pool_awe_mem_mb; | |
350 | extern long innobase_file_io_threads, innobase_lock_wait_timeout; | |
351 | extern long innobase_read_io_threads, innobase_write_io_threads; | |
352 | +extern my_bool innobase_thread_concurrency_timer_based; | |
353 | extern long innobase_extra_rsegments; | |
354 | extern long innobase_force_recovery; | |
355 | extern long innobase_open_files; | |
356 | diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc | |
357 | --- a/sql/mysqld.cc 2009-05-06 15:38:01.000000000 +0900 | |
358 | +++ b/sql/mysqld.cc 2009-05-06 16:22:06.000000000 +0900 | |
359 | @@ -5096,6 +5096,7 @@ | |
360 | OPT_INNODB_ADAPTIVE_CHECKPOINT, | |
361 | OPT_INNODB_READ_IO_THREADS, | |
362 | OPT_INNODB_WRITE_IO_THREADS, | |
363 | + OPT_INNODB_THREAD_CONCURRENCY_TIMER_BASED, | |
364 | OPT_INNODB_EXTRA_RSEGMENTS, | |
365 | OPT_INNODB_DICT_SIZE_LIMIT, | |
366 | OPT_INNODB_ADAPTIVE_HASH_INDEX, | |
367 | @@ -5455,6 +5456,11 @@ | |
368 | "Number of background write I/O threads in InnoDB.", | |
369 | (gptr*) &innobase_write_io_threads, (gptr*) &innobase_write_io_threads, | |
370 | 0, GET_LONG, REQUIRED_ARG, 1, 1, 64, 0, 0, 0}, | |
371 | + {"innodb_thread_concurrency_timer_based", OPT_INNODB_THREAD_CONCURRENCY_TIMER_BASED, | |
372 | + "Use InnoDB timer based concurrency throttling. ", | |
373 | + (gptr*) &innobase_thread_concurrency_timer_based, | |
374 | + (gptr*) &innobase_thread_concurrency_timer_based, | |
375 | + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, | |
376 | {"innodb_extra_rsegments", OPT_INNODB_EXTRA_RSEGMENTS, | |
377 | "Number of extra user rollback segments when create new database.", | |
378 | (gptr*) &innobase_extra_rsegments, (gptr*) &innobase_extra_rsegments, | |
379 | diff -ruN a/sql/set_var.cc b/sql/set_var.cc | |
380 | --- a/sql/set_var.cc 2009-05-06 15:38:01.000000000 +0900 | |
381 | +++ b/sql/set_var.cc 2009-05-06 16:02:27.000000000 +0900 | |
382 | @@ -1063,6 +1063,7 @@ | |
383 | {sys_innodb_adaptive_checkpoint.name, (char*) &sys_innodb_adaptive_checkpoint, SHOW_SYS}, | |
384 | {"innodb_read_io_threads", (char*) &innobase_read_io_threads, SHOW_LONG}, | |
385 | {"innodb_write_io_threads", (char*) &innobase_write_io_threads, SHOW_LONG}, | |
386 | + {"innodb_thread_concurrency_timer_based", (char*) &innobase_thread_concurrency_timer_based, SHOW_MY_BOOL}, | |
387 | {"innodb_extra_rsegments", (char*) &innobase_extra_rsegments, SHOW_LONG}, | |
388 | {sys_innodb_dict_size_limit.name, (char*) &sys_innodb_dict_size_limit, SHOW_SYS}, | |
389 | {sys_innodb_io_pattern_trace.name, (char*) &sys_innodb_io_pattern_trace, SHOW_SYS}, |