Skip to content

Commit 3289f6e

Browse files
committed
Bug#21221500: ADD SUPPORT FOR GCC __ATOMIC BUILTINS
This patch adds support for the GCC __atomic builtins introduced in GCC 4.7. These new builtins allows a more efficient implementation of the MySQL atomics API. Most importantly the new builtins include functions for atomic load, so that my_atomic_load can be implemented as a real load instead of a store. The new __atomic builtins are only used for platforms where the old GCC __sync builtins are not available. In particular this includes platforms supported by Ubuntu (such as powerpc) where the server would otherwise not build.
1 parent 9930e2f commit 3289f6e

File tree

10 files changed

+196
-19
lines changed

10 files changed

+196
-19
lines changed

cmake/os/WindowsCache.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
22
#
33
# This program is free software; you can redistribute it and/or modify
44
# it under the terms of the GNU General Public License as published by
@@ -210,6 +210,7 @@ SET(HAVE_BUILTIN_UNREACHABLE CACHE INTERNAL "")
210210
SET(HAVE_BUILTIN_EXPECT CACHE INTERNAL "")
211211
SET(HAVE_BUILTIN_STPCPY CACHE INTERNAL "")
212212
SET(HAVE_GCC_ATOMIC_BUILTINS CACHE INTERNAL "")
213+
SET(HAVE_GCC_SYNC_BUILTINS CACHE INTERNAL "")
213214
# Derived result HAVE_VALGRIND
214215

215216
# IPV6

config.h.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@
198198
#cmakedefine HAVE_BUILTIN_EXPECT 1
199199
#cmakedefine HAVE_BUILTIN_STPCPY 1
200200
#cmakedefine HAVE_GCC_ATOMIC_BUILTINS 1
201+
#cmakedefine HAVE_GCC_SYNC_BUILTINS 1
201202
#cmakedefine HAVE_VALGRIND
202203

203204
/* IPV6 */

configure.cmake

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,33 @@ int main()
750750
}" HAVE_BUILTIN_STPCPY)
751751
ENDIF()
752752

