1 ------------------------------------------------------------
3 committer: serg@serg.mylan
4 timestamp: Wed 2006-05-31 18:44:09 +0200
6 WL#2595 - atomic operations
7 === modified file 'configure.in'
8 --- configure.in 2006-05-26 11:17:09 +0000
9 +++ configure.in 2006-05-31 16:44:09 +0000
13 if test "$TARGET_LINUX" = "true"; then
14 - AC_MSG_CHECKING([for atomic operations])
21 -#include <asm/atomic.h>
28 - return atomic_read(&v) == 28 ? 0 : -1;
31 - [AC_DEFINE([HAVE_ATOMIC_ADD], [1],
32 - [atomic_add() from <asm/atomic.h> (Linux only)])
33 - atom_ops="${atom_ops}atomic_add "],
36 -#include <asm/atomic.h>
43 - return atomic_read(&v) == 18 ? 0 : -1;
46 - [AC_DEFINE([HAVE_ATOMIC_SUB], [1],
47 - [atomic_sub() from <asm/atomic.h> (Linux only)])
48 - atom_ops="${atom_ops}atomic_sub "],
51 - if test -z "$atom_ops"; then atom_ops="no"; fi
52 - AC_MSG_RESULT($atom_ops)
57 [ --with-pstack Use the pstack backtrace library],
58 [ USE_PSTACK=$withval ],
59 @@ -1631,6 +1589,20 @@
63 +AC_ARG_WITH([atomic-ops],
64 + AC_HELP_STRING([--with-atomic-ops=rwlocks|smp|up],
65 + [Implement atomic operations using pthread rwlocks or atomic CPU
66 + instructions for multi-processor (default) or uniprocessor
67 + configuration]), , [with_atomic_ops=smp])
68 +case "$with_atomic_ops" in
69 + "up") AC_DEFINE([MY_ATOMIC_MODE_DUMMY], [1],
70 + [Assume single-CPU mode, no concurrency]) ;;
71 + "rwlocks") AC_DEFINE([MY_ATOMIC_MODE_RWLOCKS], [1],
72 + [Use pthread rwlocks for atomic ops]) ;;
74 + *) AC_MSG_ERROR(["$with_atomic_ops" is not a valid value for --with-atomic-ops]) ;;
77 # Force static compilation to avoid linking problems/get more speed
78 AC_ARG_WITH(mysqld-ldflags,
79 [ --with-mysqld-ldflags Extra linking arguments for mysqld],
81 === added directory 'include/atomic'
82 === added file 'include/atomic/nolock.h'
83 --- include/atomic/nolock.h 1970-01-01 00:00:00 +0000
84 +++ include/atomic/nolock.h 2006-05-31 16:44:09 +0000
86 +/* Copyright (C) 2006 MySQL AB
88 + This program is free software; you can redistribute it and/or modify
89 + it under the terms of the GNU General Public License as published by
90 + the Free Software Foundation; either version 2 of the License, or
91 + (at your option) any later version.
93 + This program is distributed in the hope that it will be useful,
94 + but WITHOUT ANY WARRANTY; without even the implied warranty of
95 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
96 + GNU General Public License for more details.
98 + You should have received a copy of the GNU General Public License
99 + along with this program; if not, write to the Free Software
100 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
102 +#if defined(__i386__) || defined(_M_IX86)
103 +#ifdef MY_ATOMIC_MODE_DUMMY
106 +# define LOCK "lock "
109 +#include "x86-gcc.h"
110 +#elif defined(_MSC_VER)
111 +#include "x86-msvc.h"
115 +#ifdef make_atomic_add_body8
119 +#define make_atomic_add(S) \
120 +static inline uint ## S _my_atomic_add ## S( \
121 + my_atomic_ ## S ## _t *a, uint ## S v) \
123 + make_atomic_add_body ## S; \
127 +#define make_atomic_swap(S) \
128 +static inline uint ## S _my_atomic_swap ## S( \
129 + my_atomic_ ## S ## _t *a, uint ## S v) \
131 + make_atomic_swap_body ## S; \
135 +#define make_atomic_cas(S) \
136 +static inline uint _my_atomic_cas ## S(my_atomic_ ## S ## _t *a,\
137 + uint ## S *cmp, uint ## S set) \
140 + make_atomic_cas_body ## S; \
144 +#define make_atomic_load(S) \
145 +static inline uint ## S _my_atomic_load ## S( \
146 + my_atomic_ ## S ## _t *a) \
149 + make_atomic_load_body ## S; \
153 +#define make_atomic_store(S) \
154 +static inline void _my_atomic_store ## S( \
155 + my_atomic_ ## S ## _t *a, uint ## S v) \
157 + make_atomic_store_body ## S; \
160 +#else /* no inline functions */
162 +#define make_atomic_add(S) \
163 +extern uint ## S _my_atomic_add ## S( \
164 + my_atomic_ ## S ## _t *a, uint ## S v);
166 +#define make_atomic_swap(S) \
167 +extern uint ## S _my_atomic_swap ## S( \
168 + my_atomic_ ## S ## _t *a, uint ## S v);
170 +#define make_atomic_cas(S) \
171 +extern uint _my_atomic_cas ## S(my_atomic_ ## S ## _t *a, \
172 + uint ## S *cmp, uint ## S set);
174 +#define make_atomic_load(S) \
175 +extern uint ## S _my_atomic_load ## S( \
176 + my_atomic_ ## S ## _t *a);
178 +#define make_atomic_store(S) \
179 +extern void _my_atomic_store ## S( \
180 + my_atomic_ ## S ## _t *a, uint ## S v);
192 +make_atomic_load( 8)
193 +make_atomic_load(16)
194 +make_atomic_load(32)
196 +make_atomic_store( 8)
197 +make_atomic_store(16)
198 +make_atomic_store(32)
200 +make_atomic_swap( 8)
201 +make_atomic_swap(16)
202 +make_atomic_swap(32)
204 +#undef make_atomic_add_body8
205 +#undef make_atomic_cas_body8
206 +#undef make_atomic_load_body8
207 +#undef make_atomic_store_body8
208 +#undef make_atomic_swap_body8
209 +#undef make_atomic_add_body16
210 +#undef make_atomic_cas_body16
211 +#undef make_atomic_load_body16
212 +#undef make_atomic_store_body16
213 +#undef make_atomic_swap_body16
214 +#undef make_atomic_add_body32
215 +#undef make_atomic_cas_body32
216 +#undef make_atomic_load_body32
217 +#undef make_atomic_store_body32
218 +#undef make_atomic_swap_body32
219 +#undef make_atomic_add
220 +#undef make_atomic_cas
221 +#undef make_atomic_load
222 +#undef make_atomic_store
223 +#undef make_atomic_swap
225 +#define my_atomic_add8(a,v,L) _my_atomic_add8(a,v)
226 +#define my_atomic_add16(a,v,L) _my_atomic_add16(a,v)
227 +#define my_atomic_add32(a,v,L) _my_atomic_add32(a,v)
229 +#define my_atomic_cas8(a,c,v,L) _my_atomic_cas8(a,c,v)
230 +#define my_atomic_cas16(a,c,v,L) _my_atomic_cas16(a,c,v)
231 +#define my_atomic_cas32(a,c,v,L) _my_atomic_cas32(a,c,v)
233 +#define my_atomic_load8(a,L) _my_atomic_load8(a)
234 +#define my_atomic_load16(a,L) _my_atomic_load16(a)
235 +#define my_atomic_load32(a,L) _my_atomic_load32(a)
237 +#define my_atomic_store8(a,v,L) _my_atomic_store8(a,v)
238 +#define my_atomic_store16(a,v,L) _my_atomic_store16(a,v)
239 +#define my_atomic_store32(a,v,L) _my_atomic_store32(a,v)
241 +#define my_atomic_swap8(a,v,L) _my_atomic_swap8(a,v)
242 +#define my_atomic_swap16(a,v,L) _my_atomic_swap16(a,v)
243 +#define my_atomic_swap32(a,v,L) _my_atomic_swap32(a,v)
245 +#define my_atomic_rwlock_t typedef int
246 +#define my_atomic_rwlock_destroy(name)
247 +#define my_atomic_rwlock_init(name)
248 +#define my_atomic_rwlock_rdlock(name)
249 +#define my_atomic_rwlock_wrlock(name)
250 +#define my_atomic_rwlock_rdunlock(name)
251 +#define my_atomic_rwlock_wrunlock(name)
256 === added file 'include/atomic/rwlock.h'
257 --- include/atomic/rwlock.h 1970-01-01 00:00:00 +0000
258 +++ include/atomic/rwlock.h 2006-05-31 16:44:09 +0000
260 +/* Copyright (C) 2006 MySQL AB
262 + This program is free software; you can redistribute it and/or modify
263 + it under the terms of the GNU General Public License as published by
264 + the Free Software Foundation; either version 2 of the License, or
265 + (at your option) any later version.
267 + This program is distributed in the hope that it will be useful,
268 + but WITHOUT ANY WARRANTY; without even the implied warranty of
269 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
270 + GNU General Public License for more details.
272 + You should have received a copy of the GNU General Public License
273 + along with this program; if not, write to the Free Software
274 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
276 +typedef struct {pthread_rwlock_t rw;} my_atomic_rwlock_t;
278 +#ifdef MY_ATOMIC_EXTRA_DEBUG
279 +#define CHECK_RW if (rw) if (a->rw) assert(rw == a->rw); else a->rw=rw;
284 +#ifdef MY_ATOMIC_MODE_DUMMY
286 + the following can never be enabled by ./configure, one need to put #define in
287 + a source to trigger the following warning. The resulting code will be broken,
288 + it only makes sense to do it to see now test_atomic detects broken
289 + implementations (another way is to run a UP build on an SMP box).
291 +#warning MY_ATOMIC_MODE_DUMMY and MY_ATOMIC_MODE_RWLOCKS are incompatible
292 +#define my_atomic_rwlock_destroy(name)
293 +#define my_atomic_rwlock_init(name)
294 +#define my_atomic_rwlock_rdlock(name)
295 +#define my_atomic_rwlock_wrlock(name)
296 +#define my_atomic_rwlock_rdunlock(name)
297 +#define my_atomic_rwlock_wrunlock(name)
299 +#define my_atomic_rwlock_destroy(name) pthread_rwlock_destroy(& (name)->rw)
300 +#define my_atomic_rwlock_init(name) pthread_rwlock_init(& (name)->rw, 0)
301 +#define my_atomic_rwlock_rdlock(name) pthread_rwlock_rdlock(& (name)->rw)
302 +#define my_atomic_rwlock_wrlock(name) pthread_rwlock_wrlock(& (name)->rw)
303 +#define my_atomic_rwlock_rdunlock(name) pthread_rwlock_unlock(& (name)->rw)
304 +#define my_atomic_rwlock_wrunlock(name) pthread_rwlock_unlock(& (name)->rw)
309 +#define make_atomic_add(S) \
310 +static inline uint ## S my_atomic_add ## S( \
311 + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw) \
315 + if (rw) my_atomic_rwlock_wrlock(rw); \
318 + if (rw) my_atomic_rwlock_wrunlock(rw); \
322 +#define make_atomic_swap(S) \
323 +static inline uint ## S my_atomic_swap ## S( \
324 + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw) \
328 + if (rw) my_atomic_rwlock_wrlock(rw); \
331 + if (rw) my_atomic_rwlock_wrunlock(rw); \
335 +#define make_atomic_cas(S) \
336 +static inline uint my_atomic_cas ## S(my_atomic_ ## S ## _t *a, \
337 + uint ## S *cmp, uint ## S set, my_atomic_rwlock_t *rw) \
341 + if (rw) my_atomic_rwlock_wrlock(rw); \
342 + if (ret= (a->val == *cmp)) a->val= set; else *cmp=a->val; \
343 + if (rw) my_atomic_rwlock_wrunlock(rw); \
347 +#define make_atomic_load(S) \
348 +static inline uint ## S my_atomic_load ## S( \
349 + my_atomic_ ## S ## _t *a, my_atomic_rwlock_t *rw) \
353 + if (rw) my_atomic_rwlock_wrlock(rw); \
355 + if (rw) my_atomic_rwlock_wrunlock(rw); \
359 +#define make_atomic_store(S) \
360 +static inline void my_atomic_store ## S( \
361 + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw) \
364 + if (rw) my_atomic_rwlock_rdlock(rw); \
366 + if (rw) my_atomic_rwlock_rdunlock(rw); \
369 +#else /* no inline functions */
371 +#define make_atomic_add(S) \
372 +extern uint ## S my_atomic_add ## S( \
373 + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw);
375 +#define make_atomic_swap(S) \
376 +extern uint ## S my_atomic_swap ## S( \
377 + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw);
379 +#define make_atomic_cas(S) \
380 +extern uint my_atomic_cas ## S(my_atomic_ ## S ## _t *a, \
381 + uint ## S *cmp, uint ## S set, my_atomic_rwlock_t *rw);
383 +#define make_atomic_load(S) \
384 +extern uint ## S my_atomic_load ## S( \
385 + my_atomic_ ## S ## _t *a, my_atomic_rwlock_t *rw);
387 +#define make_atomic_store(S) \
388 +extern void my_atomic_store ## S( \
389 + my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw);
401 +make_atomic_load( 8)
402 +make_atomic_load(16)
403 +make_atomic_load(32)
404 +make_atomic_load(64)
405 +make_atomic_store( 8)
406 +make_atomic_store(16)
407 +make_atomic_store(32)
408 +make_atomic_store(64)
409 +make_atomic_swap( 8)
410 +make_atomic_swap(16)
411 +make_atomic_swap(32)
412 +make_atomic_swap(64)
413 +#undef make_atomic_add
414 +#undef make_atomic_cas
415 +#undef make_atomic_load
416 +#undef make_atomic_store
417 +#undef make_atomic_swap
422 === added file 'include/atomic/x86-gcc.h'
423 --- include/atomic/x86-gcc.h 1970-01-01 00:00:00 +0000
424 +++ include/atomic/x86-gcc.h 2006-05-31 16:44:09 +0000
426 +/* Copyright (C) 2006 MySQL AB
428 + This program is free software; you can redistribute it and/or modify
429 + it under the terms of the GNU General Public License as published by
430 + the Free Software Foundation; either version 2 of the License, or
431 + (at your option) any later version.
433 + This program is distributed in the hope that it will be useful,
434 + but WITHOUT ANY WARRANTY; without even the implied warranty of
435 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
436 + GNU General Public License for more details.
438 + You should have received a copy of the GNU General Public License
439 + along with this program; if not, write to the Free Software
440 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
443 + XXX 64-bit atomic operations can be implemented using
444 + cmpxchg8b, if necessary
447 +#define make_atomic_add_body8 \
448 + asm volatile (LOCK "xadd %0, %1;" : "+r" (v) , "+m" (a->val))
449 +#define make_atomic_swap_body8 \
450 + asm volatile ("xchg %0, %1;" : "+r" (v) , "+m" (a->val))
451 +#define make_atomic_cas_body8 \
452 + asm volatile (LOCK "cmpxchg %3, %0; setz %2;" \
453 + : "+m" (a->val), "+a" (*cmp), "=q" (ret): "r" (set))
455 +#ifdef MY_ATOMIC_MODE_DUMMY
456 +#define make_atomic_load_body8 ret=a->val
457 +#define make_atomic_store_body8 a->val=v
460 + Actually 32-bit reads/writes are always atomic on x86
461 + But we add LOCK here anyway to force memory barriers
463 +#define make_atomic_load_body8 \
465 + asm volatile (LOCK "cmpxchg %2, %0" \
466 + : "+m" (a->val), "+a" (ret): "r" (ret))
467 +#define make_atomic_store_body8 \
468 + asm volatile ("xchg %0, %1;" : "+m" (a->val) : "r" (v))
471 +#define make_atomic_add_body16 make_atomic_add_body8
472 +#define make_atomic_add_body32 make_atomic_add_body8
473 +#define make_atomic_cas_body16 make_atomic_cas_body8
474 +#define make_atomic_cas_body32 make_atomic_cas_body8
475 +#define make_atomic_load_body16 make_atomic_load_body8
476 +#define make_atomic_load_body32 make_atomic_load_body8
477 +#define make_atomic_store_body16 make_atomic_store_body8
478 +#define make_atomic_store_body32 make_atomic_store_body8
479 +#define make_atomic_swap_body16 make_atomic_swap_body8
480 +#define make_atomic_swap_body32 make_atomic_swap_body8
483 === added file 'include/atomic/x86-msvc.h'
484 --- include/atomic/x86-msvc.h 1970-01-01 00:00:00 +0000
485 +++ include/atomic/x86-msvc.h 2006-05-31 16:44:09 +0000
487 +/* Copyright (C) 2006 MySQL AB
489 + This program is free software; you can redistribute it and/or modify
490 + it under the terms of the GNU General Public License as published by
491 + the Free Software Foundation; either version 2 of the License, or
492 + (at your option) any later version.
494 + This program is distributed in the hope that it will be useful,
495 + but WITHOUT ANY WARRANTY; without even the implied warranty of
496 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
497 + GNU General Public License for more details.
499 + You should have received a copy of the GNU General Public License
500 + along with this program; if not, write to the Free Software
501 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
504 + XXX 64-bit atomic operations can be implemented using
505 + cmpxchg8b, if necessary
508 +// Would it be better to use intrinsics ?
509 +// (InterlockedCompareExchange, InterlockedCompareExchange16
510 +// InterlockedExchangeAdd, InterlockedExchange)
512 +#define make_atomic_add_body(REG) \
515 + _asm LOCK xadd a->val, REG \
516 + _asm movzx v, REG \
518 +#define make_atomic_cas_body(AREG,REG2) \
520 + _asm mov AREG, *cmp \
521 + _asm mov REG2, set \
522 + _asm LOCK cmpxchg a->val, REG2 \
523 + _asm mov *cmp, AREG \
525 + _asm movzx ret, al \
527 +#define make_atomic_swap_body(REG) \
530 + _asm xchg a->val, REG \
534 +#ifdef MY_ATOMIC_MODE_DUMMY
535 +#define make_atomic_load_body(AREG,REG) ret=a->val
536 +#define make_atomic_store_body(REG) a->val=v
539 + Actually 32-bit reads/writes are always atomic on x86
540 + But we add LOCK here anyway to force memory barriers
542 +#define make_atomic_load_body(AREG,REG2) \
545 + _asm mov REG2, AREG \
546 + _asm LOCK cmpxchg a->val, REG2 \
547 + _asm mov ret, AREG \
549 +#define make_atomic_store_body(REG) \
552 + _asm xchg a->val, REG \
556 +#define make_atomic_add_body8 make_atomic_add_body(al)
557 +#define make_atomic_add_body16 make_atomic_add_body(ax)
558 +#define make_atomic_add_body32 make_atomic_add_body(eax)
559 +#define make_atomic_cas_body8 make_atomic_cas_body(al, bl)
560 +#define make_atomic_cas_body16 make_atomic_cas_body(ax, bx)
561 +#define make_atomic_cas_body32 make_atomic_cas_body(eax, ebx)
562 +#define make_atomic_load_body8 make_atomic_load_body(al, bl)
563 +#define make_atomic_load_body16 make_atomic_load_body(ax, bx)
564 +#define make_atomic_load_body32 make_atomic_load_body(eax, ebx)
565 +#define make_atomic_store_body8 make_atomic_store_body(al)
566 +#define make_atomic_store_body16 make_atomic_store_body(ax)
567 +#define make_atomic_store_body32 make_atomic_store_body(eax)
568 +#define make_atomic_swap_body8 make_atomic_swap_body(al)
569 +#define make_atomic_swap_body16 make_atomic_swap_body(ax)
570 +#define make_atomic_swap_body32 make_atomic_swap_body(eax)
573 === added file 'include/my_atomic.h'
574 --- include/my_atomic.h 1970-01-01 00:00:00 +0000
575 +++ include/my_atomic.h 2006-05-31 16:44:09 +0000
577 +/* Copyright (C) 2006 MySQL AB
579 + This program is free software; you can redistribute it and/or modify
580 + it under the terms of the GNU General Public License as published by
581 + the Free Software Foundation; either version 2 of the License, or
582 + (at your option) any later version.
584 + This program is distributed in the hope that it will be useful,
585 + but WITHOUT ANY WARRANTY; without even the implied warranty of
586 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
587 + GNU General Public License for more details.
589 + You should have received a copy of the GNU General Public License
590 + along with this program; if not, write to the Free Software
591 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
593 +#ifndef atomic_rwlock_init
595 +#ifdef MY_ATOMIC_EXTRA_DEBUG
596 +#ifndef MY_ATOMIC_MODE_RWLOCKS
597 +#error MY_ATOMIC_EXTRA_DEBUG can be only used with MY_ATOMIC_MODE_RWLOCKS
599 +#define LOCK_PTR void *rw;
604 +typedef volatile struct {uint8 val; LOCK_PTR} my_atomic_8_t;
605 +typedef volatile struct {uint16 val; LOCK_PTR} my_atomic_16_t;
606 +typedef volatile struct {uint32 val; LOCK_PTR} my_atomic_32_t;
607 +typedef volatile struct {uint64 val; LOCK_PTR} my_atomic_64_t;
609 +#ifndef MY_ATOMIC_MODE_RWLOCKS
610 +#include "atomic/nolock.h"
613 +#ifndef my_atomic_rwlock_init
614 +#include "atomic/rwlock.h"
617 +#define MY_ATOMIC_OK 0
618 +#define MY_ATOMIC_NOT_1CPU 1
619 +extern int my_atomic_initialize();
624 === modified file 'include/my_global.h'
625 --- include/my_global.h 2006-05-02 09:36:05 +0000
626 +++ include/my_global.h 2006-05-31 16:44:09 +0000
632 + now let's figure out if inline functions are supported
633 + autoconf defines 'inline' to be empty, if not
635 +#define inline_test_1(X) X ## 1
636 +#define inline_test_2(X) inline_test_1(X)
637 +#if inline_test_2(inline) != 1
640 +#undef inline_test_2
641 +#undef inline_test_1
644 The following macros are used to control inlining a bit more than
646 typedef long longlong;
649 +typedef longlong int64;
650 +typedef ulonglong uint64;
652 #if defined(NO_CLIENT_LONG_LONG)
653 typedef unsigned long my_ulonglong;
655 === modified file 'mysys/Makefile.am'
656 --- mysys/Makefile.am 2006-05-12 08:51:07 +0000
657 +++ mysys/Makefile.am 2006-05-31 16:44:09 +0000
659 INCLUDES = @ZLIB_INCLUDES@ -I$(top_builddir)/include \
660 -I$(top_srcdir)/include -I$(srcdir)
661 pkglib_LIBRARIES = libmysys.a
662 -LDADD = libmysys.a ../dbug/libdbug.a \
663 +LDADD = libmysys.a \
664 ../strings/libmystrings.a
665 noinst_HEADERS = mysys_priv.h my_static.h \
666 my_os2cond.c my_os2dirsrch.c my_os2dirsrch.h \
668 mf_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \
669 mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \
670 my_malloc.c my_realloc.c my_once.c mulalloc.c \
671 - my_alloc.c safemalloc.c my_new.cc \
672 + my_alloc.c safemalloc.c my_new.cc my_atomic.c my_getncpus.c \
673 my_fopen.c my_fstream.c my_getsystime.c \
674 my_error.c errors.c my_div.c my_messnc.c \
675 mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \
677 # testhash_DEPENDENCIES= $(LIBRARIES)
678 # test_charset_DEPENDENCIES= $(LIBRARIES)
679 # charset2html_DEPENDENCIES= $(LIBRARIES)
681 +noinst_PROGRAMS= test_atomic$(EXEEXT)
682 DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \
683 -DDATADIR="\"$(MYSQLDATAdir)\"" \
684 -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
686 === added file 'mysys/my_atomic.c'
687 --- mysys/my_atomic.c 1970-01-01 00:00:00 +0000
688 +++ mysys/my_atomic.c 2006-05-31 16:44:09 +0000
690 +/* Copyright (C) 2006 MySQL AB
692 + This program is free software; you can redistribute it and/or modify
693 + it under the terms of the GNU General Public License as published by
694 + the Free Software Foundation; either version 2 of the License, or
695 + (at your option) any later version.
697 + This program is distributed in the hope that it will be useful,
698 + but WITHOUT ANY WARRANTY; without even the implied warranty of
699 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
700 + GNU General Public License for more details.
702 + You should have received a copy of the GNU General Public License
703 + along with this program; if not, write to the Free Software
704 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
706 +#include <my_global.h>
707 +#include <my_pthread.h>
711 + the following will cause all inline functions to be instantiated
714 +#define static extern
717 +#include <my_atomic.h>
720 + checks that the current build of atomic ops
721 + can run on this machine
724 + ATOMIC_xxx values, see my_atomic.h
726 +int my_atomic_initialize()
728 + /* currently the only thing worth checking is SMP/UP issue */
729 +#ifdef MY_ATOMIC_MODE_DUMMY
730 + return my_getncpus() == 1 ? MY_ATOMIC_OK : MY_ATOMIC_NOT_1CPU;
732 + return MY_ATOMIC_OK;
737 === added file 'mysys/my_getncpus.c'
738 --- mysys/my_getncpus.c 1970-01-01 00:00:00 +0000
739 +++ mysys/my_getncpus.c 2006-05-31 16:44:09 +0000
741 +/* Copyright (C) 2006 MySQL AB
743 + This program is free software; you can redistribute it and/or modify
744 + it under the terms of the GNU General Public License as published by
745 + the Free Software Foundation; either version 2 of the License, or
746 + (at your option) any later version.
748 + This program is distributed in the hope that it will be useful,
749 + but WITHOUT ANY WARRANTY; without even the implied warranty of
750 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
751 + GNU General Public License for more details.
753 + You should have received a copy of the GNU General Public License
754 + along with this program; if not, write to the Free Software
755 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
757 +/* get the number of (online) CPUs */
759 +#include "mysys_priv.h"
764 +#ifdef _SC_NPROCESSORS_ONLN
768 + ncpus= sysconf(_SC_NPROCESSORS_ONLN);
782 === added file 'mysys/test_atomic.c'
783 --- mysys/test_atomic.c 1970-01-01 00:00:00 +0000
784 +++ mysys/test_atomic.c 2006-05-31 16:44:09 +0000
786 +#include <my_global.h>
788 +#include <my_atomic.h>
790 +my_atomic_32_t a32,b32,c32;
791 +my_atomic_rwlock_t rwl;
793 +pthread_attr_t thr_attr;
794 +pthread_mutex_t mutex;
795 +pthread_cond_t cond;
798 +/* add and sub a random number in a loop. Must get 0 at the end */
799 +pthread_handler_t test_atomic_add_handler(void *arg)
803 + for (x=((int)(&m)); m ; m--)
806 + my_atomic_add32(&a32, x, &rwl);
807 + my_atomic_add32(&a32, -x, &rwl);
809 + pthread_mutex_lock(&mutex);
811 + if (!N) pthread_cond_signal(&cond);
812 + pthread_mutex_unlock(&mutex);
816 + 1. generate thread number 0..N-1 from b32
818 + 3. swap thread numbers in c32
819 + 4. (optionally) one more swap to avoid 0 as a result
820 + 5. subtract result from a32
821 + must get 0 in a32 at the end
823 +pthread_handler_t test_atomic_swap_handler(void *arg)
826 + uint32 x=my_atomic_add32(&b32, 1, &rwl);
828 + my_atomic_add32(&a32, x, &rwl);
831 + x=my_atomic_swap32(&c32, x,&rwl);
834 + x=my_atomic_swap32(&c32, x,&rwl);
836 + my_atomic_add32(&a32, -x, &rwl);
838 + pthread_mutex_lock(&mutex);
840 + if (!N) pthread_cond_signal(&cond);
841 + pthread_mutex_unlock(&mutex);
845 + same as test_atomic_add_handler, but my_atomic_add32 is emulated with
846 + (slower) my_atomic_cas32
848 +pthread_handler_t test_atomic_cas_handler(void *arg)
852 + for (x=((int)(&m)); m ; m--)
854 + uint32 y=my_atomic_load32(&a32, &rwl);
856 + while (!my_atomic_cas32(&a32, &y, y+x, &rwl)) ;
857 + while (!my_atomic_cas32(&a32, &y, y-x, &rwl)) ;
859 + pthread_mutex_lock(&mutex);
861 + if (!N) pthread_cond_signal(&cond);
862 + pthread_mutex_unlock(&mutex);
865 +void test_atomic(const char *test, pthread_handler handler, int n, int m)
868 + ulonglong now=my_getsystime();
870 + my_atomic_store32(&a32, 0, &rwl);
871 + my_atomic_store32(&b32, 0, &rwl);
872 + my_atomic_store32(&c32, 0, &rwl);
874 + printf("Testing %s with %d threads, %d iterations... ", test, n, m);
875 + for (N=n ; n ; n--)
876 + pthread_create(&t, &thr_attr, handler, &m);
878 + pthread_mutex_lock(&mutex);
880 + pthread_cond_wait(&cond, &mutex);
881 + pthread_mutex_unlock(&mutex);
882 + now=my_getsystime()-now;
883 + printf("got %lu in %g secs\n", my_atomic_load32(&a32, &rwl),
884 + ((double)now)/1e7);
892 + setvbuf(stdout, 0, _IONBF, 0);
894 + printf("N CPUs: %d\n", my_getncpus());
896 + if ((err= my_atomic_initialize()))
898 + printf("my_atomic_initialize() failed. Error=%d\n", err);
902 + pthread_attr_init(&thr_attr);
903 + pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
904 + pthread_mutex_init(&mutex, 0);
905 + pthread_cond_init(&cond, 0);
906 + my_atomic_rwlock_init(&rwl);
908 + test_atomic("my_atomic_add32", test_atomic_add_handler, 100,1000000);
909 + test_atomic("my_atomic_swap32", test_atomic_swap_handler, 100,1000000);
910 + test_atomic("my_atomic_cas32", test_atomic_cas_handler, 100,1000000);
912 + pthread_mutex_destroy(&mutex);
913 + pthread_cond_destroy(&cond);
914 + pthread_attr_destroy(&thr_attr);
915 + my_atomic_rwlock_destroy(&rwl);
919 ------------------------------------------------------------
921 committer: davi@mysql.com/endora.local
922 timestamp: Fri 2008-01-11 20:34:36 -0200
924 Bug#33728 Atomic builtins
926 Use compiler provided atomic builtins as a 'backend' for
927 MySQL's atomic primitives. The builtins are available on
928 a handful of platforms and compilers.
930 === modified file 'configure.in'
931 --- configure.in 2007-12-14 17:03:44 +0000
932 +++ configure.in 2008-01-11 22:34:36 +0000
933 @@ -1688,6 +1688,30 @@
934 *) AC_MSG_ERROR(["$with_atomic_ops" is not a valid value for --with-atomic-ops]) ;;
937 +AC_CACHE_CHECK([whether the compiler provides atomic builtins],
938 + [mysql_cv_gcc_atomic_builtins], [AC_TRY_RUN([
941 + int foo= -10; int bar= 10;
942 + if (!__sync_fetch_and_add(&foo, bar) || foo)
944 + bar= __sync_lock_test_and_set(&foo, bar);
945 + if (bar || foo != 10)
947 + bar= __sync_val_compare_and_swap(&bar, foo, 15);
952 +], [mysql_cv_gcc_atomic_builtins=yes],
953 + [mysql_cv_gcc_atomic_builtins=no],
954 + [mysql_cv_gcc_atomic_builtins=no])])
956 +if test "x$mysql_cv_gcc_atomic_builtins" = xyes; then
957 + AC_DEFINE(HAVE_ATOMIC_BUILTINS, 1,
958 + [Define to 1 if compiler provides atomic builtins.])
961 # Force static compilation to avoid linking problems/get more speed
962 AC_ARG_WITH(mysqld-ldflags,
963 [ --with-mysqld-ldflags Extra linking arguments for mysqld],
965 === added file 'include/atomic/gcc_builtins.h'
966 --- include/atomic/gcc_builtins.h 1970-01-01 00:00:00 +0000
967 +++ include/atomic/gcc_builtins.h 2008-01-11 22:34:36 +0000
969 +/* Copyright (C) 2008 MySQL AB
971 + This program is free software; you can redistribute it and/or modify
972 + it under the terms of the GNU General Public License as published by
973 + the Free Software Foundation; version 2 of the License.
975 + This program is distributed in the hope that it will be useful,
976 + but WITHOUT ANY WARRANTY; without even the implied warranty of
977 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
978 + GNU General Public License for more details.
980 + You should have received a copy of the GNU General Public License
981 + along with this program; if not, write to the Free Software
982 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
984 +#define make_atomic_add_body(S) \
985 + v= __sync_fetch_and_add(a, v);
986 +#define make_atomic_swap_body(S) \
987 + v= __sync_lock_test_and_set(a, v);
988 +#define make_atomic_cas_body(S) \
990 + sav= __sync_val_compare_and_swap(a, *cmp, set); \
991 + if (!(ret= (sav == *cmp))) *cmp= sav;
993 +#ifdef MY_ATOMIC_MODE_DUMMY
994 +#define make_atomic_load_body(S) ret= *a
995 +#define make_atomic_store_body(S) *a= v
997 +#define make_atomic_load_body(S) \
998 + ret= __sync_fetch_and_or(a, 0);
999 +#define make_atomic_store_body(S) \
1000 + (void) __sync_lock_test_and_set(a, v);
1003 === modified file 'include/atomic/nolock.h'
1004 --- include/atomic/nolock.h 2006-12-27 01:23:51 +0000
1005 +++ include/atomic/nolock.h 2008-01-11 22:34:36 +0000
1007 along with this program; if not, write to the Free Software
1008 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
1010 -#if defined(__i386__) || defined(_M_IX86)
1011 +#if defined(__i386__) || defined(_M_IX86) || defined(HAVE_ATOMIC_BUILTINS)
1012 #ifdef MY_ATOMIC_MODE_DUMMY
1015 # define LOCK "lock "
1018 +#ifdef HAVE_ATOMIC_BUILTINS
1019 +#include "gcc_builtins.h"
1021 #include "x86-gcc.h"
1022 #elif defined(_MSC_VER)
1023 #include "x86-msvc.h"