753+
CHECK_CXX_SOURCE_COMPILES("
754+
int main()
755+
{
756+
int foo= -10; int bar= 10;
757+
long long int foo64= -10; long long int bar64= 10;
758+
if (!__atomic_fetch_add(&foo, bar, __ATOMIC_SEQ_CST) || foo)
759+
return -1;
760+
bar= __atomic_exchange_n(&foo, bar, __ATOMIC_SEQ_CST);
761+
if (bar || foo != 10)
762+
return -1;
763+
bar= __atomic_compare_exchange_n(&bar, &foo, 15, 0,
764+
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
765+
if (bar)
766+
return -1;
767+
if (!__atomic_fetch_add(&foo64, bar64, __ATOMIC_SEQ_CST) || foo64)
768+
return -1;
769+
bar64= __atomic_exchange_n(&foo64, bar64, __ATOMIC_SEQ_CST);
770+
if (bar64 || foo64 != 10)
771+
return -1;
772+
bar64= __atomic_compare_exchange_n(&bar64, &foo64, 15, 0,
773+
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
774+
if (bar64)
775+
return -1;
776+
return 0;
777+
}"
778+
HAVE_GCC_ATOMIC_BUILTINS)
779+
753780
CHECK_CXX_SOURCE_COMPILES("
754781
int main()
755782
{
@@ -773,7 +800,7 @@ CHECK_CXX_SOURCE_COMPILES("
773800
return -1;
774801
return 0;
775802
}"
776-
HAVE_GCC_ATOMIC_BUILTINS)
803+
HAVE_GCC_SYNC_BUILTINS)
777804

778805
IF(WITH_VALGRIND)
779806
SET(VALGRIND_HEADERS "valgrind/memcheck.h;valgrind/valgrind.h")

include/atomic/gcc_atomic.h

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#ifndef GCC_ATOMIC_INCLUDED
2+
#define GCC_ATOMIC_INCLUDED
3+
4+
/* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
5+
6+
This program is free software; you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation; version 2 of the License.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with this program; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
18+
19+
/* New GCC __atomic builtins introduced in GCC 4.7 */
20+
21+
static inline int my_atomic_cas32(int32 volatile *a, int32 *cmp, int32 set)
22+
{
23+
return __atomic_compare_exchange_n(a, cmp, set, 0,
24+
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
25+
}
26+
27+
static inline int my_atomic_cas64(int64 volatile *a, int64 *cmp, int64 set)
28+
{
29+
return __atomic_compare_exchange_n(a, cmp, set, 0,
30+
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
31+
}
32+
33+
static inline int my_atomic_casptr(void * volatile *a, void **cmp, void *set)
34+
{
35+
return __atomic_compare_exchange_n(a, cmp, set, 0,
36+
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
37+
}
38+
39+
static inline int32 my_atomic_add32(int32 volatile *a, int32 v)
40+
{
41+
return __atomic_fetch_add(a, v, __ATOMIC_SEQ_CST);
42+
}
43+
44+
static inline int64 my_atomic_add64(int64 volatile *a, int64 v)
45+
{
46+
return __atomic_fetch_add(a, v, __ATOMIC_SEQ_CST);
47+
}
48+
49+
static inline int32 my_atomic_fas32(int32 volatile *a, int32 v)
50+
{
51+
return __atomic_exchange_n(a, v, __ATOMIC_SEQ_CST);
52+
}
53+
54+
static inline int64 my_atomic_fas64(int64 volatile *a, int64 v)
55+
{
56+
return __atomic_exchange_n(a, v, __ATOMIC_SEQ_CST);
57+
}
58+
59+
static inline void * my_atomic_fasptr(void * volatile *a, void * v)
60+
{
61+
return __atomic_exchange_n(a, v, __ATOMIC_SEQ_CST);
62+
}
63+
64+
static inline int32 my_atomic_load32(int32 volatile *a)
65+
{
66+
return __atomic_load_n(a, __ATOMIC_SEQ_CST);
67+
}
68+
69+
static inline int64 my_atomic_load64(int64 volatile *a)
70+
{
71+
return __atomic_load_n(a, __ATOMIC_SEQ_CST);
72+
}
73+
74+
static inline void* my_atomic_loadptr(void * volatile *a)
75+
{
76+
return __atomic_load_n(a, __ATOMIC_SEQ_CST);
77+
}
78+
79+
static inline void my_atomic_store32(int32 volatile *a, int32 v)
80+
{
81+
__atomic_store_n(a, v, __ATOMIC_SEQ_CST);
82+
}
83+
84+
static inline void my_atomic_store64(int64 volatile *a, int64 v)
85+
{
86+
__atomic_store_n(a, v, __ATOMIC_SEQ_CST);
87+
}
88+
89+
static inline void my_atomic_storeptr(void * volatile *a, void *v)
90+
{
91+
__atomic_store_n(a, v, __ATOMIC_SEQ_CST);
92+
}
93+
94+
#endif /* GCC_ATOMIC_INCLUDED */

include/atomic/gcc_builtins.h renamed to include/atomic/gcc_sync.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
#ifndef ATOMIC_GCC_BUILTINS_INCLUDED
2-
#define ATOMIC_GCC_BUILTINS_INCLUDED
1+
#ifndef GCC_SYNC_INCLUDED
2+
#define GCC_SYNC_INCLUDED
33

4-
/* Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
4+
/* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
55
66
This program is free software; you can redistribute it and/or modify
77
it under the terms of the GNU General Public License as published by
@@ -16,6 +16,8 @@
1616
along with this program; if not, write to the Free Software
1717
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
1818

19+
/* Old GCC __sync builtins introduced in GCC 4.1 */
20+
1921
static inline int my_atomic_cas32(int32 volatile *a, int32 *cmp, int32 set)
2022
{
2123
int32 cmp_val= *cmp;
@@ -101,4 +103,4 @@ static inline void my_atomic_storeptr(void * volatile *a, void *v)
101103
(void) __sync_lock_test_and_set(a, v);
102104
}
103105

104-
#endif /* ATOMIC_GCC_BUILTINS_INCLUDED */
106+
#endif /* GCC_SYNC_INCLUDED */

include/my_atomic.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef MY_ATOMIC_INCLUDED
22
#define MY_ATOMIC_INCLUDED
33

4-
/* Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
4+
/* Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
55
66
This program is free software; you can redistribute it and/or modify
77
it under the terms of the GNU General Public License as published by
@@ -56,8 +56,10 @@
5656
# include "atomic/generic-msvc.h"
5757
#elif defined(HAVE_SOLARIS_ATOMIC)
5858
# include "atomic/solaris.h"
59-
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
60-
# include "atomic/gcc_builtins.h"
59+
#elif defined(HAVE_GCC_SYNC_BUILTINS) /* Use old __sync by default */
60+
# include "atomic/gcc_sync.h"
61+
#elif defined(HAVE_GCC_ATOMIC_BUILTINS) /* Use __atomic on e.g. powerpc */
62+
# include "atomic/gcc_atomic.h"
6163
#else
6264
# error Native atomics support not found!
6365
#endif

mysys/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
22
#
33
# This program is free software; you can redistribute it and/or modify
44
# it under the terms of the GNU General Public License as published by
@@ -66,7 +66,7 @@ ENDIF()
6666

6767
ADD_CONVENIENCE_LIBRARY(mysys ${MYSYS_SOURCES})
6868
TARGET_LINK_LIBRARIES(mysys dbug strings ${ZLIB_LIBRARY}
69-
${LIBNSL} ${LIBM} ${LIBRT})
69+
${LIBNSL} ${LIBM} ${LIBRT} ${LIBATOMIC})
7070
DTRACE_INSTRUMENT(mysys)
7171

7272
# Need explicit pthread for gcc -fsanitize=address

plugin/innodb_memcached/daemon_memcached/daemon/memcached.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
* memcached - memory caching daemon
44
*
55
* http://www.danga.com/memcached/
6-
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
6+
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
77
* Copyright 2003 Danga Interactive, Inc. All rights reserved.
8-
* This file was modified by Oracle on 28-08-2015.
9-
* Modifications copyright (c) 2015, Oracle and/or its affiliates.
8+
* This file was modified by Oracle on 28-08-2015 and 23-03-2016.
9+
* Modifications copyright (c) 2015, 2016, Oracle and/or its affiliates.
1010
* All rights reserved.
1111
*
1212
* Use and distribution licensed under the BSD license. See
@@ -89,7 +89,7 @@ static inline void item_set_cas(const void *cookie, item *it, uint64_t cas) {
8989
#define STATS_MISS(conn, op, key, nkey) \
9090
STATS_TWO(conn, op##_misses, cmd_##op, key, nkey)
9191

92-
#if defined(HAVE_GCC_ATOMIC_BUILTINS)
92+
#if defined(HAVE_GCC_SYNC_BUILTINS)
9393

9494
#define STATS_NOKEY(conn, op) \
9595
do { \
@@ -115,7 +115,7 @@ do { \
115115

116116
#define MEMCACHED_ATOMIC_MSG "InnoDB MEMCACHED: Memcached uses atomic increment \n"
117117

118-
#else /* HAVE_GCC_ATOMIC_BUILTINS */
118+
#else /* HAVE_GCC_SYNC_BUILTINS */
119119
#define STATS_NOKEY(conn, op) { \
120120
struct thread_stats *thread_stats = \
121121
get_thread_stats(conn); \
@@ -142,7 +142,7 @@ do { \
142142
}
143143

144144
#define MEMCACHED_ATOMIC_MSG "InnoDB Memcached: Memcached DOES NOT use atomic increment"
145-
#endif /* HAVE_GCC_ATOMIC_BUILTINS */
145+
#endif /* HAVE_GCC_SYNC_BUILTINS */
146146

147147
volatile sig_atomic_t memcached_shutdown;
148148
volatile sig_atomic_t memcached_initialized;

plugin/innodb_memcached/innodb_memcache/src/innodb_api.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,7 @@ mci_get_cas(
938938
{
939939
static uint64_t cas_id = 0;
940940

941-
#if defined(HAVE_GCC_ATOMIC_BUILTINS)
941+
#if defined(HAVE_GCC_SYNC_BUILTINS)
942942
return(__sync_add_and_fetch(&cas_id, 1));
943943
#else
944944
pthread_mutex_lock(&eng->cas_mutex);

storage/innobase/include/os0atomic.h

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*****************************************************************************
2-
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
2+
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
33
Copyright (c) 2008, Google Inc.
44
55
Portions of this file contain modifications contributed and copyrighted by
@@ -208,6 +208,8 @@ amount to decrement. There is no atomic substract function on Windows */
208208
Returns true if swapped, ptr is pointer to target, old_val is value to
209209
compare to, new_val is the value to swap in. */
210210

211+
#if defined(HAVE_GCC_SYNC_BUILTINS)
212+
211213
# define os_compare_and_swap(ptr, old_val, new_val) \
212214
__sync_bool_compare_and_swap(ptr, old_val, new_val)
213215

@@ -220,9 +222,47 @@ compare to, new_val is the value to swap in. */
220222
# define os_compare_and_swap_uint32(ptr, old_val, new_val) \
221223
os_compare_and_swap(ptr, old_val, new_val)
222224

225+
#else
226+
227+
UNIV_INLINE
228+
bool
229+
os_compare_and_swap_ulint(volatile ulint* ptr, ulint old_val, ulint new_val)
230+
{
231+
return __atomic_compare_exchange_n(ptr, &old_val, new_val, 0,
232+
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
233+
}
234+
235+
UNIV_INLINE
236+
bool
237+
os_compare_and_swap_lint(volatile lint* ptr, lint old_val, lint new_val)
238+
{
239+
return __atomic_compare_exchange_n(ptr, &old_val, new_val, 0,
240+
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
241+
}
242+
243+
UNIV_INLINE
244+
bool
245+
os_compare_and_swap_uint32(volatile ib_uint32_t* ptr, ib_uint32_t old_val, ib_uint32_t new_val)
246+
{
247+
return __atomic_compare_exchange_n(ptr, &old_val, new_val, 0,
248+
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
249+
}
250+
251+
#endif /* HAVE_GCC_SYNC_BUILTINS */
252+
223253
# ifdef HAVE_IB_ATOMIC_PTHREAD_T_GCC
254+
#if defined(HAVE_GCC_SYNC_BUILTINS)
224255
# define os_compare_and_swap_thread_id(ptr, old_val, new_val) \
225256
os_compare_and_swap(ptr, old_val, new_val)
257+
#else
258+
UNIV_INLINE
259+
bool
260+
os_compare_and_swap_thread_id(volatile os_thread_id_t* ptr, os_thread_id_t old_val, os_thread_id_t new_val)
261+
{
262+
return __atomic_compare_exchange_n(ptr, &old_val, new_val, 0,
263+
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
264+
}
265+
#endif /* HAVE_GCC_SYNC_BUILTINS */
226266
# define INNODB_RW_LOCKS_USE_ATOMICS
227267
# define IB_ATOMICS_STARTUP_MSG \
228268
"Mutexes and rw_locks use GCC atomic builtins"
@@ -235,8 +275,13 @@ compare to, new_val is the value to swap in. */
235275
Returns the resulting value, ptr is pointer to target, amount is the
236276
amount of increment. */
237277

278+
#if defined(HAVE_GCC_SYNC_BUILTINS)
238279
# define os_atomic_increment(ptr, amount) \
239280
__sync_add_and_fetch(ptr, amount)
281+
#else
282+
# define os_atomic_increment(ptr, amount) \
283+
__atomic_add_fetch(ptr, amount, __ATOMIC_SEQ_CST)
284+
#endif /* HAVE_GCC_SYNC_BUILTINS */
240285

241286
# define os_atomic_increment_lint(ptr, amount) \
242287
os_atomic_increment(ptr, amount)
@@ -253,8 +298,13 @@ amount of increment. */
253298
/* Returns the resulting value, ptr is pointer to target, amount is the
254299
amount to decrement. */
255300

301+
#if defined(HAVE_GCC_SYNC_BUILTINS)
256302
# define os_atomic_decrement(ptr, amount) \
257303
__sync_sub_and_fetch(ptr, amount)
304+
#else
305+
# define os_atomic_decrement(ptr, amount) \
306+
__atomic_sub_fetch(ptr, amount, __ATOMIC_SEQ_CST)
307+
#endif /* HAVE_GCC_SYNC_BUILTINS */
258308

259309
# define os_atomic_decrement_lint(ptr, amount) \
260310
os_atomic_decrement(ptr, amount)

0 commit comments

Comments
 (0)