Merge lp:~percona-dev/percona-server/atomic-fixes-51 into lp:~percona-dev/percona-server/5.1.57

Proposed by Laurynas Biveinis
Status: Superseded
Proposed branch: lp:~percona-dev/percona-server/atomic-fixes-51
Merge into: lp:~percona-dev/percona-server/5.1.57
Diff against target: 1468 lines (+1318/-93)
1 file modified
response-time-distribution.patch (+1318/-93)
To merge this branch: bzr merge lp:~percona-dev/percona-server/atomic-fixes-51
Reviewer Review Type Date Requested Status
Oleg Tsarev (community) Approve
Valentine Gostev qa Pending
Review via email: mp+63655@code.launchpad.net

This proposal has been superseded by a proposal from 2011-06-09.

Description of the change

Fix LP bug 737947: unportable atomic constructs break build on various platforms.

The fix is to remove query_response_time.cc-specific atomic code, and use MySQL primitives in my_atomic.h backported from MySQL 5.5 together with updated configure.in logic for GCC and Solaris atomic primitives detection. This way the portability is not limited in any way by the patch as well as minimizing future maintainenance burden.

To post a comment you must log in.
Revision history for this message
Oleg Tsarev (tsarev) wrote :

Looks good for me
But you should also request QA review

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'response-time-distribution.patch'
2--- response-time-distribution.patch 2011-05-12 11:00:37 +0000
3+++ response-time-distribution.patch 2011-06-07 07:56:14 +0000
4@@ -222,12 +222,9 @@
5 diff -ruN a/sql/query_response_time.cc b/sql/query_response_time.cc
6 --- a/sql/query_response_time.cc 1970-01-01 00:00:00.000000000 +0000
7 +++ b/sql/query_response_time.cc 2010-11-02 15:34:52.000000000 +0000
8-@@ -0,0 +1,369 @@
9-+#ifdef __FreeBSD__
10-+#include <sys/types.h>
11-+#include <machine/atomic.h>
12-+#endif // __FreeBSD__
13+@@ -0,0 +1,313 @@
14 +#include "my_global.h"
15++#include "my_atomic.h"
16 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
17 +#include "mysql_priv.h"
18 +#include "mysql_com.h"
19@@ -378,104 +375,45 @@
20 + }
21 + buffer[result_length]= 0;
22 +}
23-+#ifdef __x86_64__
24-+typedef uint64 TimeCounter;
25-+void add_time_atomic(TimeCounter* counter, uint64 time)
26-+{
27-+ __sync_fetch_and_add(counter,time);
28-+}
29-+#endif // __x86_64__
30-+#ifdef __i386__
31-+inline uint32 get_high(uint64 value)
32-+{
33-+ return ((value >> 32) << 32);
34-+}
35-+inline uint32 get_low(uint64 value)
36-+{
37-+ return ((value << 32) >> 32);
38-+}
39-+#ifdef __FreeBSD__
40-+inline bool compare_and_swap(volatile uint32 *target, uint32 old, uint32 new_value)
41-+{
42-+ return atomic_cmpset_32(target,old,new_value);
43-+}
44-+#else // __FreeBSD__
45-+inline bool compare_and_swap(volatile uint32* target, uint32 old, uint32 new_value)
46-+{
47-+ return __sync_bool_compare_and_swap(target,old,new_value);
48-+}
49-+#endif // __FreeBSD__
50-+class TimeCounter
51-+{
52-+public:
53-+ TimeCounter& operator=(uint64 time)
54-+ {
55-+ this->m_high= get_high(time);
56-+ this->m_low= get_low(time);
57-+ return *this;
58-+ }
59-+ operator uint64() const
60-+ {
61-+ return ((static_cast<uint64>(m_high) << 32) + static_cast<uint64>(m_low));
62-+ }
63-+ void add(uint64 time)
64-+ {
65-+ uint32 time_high = get_high(time);
66-+ uint32 time_low = get_low(time);
67-+ uint64 time_low64= time_low;
68-+ while(true)
69-+ {
70-+ uint32 old_low= this->m_low;
71-+ uint64 old_low64= old_low;
72-+
73-+ uint64 new_low64= old_low64 + time_low64;
74-+ uint32 new_low= (get_low(new_low64));
75-+ bool add_high= (get_high(new_low64) != 0);
76-+
77-+ if(!compare_and_swap(&m_low,old_low,new_low))
78-+ {
79-+ continue;
80-+ }
81-+ if(add_high)
82-+ {
83-+ ++time_high;
84-+ }
85-+ if(time_high > 0)
86-+ {
87-+ __sync_fetch_and_add(&m_high,time_high);
88-+ }
89-+ break;
90-+ }
91-+ }
92-+private:
93-+ uint32 m_low;
94-+ uint32 m_high;
95-+};
96-+void add_time_atomic(TimeCounter* counter, uint64 time)
97-+{
98-+ counter->add(time);
99-+}
100-+#endif // __i386__
101 +
102 +class time_collector
103 +{
104 +public:
105 + time_collector(utility& u) : m_utility(&u)
106 + {
107-+ }
108-+ uint32 count(uint index) const { return m_count[index]; }
109-+ uint64 total(uint index) const { return m_total[index]; }
110++ my_atomic_rwlock_init(&time_collector_lock);
111++ }
112++ ~time_collector()
113++ {
114++ my_atomic_rwlock_destroy(&time_collector_lock);
115++ }
116++ uint32 count(uint index) const
117++ {
118++ my_atomic_rwlock_rdlock(&time_collector_lock);
119++ uint32 result= my_atomic_load32((volatile int32*)&m_count[index]);
120++ my_atomic_rwlock_rdunlock(&time_collector_lock);
121++ return result;
122++ }
123++ uint64 total(uint index) const
124++ {
125++ my_atomic_rwlock_rdlock(&time_collector_lock);
126++ uint64 result= my_atomic_load64((volatile int64*)&m_total[index]);
127++ my_atomic_rwlock_rdunlock(&time_collector_lock);
128++ return result;
129++ }
130 +public:
131 + void flush()
132 + {
133-+ memset(&m_count,0,sizeof(m_count));
134++ my_atomic_rwlock_wrlock(&time_collector_lock);
135++ memset((void*)&m_count,0,sizeof(m_count));
136 + memset((void*)&m_total,0,sizeof(m_total));
137++ my_atomic_rwlock_wrunlock(&time_collector_lock);
138 + }
139 + void collect(uint64 time)
140 + {
141 + bool no_collect= false;
142 + DBUG_EXECUTE_IF("response_time_distribution_log_only_more_300_milliseconds", { \
143-+ no_collect= time < 300 * 1000; \
144++ no_collect= time < 300 * 1000; \
145 + });
146 + if(no_collect) return;
147 + int i= 0;
148@@ -483,16 +421,22 @@
149 + {
150 + if(m_utility->bound(i) > time)
151 + {
152-+ __sync_fetch_and_add(&(m_count[i]),(uint32)1);
153-+ add_time_atomic(&(m_total[i]),time);
154++ my_atomic_rwlock_wrlock(&time_collector_lock);
155++ my_atomic_add32((volatile int32*)(&m_count[i]), 1);
156++ my_atomic_add64((volatile int64*)(&m_total[i]), time);
157++ my_atomic_rwlock_wrunlock(&time_collector_lock);
158 + break;
159 + }
160 + }
161 + }
162 +private:
163 + utility* m_utility;
164-+ uint32 m_count[OVERALL_POWER_COUNT + 1];
165-+ TimeCounter m_total[OVERALL_POWER_COUNT + 1];
166++ /* The lock for atomic operations on m_count and m_total. Only actually
167++ used on architectures that do not have atomic implementation of atomic
168++ operations. */
169++ my_atomic_rwlock_t time_collector_lock;
170++ volatile uint32 m_count[OVERALL_POWER_COUNT + 1];
171++ volatile uint64 m_total[OVERALL_POWER_COUNT + 1];
172 +};
173 +
174 +class collector
175@@ -869,7 +813,77 @@
176 diff -ruN a/configure.in b/configure.in
177 --- a/configure.in 2010-12-07 19:19:42.000000000 +0300
178 +++ b/configure.in 2010-12-07 19:21:39.000000000 +0300
179-@@ -2687,7 +2687,16 @@
180+@@ -1738,6 +1738,7 @@
181+ int main()
182+ {
183+ int foo= -10; int bar= 10;
184++ long long int foo64= -10; long long int bar64= 10;
185+ if (!__sync_fetch_and_add(&foo, bar) || foo)
186+ return -1;
187+ bar= __sync_lock_test_and_set(&foo, bar);
188+@@ -1746,6 +1747,14 @@
189+ bar= __sync_val_compare_and_swap(&bar, foo, 15);
190+ if (bar)
191+ return -1;
192++ if (!__sync_fetch_and_add(&foo64, bar64) || foo64)
193++ return -1;
194++ bar64= __sync_lock_test_and_set(&foo64, bar64);
195++ if (bar64 || foo64 != 10)
196++ return -1;
197++ bar64= __sync_val_compare_and_swap(&bar64, foo, 15);
198++ if (bar64)
199++ return -1;
200+ return 0;
201+ }
202+ ], [mysql_cv_gcc_atomic_builtins=yes],
203+@@ -1757,6 +1766,46 @@
204+ [Define to 1 if compiler provides atomic builtins.])
205+ fi
206+
207++AC_CACHE_CHECK([whether the OS provides atomic_* functions like Solaris],
208++ [mysql_cv_solaris_atomic],
209++ [AC_RUN_IFELSE(
210++ [AC_LANG_PROGRAM(
211++ [[
212++ #include <atomic.h>
213++ ]],
214++ [[
215++ int foo = -10; int bar = 10;
216++ int64_t foo64 = -10; int64_t bar64 = 10;
217++ if (atomic_add_int_nv((uint_t *)&foo, bar) || foo)
218++ return -1;
219++ bar = atomic_swap_uint((uint_t *)&foo, (uint_t)bar);
220++ if (bar || foo != 10)
221++ return -1;
222++ bar = atomic_cas_uint((uint_t *)&bar, (uint_t)foo, 15);
223++ if (bar)
224++ return -1;
225++ if (atomic_add_64_nv((volatile uint64_t *)&foo64, bar64) || foo64)
226++ return -1;
227++ bar64 = atomic_swap_64((volatile uint64_t *)&foo64, (uint64_t)bar64);
228++ if (bar64 || foo64 != 10)
229++ return -1;
230++ bar64 = atomic_cas_64((volatile uint64_t *)&bar64, (uint_t)foo64, 15);
231++ if (bar64)
232++ return -1;
233++ atomic_or_64((volatile uint64_t *)&bar64, 0);
234++ return 0;
235++ ]]
236++ )],
237++ [mysql_cv_solaris_atomic=yes],
238++ [mysql_cv_solaris_atomic=no],
239++ [mysql_cv_solaris_atomic=no]
240++)])
241++
242++if test "x$mysql_cv_solaris_atomic" = xyes; then
243++ AC_DEFINE(HAVE_SOLARIS_ATOMIC, 1,
244++ [Define to 1 if OS provides atomic_* functions like Solaris.])
245++fi
246++
247+ # Force static compilation to avoid linking problems/get more speed
248+ AC_ARG_WITH(mysqld-ldflags,
249+ [ --with-mysqld-ldflags Extra linking arguments for mysqld],
250+@@ -2687,7 +2736,16 @@
251 AC_SUBST(readline_link)
252 AC_SUBST(readline_h_ln_cmd)
253
254@@ -886,3 +900,1214 @@
255
256 # Include man pages, if desired, adapted to the configured parts.
257 if test X"$with_man" = Xyes
258+diff -ruN /dev/null b/include/my_atomic.h
259+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
260++++ b/include/my_atomic.h 2011-06-07 08:59:00.000000000 +0300
261+@@ -0,0 +1,287 @@
262++#ifndef MY_ATOMIC_INCLUDED
263++#define MY_ATOMIC_INCLUDED
264++
265++/* Copyright (C) 2006 MySQL AB
266++
267++ This program is free software; you can redistribute it and/or modify
268++ it under the terms of the GNU General Public License as published by
269++ the Free Software Foundation; version 2 of the License.
270++
271++ This program is distributed in the hope that it will be useful,
272++ but WITHOUT ANY WARRANTY; without even the implied warranty of
273++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
274++ GNU General Public License for more details.
275++
276++ You should have received a copy of the GNU General Public License
277++ along with this program; if not, write to the Free Software
278++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
279++
280++/*
281++ This header defines five atomic operations:
282++
283++ my_atomic_add#(&var, what)
284++ 'Fetch and Add'
285++ add 'what' to *var, and return the old value of *var
286++
287++ my_atomic_fas#(&var, what)
288++ 'Fetch And Store'
289++ store 'what' in *var, and return the old value of *var
290++
291++ my_atomic_cas#(&var, &old, new)
292++ An odd variation of 'Compare And Set/Swap'
293++ if *var is equal to *old, then store 'new' in *var, and return TRUE
294++ otherwise store *var in *old, and return FALSE
295++ Usually, &old should not be accessed if the operation is successful.
296++
297++ my_atomic_load#(&var)
298++ return *var
299++
300++ my_atomic_store#(&var, what)
301++ store 'what' in *var
302++
303++ '#' is substituted by a size suffix - 8, 16, 32, 64, or ptr
304++ (e.g. my_atomic_add8, my_atomic_fas32, my_atomic_casptr).
305++
306++ NOTE This operations are not always atomic, so they always must be
307++ enclosed in my_atomic_rwlock_rdlock(lock)/my_atomic_rwlock_rdunlock(lock)
308++ or my_atomic_rwlock_wrlock(lock)/my_atomic_rwlock_wrunlock(lock).
309++ Hint: if a code block makes intensive use of atomic ops, it make sense
310++ to take/release rwlock once for the whole block, not for every statement.
311++
312++ On architectures where these operations are really atomic, rwlocks will
313++ be optimized away.
314++ 8- and 16-bit atomics aren't implemented for windows (see generic-msvc.h),
315++ but can be added, if necessary.
316++*/
317++
318++#ifndef my_atomic_rwlock_init
319++
320++#define intptr void *
321++/**
322++ Currently we don't support 8-bit and 16-bit operations.
323++ It can be added later if needed.
324++*/
325++#undef MY_ATOMIC_HAS_8_16
326++
327++#ifndef MY_ATOMIC_MODE_RWLOCKS
328++/*
329++ * Attempt to do atomic ops without locks
330++ */
331++#include "atomic/nolock.h"
332++#endif
333++
334++#ifndef make_atomic_cas_body
335++/* nolock.h was not able to generate even a CAS function, fall back */
336++#include "atomic/rwlock.h"
337++#endif
338++
339++/* define missing functions by using the already generated ones */
340++#ifndef make_atomic_add_body
341++#define make_atomic_add_body(S) \
342++ int ## S tmp=*a; \
343++ while (!my_atomic_cas ## S(a, &tmp, tmp+v)) ; \
344++ v=tmp;
345++#endif
346++#ifndef make_atomic_fas_body
347++#define make_atomic_fas_body(S) \
348++ int ## S tmp=*a; \
349++ while (!my_atomic_cas ## S(a, &tmp, v)) ; \
350++ v=tmp;
351++#endif
352++#ifndef make_atomic_load_body
353++#define make_atomic_load_body(S) \
354++ ret= 0; /* avoid compiler warning */ \
355++ (void)(my_atomic_cas ## S(a, &ret, ret));
356++#endif
357++#ifndef make_atomic_store_body
358++#define make_atomic_store_body(S) \
359++ (void)(my_atomic_fas ## S (a, v));
360++#endif
361++
362++/*
363++ transparent_union doesn't work in g++
364++ Bug ?
365++
366++ Darwin's gcc doesn't want to put pointers in a transparent_union
367++ when built with -arch ppc64. Complains:
368++ warning: 'transparent_union' attribute ignored
369++*/
370++#if defined(__GNUC__) && !defined(__cplusplus) && \
371++ ! (defined(__APPLE__) && (defined(_ARCH_PPC64) ||defined (_ARCH_PPC)))
372++/*
373++ we want to be able to use my_atomic_xxx functions with
374++ both signed and unsigned integers. But gcc will issue a warning
375++ "passing arg N of `my_atomic_XXX' as [un]signed due to prototype"
376++ if the signedness of the argument doesn't match the prototype, or
377++ "pointer targets in passing argument N of my_atomic_XXX differ in signedness"
378++ if int* is used where uint* is expected (or vice versa).
379++ Let's shut these warnings up
380++*/
381++#define make_transparent_unions(S) \
382++ typedef union { \
383++ int ## S i; \
384++ uint ## S u; \
385++ } U_ ## S __attribute__ ((transparent_union)); \
386++ typedef union { \
387++ int ## S volatile *i; \
388++ uint ## S volatile *u; \
389++ } Uv_ ## S __attribute__ ((transparent_union));
390++#define uintptr intptr
391++make_transparent_unions(8)
392++make_transparent_unions(16)
393++make_transparent_unions(32)
394++make_transparent_unions(64)
395++make_transparent_unions(ptr)
396++#undef uintptr
397++#undef make_transparent_unions
398++#define a U_a.i
399++#define cmp U_cmp.i
400++#define v U_v.i
401++#define set U_set.i
402++#else
403++#define U_8 int8
404++#define U_16 int16
405++#define U_32 int32
406++#define U_64 int64
407++#define U_ptr intptr
408++#define Uv_8 int8
409++#define Uv_16 int16
410++#define Uv_32 int32
411++#define Uv_64 int64
412++#define Uv_ptr intptr
413++#define U_a volatile *a
414++#define U_cmp *cmp
415++#define U_v v
416++#define U_set set
417++#endif /* __GCC__ transparent_union magic */
418++
419++#define make_atomic_cas(S) \
420++static inline int my_atomic_cas ## S(Uv_ ## S U_a, \
421++ Uv_ ## S U_cmp, U_ ## S U_set) \
422++{ \
423++ int8 ret; \
424++ make_atomic_cas_body(S); \
425++ return ret; \
426++}
427++
428++#define make_atomic_add(S) \
429++static inline int ## S my_atomic_add ## S( \
430++ Uv_ ## S U_a, U_ ## S U_v) \
431++{ \
432++ make_atomic_add_body(S); \
433++ return v; \
434++}
435++
436++#define make_atomic_fas(S) \
437++static inline int ## S my_atomic_fas ## S( \
438++ Uv_ ## S U_a, U_ ## S U_v) \
439++{ \
440++ make_atomic_fas_body(S); \
441++ return v; \
442++}
443++
444++#define make_atomic_load(S) \
445++static inline int ## S my_atomic_load ## S(Uv_ ## S U_a) \
446++{ \
447++ int ## S ret; \
448++ make_atomic_load_body(S); \
449++ return ret; \
450++}
451++
452++#define make_atomic_store(S) \
453++static inline void my_atomic_store ## S( \
454++ Uv_ ## S U_a, U_ ## S U_v) \
455++{ \
456++ make_atomic_store_body(S); \
457++}
458++
459++#ifdef MY_ATOMIC_HAS_8_16
460++make_atomic_cas(8)
461++make_atomic_cas(16)
462++#endif
463++make_atomic_cas(32)
464++make_atomic_cas(64)
465++make_atomic_cas(ptr)
466++
467++#ifdef MY_ATOMIC_HAS_8_16
468++make_atomic_add(8)
469++make_atomic_add(16)
470++#endif
471++make_atomic_add(32)
472++make_atomic_add(64)
473++
474++#ifdef MY_ATOMIC_HAS_8_16
475++make_atomic_load(8)
476++make_atomic_load(16)
477++#endif
478++make_atomic_load(32)
479++make_atomic_load(64)
480++make_atomic_load(ptr)
481++
482++#ifdef MY_ATOMIC_HAS_8_16
483++make_atomic_fas(8)
484++make_atomic_fas(16)
485++#endif
486++make_atomic_fas(32)
487++make_atomic_fas(64)
488++make_atomic_fas(ptr)
489++
490++#ifdef MY_ATOMIC_HAS_8_16
491++make_atomic_store(8)
492++make_atomic_store(16)
493++#endif
494++make_atomic_store(32)
495++make_atomic_store(64)
496++make_atomic_store(ptr)
497++
498++#ifdef _atomic_h_cleanup_
499++#include _atomic_h_cleanup_
500++#undef _atomic_h_cleanup_
501++#endif
502++
503++#undef U_8
504++#undef U_16
505++#undef U_32
506++#undef U_64
507++#undef U_ptr
508++#undef Uv_8
509++#undef Uv_16
510++#undef Uv_32
511++#undef Uv_64
512++#undef Uv_ptr
513++#undef a
514++#undef cmp
515++#undef v
516++#undef set
517++#undef U_a
518++#undef U_cmp
519++#undef U_v
520++#undef U_set
521++#undef make_atomic_add
522++#undef make_atomic_cas
523++#undef make_atomic_load
524++#undef make_atomic_store
525++#undef make_atomic_fas
526++#undef make_atomic_add_body
527++#undef make_atomic_cas_body
528++#undef make_atomic_load_body
529++#undef make_atomic_store_body
530++#undef make_atomic_fas_body
531++#undef intptr
532++
533++/*
534++ the macro below defines (as an expression) the code that
535++ will be run in spin-loops. Intel manuals recummend to have PAUSE there.
536++ It is expected to be defined in include/atomic/ *.h files
537++*/
538++#ifndef LF_BACKOFF
539++#define LF_BACKOFF (1)
540++#endif
541++
542++#define MY_ATOMIC_OK 0
543++#define MY_ATOMIC_NOT_1CPU 1
544++extern int my_atomic_initialize();
545++
546++#endif
547++
548++#endif /* MY_ATOMIC_INCLUDED */
549+diff -ruN a/mysys/Makefile.am b/mysys/Makefile.am
550+--- a/mysys/Makefile.am 2011-04-12 15:11:35.000000000 +0300
551++++ b/mysys/Makefile.am 2011-06-07 08:59:00.432197996 +0300
552+@@ -51,7 +51,8 @@
553+ rijndael.c my_aes.c sha1.c \
554+ my_compare.c my_netware.c my_largepage.c \
555+ my_memmem.c stacktrace.c \
556+- my_windac.c my_access.c base64.c my_libwrap.c
557++ my_windac.c my_access.c base64.c my_libwrap.c \
558++ my_atomic.c
559+
560+ if NEED_THREAD
561+ # mf_keycache is used only in the server, so it is safe to leave the file
562+diff -ruN a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt
563+--- a/mysys/CMakeLists.txt 2011-04-12 15:11:35.000000000 +0300
564++++ b/mysys/CMakeLists.txt 2011-06-07 08:59:00.432197996 +0300
565+@@ -41,7 +41,8 @@
566+ my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c my_wincond.c
567+ my_windac.c my_winthread.c my_write.c ptr_cmp.c queues.c stacktrace.c
568+ rijndael.c safemalloc.c sha1.c string.c thr_alarm.c thr_lock.c thr_mutex.c
569+- thr_rwlock.c tree.c typelib.c my_vle.c base64.c my_memmem.c my_getpagesize.c)
570++ thr_rwlock.c tree.c typelib.c my_vle.c base64.c my_memmem.c my_getpagesize.c
571++ my_atomic.c)
572+
573+ IF(NOT SOURCE_SUBLIBS)
574+ ADD_LIBRARY(mysys ${MYSYS_SOURCES})
575+diff -ruN a/include/Makefile.am b/include/Makefile.am
576+--- a/include/Makefile.am 2011-04-12 15:11:35.000000000 +0300
577++++ b/include/Makefile.am 2011-06-07 08:59:00.432197996 +0300
578+@@ -38,7 +38,10 @@
579+ my_aes.h my_tree.h my_trie.h hash.h thr_alarm.h \
580+ thr_lock.h t_ctype.h violite.h my_md5.h base64.h \
581+ my_compare.h my_time.h my_vle.h my_user.h \
582+- my_libwrap.h my_stacktrace.h
583++ my_libwrap.h my_stacktrace.h my_atomic.h \
584++ atomic/gcc_builtins.h atomic/generic-msvc.h \
585++ atomic/nolock.h atomic/rwlock.h atomic/solaris.h \
586++ atomic/x86-gcc.h
587+
588+ EXTRA_DIST = mysql.h.pp mysql/plugin.h.pp
589+
590+diff -ruN /dev/null b/include/atomic/gcc_builtins.h
591+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
592++++ b/include/atomic/gcc_builtins.h 2011-06-07 08:59:00.000000000 +0300
593+@@ -0,0 +1,42 @@
594++#ifndef ATOMIC_GCC_BUILTINS_INCLUDED
595++#define ATOMIC_GCC_BUILTINS_INCLUDED
596++
597++/* Copyright (C) 2008 MySQL AB
598++
599++ This program is free software; you can redistribute it and/or modify
600++ it under the terms of the GNU General Public License as published by
601++ the Free Software Foundation; version 2 of the License.
602++
603++ This program is distributed in the hope that it will be useful,
604++ but WITHOUT ANY WARRANTY; without even the implied warranty of
605++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
606++ GNU General Public License for more details.
607++
608++ You should have received a copy of the GNU General Public License
609++ along with this program; if not, write to the Free Software
610++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
611++
612++#define make_atomic_add_body(S) \
613++ v= __sync_fetch_and_add(a, v);
614++#define make_atomic_fas_body(S) \
615++ v= __sync_lock_test_and_set(a, v);
616++#define make_atomic_cas_body(S) \
617++ int ## S sav; \
618++ int ## S cmp_val= *cmp; \
619++ sav= __sync_val_compare_and_swap(a, cmp_val, set);\
620++ if (!(ret= (sav == cmp_val))) *cmp= sav
621++
622++#ifdef MY_ATOMIC_MODE_DUMMY
623++#define make_atomic_load_body(S) ret= *a
624++#define make_atomic_store_body(S) *a= v
625++#define MY_ATOMIC_MODE "gcc-builtins-up"
626++
627++#else
628++#define MY_ATOMIC_MODE "gcc-builtins-smp"
629++#define make_atomic_load_body(S) \
630++ ret= __sync_fetch_and_or(a, 0);
631++#define make_atomic_store_body(S) \
632++ (void) __sync_lock_test_and_set(a, v);
633++#endif
634++
635++#endif /* ATOMIC_GCC_BUILTINS_INCLUDED */
636+diff -ruN /dev/null b/include/atomic/generic-msvc.h
637+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
638++++ b/include/atomic/generic-msvc.h 2011-06-07 08:59:00.000000000 +0300
639+@@ -0,0 +1,134 @@
640++/* Copyright (C) 2006-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
641++
642++ This program is free software; you can redistribute it and/or modify
643++ it under the terms of the GNU General Public License as published by
644++ the Free Software Foundation; version 2 of the License.
645++
646++ This program is distributed in the hope that it will be useful,
647++ but WITHOUT ANY WARRANTY; without even the implied warranty of
648++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
649++ GNU General Public License for more details.
650++
651++ You should have received a copy of the GNU General Public License
652++ along with this program; if not, write to the Free Software
653++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
654++
655++#ifndef _atomic_h_cleanup_
656++#define _atomic_h_cleanup_ "atomic/generic-msvc.h"
657++
658++/*
659++ We don't implement anything specific for MY_ATOMIC_MODE_DUMMY, always use
660++ intrinsics.
661++ 8 and 16-bit atomics are not implemented, but it can be done if necessary.
662++*/
663++#undef MY_ATOMIC_HAS_8_16
664++
665++#include <windows.h>
666++/*
667++ x86 compilers (both VS2003 or VS2005) never use instrinsics, but generate
668++ function calls to kernel32 instead, even in the optimized build.
669++ We force intrinsics as described in MSDN documentation for
670++ _InterlockedCompareExchange.
671++*/
672++#ifdef _M_IX86
673++
674++#if (_MSC_VER >= 1500)
675++#include <intrin.h>
676++#else
677++C_MODE_START
678++/*Visual Studio 2003 and earlier do not have prototypes for atomic intrinsics*/
679++LONG _InterlockedCompareExchange (LONG volatile *Target, LONG Value, LONG Comp);
680++LONGLONG _InterlockedCompareExchange64 (LONGLONG volatile *Target,
681++ LONGLONG Value, LONGLONG Comp);
682++C_MODE_END
683++
684++#pragma intrinsic(_InterlockedCompareExchange)
685++#pragma intrinsic(_InterlockedCompareExchange64)
686++#endif
687++
688++#define InterlockedCompareExchange _InterlockedCompareExchange
689++#define InterlockedCompareExchange64 _InterlockedCompareExchange64
690++/*
691++ No need to do something special for InterlockedCompareExchangePointer
692++ as it is a #define to InterlockedCompareExchange. The same applies to
693++ InterlockedExchangePointer.
694++*/
695++#endif /*_M_IX86*/
696++
697++#define MY_ATOMIC_MODE "msvc-intrinsics"
698++/* Implement using CAS on WIN32 */
699++#define IL_COMP_EXCHG32(X,Y,Z) \
700++ InterlockedCompareExchange((volatile LONG *)(X),(Y),(Z))
701++#define IL_COMP_EXCHG64(X,Y,Z) \
702++ InterlockedCompareExchange64((volatile LONGLONG *)(X), \
703++ (LONGLONG)(Y),(LONGLONG)(Z))
704++#define IL_COMP_EXCHGptr InterlockedCompareExchangePointer
705++
706++#define make_atomic_cas_body(S) \
707++ int ## S initial_cmp= *cmp; \
708++ int ## S initial_a= IL_COMP_EXCHG ## S (a, set, initial_cmp); \
709++ if (!(ret= (initial_a == initial_cmp))) *cmp= initial_a;
710++
711++#ifndef _M_IX86
712++/* Use full set of optimised functions on WIN64 */
713++#define IL_EXCHG_ADD32(X,Y) \
714++ InterlockedExchangeAdd((volatile LONG *)(X),(Y))
715++#define IL_EXCHG_ADD64(X,Y) \
716++ InterlockedExchangeAdd64((volatile LONGLONG *)(X),(LONGLONG)(Y))
717++#define IL_EXCHG32(X,Y) \
718++ InterlockedExchange((volatile LONG *)(X),(Y))
719++#define IL_EXCHG64(X,Y) \
720++ InterlockedExchange64((volatile LONGLONG *)(X),(LONGLONG)(Y))
721++#define IL_EXCHGptr InterlockedExchangePointer
722++
723++#define make_atomic_add_body(S) \
724++ v= IL_EXCHG_ADD ## S (a, v)
725++#define make_atomic_swap_body(S) \
726++ v= IL_EXCHG ## S (a, v)
727++#define make_atomic_load_body(S) \
728++ ret= 0; /* avoid compiler warning */ \
729++ ret= IL_COMP_EXCHG ## S (a, ret, ret);
730++#endif
731++/*
732++ my_yield_processor (equivalent of x86 PAUSE instruction) should be used
733++ to improve performance on hyperthreaded CPUs. Intel recommends to use it in
734++ spin loops also on non-HT machines to reduce power consumption (see e.g
735++ http://softwarecommunity.intel.com/articles/eng/2004.htm)
736++
737++ Running benchmarks for spinlocks implemented with InterlockedCompareExchange
738++ and YieldProcessor shows that much better performance is achieved by calling
739++ YieldProcessor in a loop - that is, yielding longer. On Intel boxes setting
740++ loop count in the range 200-300 brought best results.
741++ */
742++#ifndef YIELD_LOOPS
743++#define YIELD_LOOPS 200
744++#endif
745++
746++static __inline int my_yield_processor()
747++{
748++ int i;
749++ for(i=0; i<YIELD_LOOPS; i++)
750++ {
751++#if (_MSC_VER <= 1310)
752++ /* On older compilers YieldProcessor is not available, use inline assembly*/
753++ __asm { rep nop }
754++#else
755++ YieldProcessor();
756++#endif
757++ }
758++ return 1;
759++}
760++
761++#define LF_BACKOFF my_yield_processor()
762++#else /* cleanup */
763++
764++#undef IL_EXCHG_ADD32
765++#undef IL_EXCHG_ADD64
766++#undef IL_COMP_EXCHG32
767++#undef IL_COMP_EXCHG64
768++#undef IL_COMP_EXCHGptr
769++#undef IL_EXCHG32
770++#undef IL_EXCHG64
771++#undef IL_EXCHGptr
772++
773++#endif
774+diff -ruN /dev/null b/include/atomic/nolock.h
775+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
776++++ b/include/atomic/nolock.h 2011-06-07 08:59:00.000000000 +0300
777+@@ -0,0 +1,69 @@
778++#ifndef ATOMIC_NOLOCK_INCLUDED
779++#define ATOMIC_NOLOCK_INCLUDED
780++
781++/* Copyright (C) 2006 MySQL AB
782++
783++ This program is free software; you can redistribute it and/or modify
784++ it under the terms of the GNU General Public License as published by
785++ the Free Software Foundation; version 2 of the License.
786++
787++ This program is distributed in the hope that it will be useful,
788++ but WITHOUT ANY WARRANTY; without even the implied warranty of
789++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
790++ GNU General Public License for more details.
791++
792++ You should have received a copy of the GNU General Public License
793++ along with this program; if not, write to the Free Software
794++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
795++
796++#if defined(__i386__) || defined(_MSC_VER) || defined(__x86_64__) \
797++ || defined(HAVE_GCC_ATOMIC_BUILTINS) \
798++ || defined(HAVE_SOLARIS_ATOMIC)
799++
800++# ifdef MY_ATOMIC_MODE_DUMMY
801++# define LOCK_prefix ""
802++# else
803++# define LOCK_prefix "lock"
804++# endif
805++/*
806++ We choose implementation as follows:
807++ ------------------------------------
808++ On Windows using Visual C++ the native implementation should be
809++ preferrable. When using gcc we prefer the Solaris implementation
810++ before the gcc because of stability preference, we choose gcc
811++ builtins if available, otherwise we choose the somewhat broken
812++ native x86 implementation. If neither Visual C++ or gcc we still
813++ choose the Solaris implementation on Solaris (mainly for SunStudio
814++ compilers).
815++*/
816++# if defined(_MSV_VER)
817++# include "generic-msvc.h"
818++# elif __GNUC__
819++# if defined(HAVE_SOLARIS_ATOMIC)
820++# include "solaris.h"
821++# elif defined(HAVE_GCC_ATOMIC_BUILTINS)
822++# include "gcc_builtins.h"
823++# elif defined(__i386__) || defined(__x86_64__)
824++# include "x86-gcc.h"
825++# endif
826++# elif defined(HAVE_SOLARIS_ATOMIC)
827++# include "solaris.h"
828++# endif
829++#endif
830++
831++#if defined(make_atomic_cas_body)
832++/*
833++ Type not used so minimal size (emptry struct has different size between C
834++ and C++, zero-length array is gcc-specific).
835++*/
836++typedef char my_atomic_rwlock_t __attribute__ ((unused));
837++#define my_atomic_rwlock_destroy(name)
838++#define my_atomic_rwlock_init(name)
839++#define my_atomic_rwlock_rdlock(name)
840++#define my_atomic_rwlock_wrlock(name)
841++#define my_atomic_rwlock_rdunlock(name)
842++#define my_atomic_rwlock_wrunlock(name)
843++
844++#endif
845++
846++#endif /* ATOMIC_NOLOCK_INCLUDED */
847+diff -ruN /dev/null b/include/atomic/rwlock.h
848+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
849++++ b/include/atomic/rwlock.h 2011-06-07 08:59:00.000000000 +0300
850+@@ -0,0 +1,100 @@
851++#ifndef ATOMIC_RWLOCK_INCLUDED
852++#define ATOMIC_RWLOCK_INCLUDED
853++
854++/* Copyright (C) 2006 MySQL AB, 2009 Sun Microsystems, Inc.
855++
856++ This program is free software; you can redistribute it and/or modify
857++ it under the terms of the GNU General Public License as published by
858++ the Free Software Foundation; version 2 of the License.
859++
860++ This program is distributed in the hope that it will be useful,
861++ but WITHOUT ANY WARRANTY; without even the implied warranty of
862++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
863++ GNU General Public License for more details.
864++
865++ You should have received a copy of the GNU General Public License
866++ along with this program; if not, write to the Free Software
867++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
868++
869++#define MY_ATOMIC_MODE_RWLOCKS 1
870++
871++#ifdef MY_ATOMIC_MODE_DUMMY
872++/*
873++ the following can never be enabled by ./configure, one need to put #define in
874++ a source to trigger the following warning. The resulting code will be broken,
875++ it only makes sense to do it to see now test_atomic detects broken
876++ implementations (another way is to run a UP build on an SMP box).
877++*/
878++#warning MY_ATOMIC_MODE_DUMMY and MY_ATOMIC_MODE_RWLOCKS are incompatible
879++
880++typedef char my_atomic_rwlock_t;
881++
882++#define my_atomic_rwlock_destroy(name)
883++#define my_atomic_rwlock_init(name)
884++#define my_atomic_rwlock_rdlock(name)
885++#define my_atomic_rwlock_wrlock(name)
886++#define my_atomic_rwlock_rdunlock(name)
887++#define my_atomic_rwlock_wrunlock(name)
888++#define MY_ATOMIC_MODE "dummy (non-atomic)"
889++#else /* not MY_ATOMIC_MODE_DUMMY */
890++
891++typedef struct {pthread_mutex_t rw;} my_atomic_rwlock_t;
892++
893++#ifndef SAFE_MUTEX
894++
895++/*
896++ we're using read-write lock macros but map them to mutex locks, and they're
897++ faster. Still, having semantically rich API we can change the
898++ underlying implementation, if necessary.
899++*/
900++#define my_atomic_rwlock_destroy(name) pthread_mutex_destroy(& (name)->rw)
901++#define my_atomic_rwlock_init(name) pthread_mutex_init(& (name)->rw, 0)
902++#define my_atomic_rwlock_rdlock(name) pthread_mutex_lock(& (name)->rw)
903++#define my_atomic_rwlock_wrlock(name) pthread_mutex_lock(& (name)->rw)
904++#define my_atomic_rwlock_rdunlock(name) pthread_mutex_unlock(& (name)->rw)
905++#define my_atomic_rwlock_wrunlock(name) pthread_mutex_unlock(& (name)->rw)
906++
907++#else /* SAFE_MUTEX */
908++
909++/*
910++ SAFE_MUTEX pollutes the compiling name space with macros
911++ that alter pthread_mutex_t, pthread_mutex_init, etc.
912++ Atomic operations should never use the safe mutex wrappers.
913++ Unfortunately, there is no way to have both:
914++ - safe mutex macros expanding pthread_mutex_lock to safe_mutex_lock
915++ - my_atomic macros expanding to unmodified pthread_mutex_lock
916++ inlined in the same compilation unit.
917++ So, in case of SAFE_MUTEX, a function call is required.
918++ Given that SAFE_MUTEX is a debugging facility,
919++ this extra function call is not a performance concern for
920++ production builds.
921++*/
922++C_MODE_START
923++extern void plain_pthread_mutex_init(safe_mutex_t *);
924++extern void plain_pthread_mutex_destroy(safe_mutex_t *);
925++extern void plain_pthread_mutex_lock(safe_mutex_t *);
926++extern void plain_pthread_mutex_unlock(safe_mutex_t *);
927++C_MODE_END
928++
929++#define my_atomic_rwlock_destroy(name) plain_pthread_mutex_destroy(&(name)->rw)
930++#define my_atomic_rwlock_init(name) plain_pthread_mutex_init(&(name)->rw)
931++#define my_atomic_rwlock_rdlock(name) plain_pthread_mutex_lock(&(name)->rw)
932++#define my_atomic_rwlock_wrlock(name) plain_pthread_mutex_lock(&(name)->rw)
933++#define my_atomic_rwlock_rdunlock(name) plain_pthread_mutex_unlock(&(name)->rw)
934++#define my_atomic_rwlock_wrunlock(name) plain_pthread_mutex_unlock(&(name)->rw)
935++
936++#endif /* SAFE_MUTEX */
937++
938++#define MY_ATOMIC_MODE "mutex"
939++#ifndef MY_ATOMIC_MODE_RWLOCKS
940++#define MY_ATOMIC_MODE_RWLOCKS 1
941++#endif
942++#endif
943++
944++#define make_atomic_add_body(S) int ## S sav; sav= *a; *a+= v; v=sav;
945++#define make_atomic_fas_body(S) int ## S sav; sav= *a; *a= v; v=sav;
946++#define make_atomic_cas_body(S) if ((ret= (*a == *cmp))) *a= set; else *cmp=*a;
947++#define make_atomic_load_body(S) ret= *a;
948++#define make_atomic_store_body(S) *a= v;
949++
950++#endif /* ATOMIC_RWLOCK_INCLUDED */
951+diff -ruN /dev/null b/include/atomic/solaris.h
952+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
953++++ b/include/atomic/solaris.h 2011-06-07 08:59:00.000000000 +0300
954+@@ -0,0 +1,72 @@
955++/* Copyright (C) 2008 MySQL AB, 2009 Sun Microsystems, Inc
956++
957++ This program is free software; you can redistribute it and/or modify
958++ it under the terms of the GNU General Public License as published by
959++ the Free Software Foundation; version 2 of the License.
960++
961++ This program is distributed in the hope that it will be useful,
962++ but WITHOUT ANY WARRANTY; without even the implied warranty of
963++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
964++ GNU General Public License for more details.
965++
966++ You should have received a copy of the GNU General Public License
967++ along with this program; if not, write to the Free Software
968++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
969++
970++#ifndef _atomic_h_cleanup_
971++#define _atomic_h_cleanup_ "atomic/solaris.h"
972++
973++#include <atomic.h>
974++
975++#define MY_ATOMIC_MODE "solaris-atomic"
976++
977++#if defined(__GNUC__)
978++#define atomic_typeof(T,V) __typeof__(V)
979++#else
980++#define atomic_typeof(T,V) T
981++#endif
982++
983++#define uintptr_t void *
984++#define atomic_or_ptr_nv(X,Y) (void *)atomic_or_ulong_nv((volatile ulong_t *)X, Y)
985++
986++#define make_atomic_cas_body(S) \
987++ atomic_typeof(uint ## S ## _t, *cmp) sav; \
988++ sav = atomic_cas_ ## S( \
989++ (volatile uint ## S ## _t *)a, \
990++ (uint ## S ## _t)*cmp, \
991++ (uint ## S ## _t)set); \
992++ if (! (ret= (sav == *cmp))) \
993++ *cmp= sav;
994++
995++#define make_atomic_add_body(S) \
996++ int ## S nv; /* new value */ \
997++ nv= atomic_add_ ## S ## _nv((volatile uint ## S ## _t *)a, v); \
998++ v= nv - v
999++
1000++/* ------------------------------------------------------------------------ */
1001++
1002++#ifdef MY_ATOMIC_MODE_DUMMY
1003++
1004++#define make_atomic_load_body(S) ret= *a
1005++#define make_atomic_store_body(S) *a= v
1006++
1007++#else /* MY_ATOMIC_MODE_DUMMY */
1008++
1009++#define make_atomic_load_body(S) \
1010++ ret= atomic_or_ ## S ## _nv((volatile uint ## S ## _t *)a, 0)
1011++
1012++#define make_atomic_store_body(S) \
1013++ (void) atomic_swap_ ## S((volatile uint ## S ## _t *)a, (uint ## S ## _t)v)
1014++
1015++#endif
1016++
1017++#define make_atomic_fas_body(S) \
1018++ v= atomic_swap_ ## S((volatile uint ## S ## _t *)a, (uint ## S ## _t)v)
1019++
1020++#else /* cleanup */
1021++
1022++#undef uintptr_t
1023++#undef atomic_or_ptr_nv
1024++
1025++#endif
1026++
1027+diff -ruN /dev/null b/include/atomic/x86-gcc.h
1028+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
1029++++ b/include/atomic/x86-gcc.h 2011-06-07 08:59:00.000000000 +0300
1030+@@ -0,0 +1,145 @@
1031++#ifndef ATOMIC_X86_GCC_INCLUDED
1032++#define ATOMIC_X86_GCC_INCLUDED
1033++
1034++/* Copyright (C) 2006 MySQL AB
1035++
1036++ This program is free software; you can redistribute it and/or modify
1037++ it under the terms of the GNU General Public License as published by
1038++ the Free Software Foundation; version 2 of the License.
1039++
1040++ This program is distributed in the hope that it will be useful,
1041++ but WITHOUT ANY WARRANTY; without even the implied warranty of
1042++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1043++ GNU General Public License for more details.
1044++
1045++ You should have received a copy of the GNU General Public License
1046++ along with this program; if not, write to the Free Software
1047++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
1048++
1049++/*
1050++ XXX 64-bit atomic operations can be implemented using
1051++ cmpxchg8b, if necessary. Though I've heard that not all 64-bit
1052++ architectures support double-word (128-bit) cas.
1053++*/
1054++
1055++/*
1056++ No special support of 8 and 16 bit operations are implemented here
1057++ currently.
1058++*/
1059++#undef MY_ATOMIC_HAS_8_AND_16
1060++
1061++#ifdef __x86_64__
1062++# ifdef MY_ATOMIC_NO_XADD
1063++# define MY_ATOMIC_MODE "gcc-amd64" LOCK_prefix "-no-xadd"
1064++# else
1065++# define MY_ATOMIC_MODE "gcc-amd64" LOCK_prefix
1066++# endif
1067++#else
1068++# ifdef MY_ATOMIC_NO_XADD
1069++# define MY_ATOMIC_MODE "gcc-x86" LOCK_prefix "-no-xadd"
1070++# else
1071++# define MY_ATOMIC_MODE "gcc-x86" LOCK_prefix
1072++# endif
1073++#endif
1074++
1075++/* fix -ansi errors while maintaining readability */
1076++#ifndef asm
1077++#define asm __asm__
1078++#endif
1079++
1080++#ifndef MY_ATOMIC_NO_XADD
1081++#define make_atomic_add_body(S) make_atomic_add_body ## S
1082++#define make_atomic_cas_body(S) make_atomic_cas_body ## S
1083++#endif
1084++
1085++#define make_atomic_add_body32 \
1086++ asm volatile (LOCK_prefix "; xadd %0, %1;" \
1087++ : "+r" (v), "=m" (*a) \
1088++ : "m" (*a) \
1089++ : "memory")
1090++
1091++#define make_atomic_cas_body32 \
1092++ __typeof__(*cmp) sav; \
1093++ asm volatile (LOCK_prefix "; cmpxchg %3, %0; setz %2;" \
1094++ : "=m" (*a), "=a" (sav), "=q" (ret) \
1095++ : "r" (set), "m" (*a), "a" (*cmp) \
1096++ : "memory"); \
1097++ if (!ret) \
1098++ *cmp= sav
1099++
1100++#ifdef __x86_64__
1101++#define make_atomic_add_body64 make_atomic_add_body32
1102++#define make_atomic_cas_body64 make_atomic_cas_body32
1103++
1104++#define make_atomic_fas_body(S) \
1105++ asm volatile ("xchg %0, %1;" \
1106++ : "+r" (v), "=m" (*a) \
1107++ : "m" (*a) \
1108++ : "memory")
1109++
1110++/*
1111++ Actually 32/64-bit reads/writes are always atomic on x86_64,
1112++ nonetheless issue memory barriers as appropriate.
1113++*/
1114++#define make_atomic_load_body(S) \
1115++ /* Serialize prior load and store operations. */ \
1116++ asm volatile ("mfence" ::: "memory"); \
1117++ ret= *a; \
1118++ /* Prevent compiler from reordering instructions. */ \
1119++ asm volatile ("" ::: "memory")
1120++#define make_atomic_store_body(S) \
1121++ asm volatile ("; xchg %0, %1;" \
1122++ : "=m" (*a), "+r" (v) \
1123++ : "m" (*a) \
1124++ : "memory")
1125++
1126++#else
1127++/*
1128++ Use default implementations of 64-bit operations since we solved
1129++ the 64-bit problem on 32-bit platforms for CAS, no need to solve it
1130++ once more for ADD, LOAD, STORE and FAS as well.
1131++ Since we already added add32 support, we need to define add64
1132++ here, but we haven't defined fas, load and store at all, so
1133++ we can fallback on default implementations.
1134++*/
1135++#define make_atomic_add_body64 \
1136++ int64 tmp=*a; \
1137++ while (!my_atomic_cas64(a, &tmp, tmp+v)) ; \
1138++ v=tmp;
1139++
1140++/*
1141++ On some platforms (e.g. Mac OS X and Solaris) the ebx register
1142++ is held as a pointer to the global offset table. Thus we're not
1143++ allowed to use the b-register on those platforms when compiling
1144++ PIC code, to avoid this we push ebx and pop ebx. The new value
1145++ is copied directly from memory to avoid problems with a implicit
1146++ manipulation of the stack pointer by the push.
1147++
1148++ cmpxchg8b works on both 32-bit platforms and 64-bit platforms but
1149++ the code here is only used on 32-bit platforms, on 64-bit
1150++ platforms the much simpler make_atomic_cas_body32 will work
1151++ fine.
1152++*/
1153++#define make_atomic_cas_body64 \
1154++ asm volatile ("push %%ebx;" \
1155++ "movl (%%ecx), %%ebx;" \
1156++ "movl 4(%%ecx), %%ecx;" \
1157++ LOCK_prefix "; cmpxchg8b %0;" \
1158++ "setz %2; pop %%ebx" \
1159++ : "=m" (*a), "+A" (*cmp), "=c" (ret) \
1160++ : "c" (&set), "m" (*a) \
1161++ : "memory", "esp")
1162++#endif
1163++
1164++/*
1165++ The implementation of make_atomic_cas_body32 is adaptable to
1166++ the OS word size, so on 64-bit platforms it will automatically
1167++ adapt to 64-bits and so it will work also on 64-bit platforms
1168++*/
1169++#define make_atomic_cas_bodyptr make_atomic_cas_body32
1170++
1171++#ifdef MY_ATOMIC_MODE_DUMMY
1172++#define make_atomic_load_body(S) ret=*a
1173++#define make_atomic_store_body(S) *a=v
1174++#endif
1175++#endif /* ATOMIC_X86_GCC_INCLUDED */
1176+diff -ruN /dev/null b/mysys/my_atomic.c
1177+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
1178++++ b/mysys/my_atomic.c 2011-06-07 08:59:00.000000000 +0300
1179+@@ -0,0 +1,289 @@
1180++#ifndef MY_ATOMIC_INCLUDED
1181++#define MY_ATOMIC_INCLUDED
1182++
1183++/* Copyright (C) 2006 MySQL AB
1184++
1185++ This program is free software; you can redistribute it and/or modify
1186++ it under the terms of the GNU General Public License as published by
1187++ the Free Software Foundation; version 2 of the License.
1188++
1189++ This program is distributed in the hope that it will be useful,
1190++ but WITHOUT ANY WARRANTY; without even the implied warranty of
1191++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1192++ GNU General Public License for more details.
1193++
1194++ You should have received a copy of the GNU General Public License
1195++ along with this program; if not, write to the Free Software
1196++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
1197++
1198++/*
1199++ This header defines five atomic operations:
1200++
1201++ my_atomic_add#(&var, what)
1202++ 'Fetch and Add'
1203++ add 'what' to *var, and return the old value of *var
1204++
1205++ my_atomic_fas#(&var, what)
1206++ 'Fetch And Store'
1207++ store 'what' in *var, and return the old value of *var
1208++
1209++ my_atomic_cas#(&var, &old, new)
1210++ An odd variation of 'Compare And Set/Swap'
1211++ if *var is equal to *old, then store 'new' in *var, and return TRUE
1212++ otherwise store *var in *old, and return FALSE
1213++ Usually, &old should not be accessed if the operation is successful.
1214++
1215++ my_atomic_load#(&var)
1216++ return *var
1217++
1218++ my_atomic_store#(&var, what)
1219++ store 'what' in *var
1220++
1221++ '#' is substituted by a size suffix - 8, 16, 32, 64, or ptr
1222++ (e.g. my_atomic_add8, my_atomic_fas32, my_atomic_casptr).
1223++
1224++ NOTE This operations are not always atomic, so they always must be
1225++ enclosed in my_atomic_rwlock_rdlock(lock)/my_atomic_rwlock_rdunlock(lock)
1226++ or my_atomic_rwlock_wrlock(lock)/my_atomic_rwlock_wrunlock(lock).
1227++ Hint: if a code block makes intensive use of atomic ops, it make sense
1228++ to take/release rwlock once for the whole block, not for every statement.
1229++
1230++ On architectures where these operations are really atomic, rwlocks will
1231++ be optimized away.
1232++ 8- and 16-bit atomics aren't implemented for windows (see generic-msvc.h),
1233++ but can be added, if necessary.
1234++*/
1235++
1236++#include "my_global.h"
1237++
1238++#ifndef my_atomic_rwlock_init
1239++
1240++#define intptr void *
1241++/**
1242++ Currently we don't support 8-bit and 16-bit operations.
1243++ It can be added later if needed.
1244++*/
1245++#undef MY_ATOMIC_HAS_8_16
1246++
1247++#ifndef MY_ATOMIC_MODE_RWLOCKS
1248++/*
1249++ * Attempt to do atomic ops without locks
1250++ */
1251++#include "atomic/nolock.h"
1252++#endif
1253++
1254++#ifndef make_atomic_cas_body
1255++/* nolock.h was not able to generate even a CAS function, fall back */
1256++#include "atomic/rwlock.h"
1257++#endif
1258++
1259++/* define missing functions by using the already generated ones */
1260++#ifndef make_atomic_add_body
1261++#define make_atomic_add_body(S) \
1262++ int ## S tmp=*a; \
1263++ while (!my_atomic_cas ## S(a, &tmp, tmp+v)) ; \
1264++ v=tmp;
1265++#endif
1266++#ifndef make_atomic_fas_body
1267++#define make_atomic_fas_body(S) \
1268++ int ## S tmp=*a; \
1269++ while (!my_atomic_cas ## S(a, &tmp, v)) ; \
1270++ v=tmp;
1271++#endif
1272++#ifndef make_atomic_load_body
1273++#define make_atomic_load_body(S) \
1274++ ret= 0; /* avoid compiler warning */ \
1275++ (void)(my_atomic_cas ## S(a, &ret, ret));
1276++#endif
1277++#ifndef make_atomic_store_body
1278++#define make_atomic_store_body(S) \
1279++ (void)(my_atomic_fas ## S (a, v));
1280++#endif
1281++
1282++/*
1283++ transparent_union doesn't work in g++
1284++ Bug ?
1285++
1286++ Darwin's gcc doesn't want to put pointers in a transparent_union
1287++ when built with -arch ppc64. Complains:
1288++ warning: 'transparent_union' attribute ignored
1289++*/
1290++#if defined(__GNUC__) && !defined(__cplusplus) && \
1291++ ! (defined(__APPLE__) && (defined(_ARCH_PPC64) ||defined (_ARCH_PPC)))
1292++/*
1293++ we want to be able to use my_atomic_xxx functions with
1294++ both signed and unsigned integers. But gcc will issue a warning
1295++ "passing arg N of `my_atomic_XXX' as [un]signed due to prototype"
1296++ if the signedness of the argument doesn't match the prototype, or
1297++ "pointer targets in passing argument N of my_atomic_XXX differ in signedness"
1298++ if int* is used where uint* is expected (or vice versa).
1299++ Let's shut these warnings up
1300++*/
1301++#define make_transparent_unions(S) \
1302++ typedef union { \
1303++ int ## S i; \
1304++ uint ## S u; \
1305++ } U_ ## S __attribute__ ((transparent_union)); \
1306++ typedef union { \
1307++ int ## S volatile *i; \
1308++ uint ## S volatile *u; \
1309++ } Uv_ ## S __attribute__ ((transparent_union));
1310++#define uintptr intptr
1311++make_transparent_unions(8)
1312++make_transparent_unions(16)
1313++make_transparent_unions(32)
1314++make_transparent_unions(64)
1315++make_transparent_unions(ptr)
1316++#undef uintptr
1317++#undef make_transparent_unions
1318++#define a U_a.i
1319++#define cmp U_cmp.i
1320++#define v U_v.i
1321++#define set U_set.i
1322++#else
1323++#define U_8 int8
1324++#define U_16 int16
1325++#define U_32 int32
1326++#define U_64 int64
1327++#define U_ptr intptr
1328++#define Uv_8 int8
1329++#define Uv_16 int16
1330++#define Uv_32 int32
1331++#define Uv_64 int64
1332++#define Uv_ptr intptr
1333++#define U_a volatile *a
1334++#define U_cmp *cmp
1335++#define U_v v
1336++#define U_set set
1337++#endif /* __GCC__ transparent_union magic */
1338++
1339++#define make_atomic_cas(S) \
1340++static inline int my_atomic_cas ## S(Uv_ ## S U_a, \
1341++ Uv_ ## S U_cmp, U_ ## S U_set) \
1342++{ \
1343++ int8 ret; \
1344++ make_atomic_cas_body(S); \
1345++ return ret; \
1346++}
1347++
1348++#define make_atomic_add(S) \
1349++static inline int ## S my_atomic_add ## S( \
1350++ Uv_ ## S U_a, U_ ## S U_v) \
1351++{ \
1352++ make_atomic_add_body(S); \
1353++ return v; \
1354++}
1355++
1356++#define make_atomic_fas(S) \
1357++static inline int ## S my_atomic_fas ## S( \
1358++ Uv_ ## S U_a, U_ ## S U_v) \
1359++{ \
1360++ make_atomic_fas_body(S); \
1361++ return v; \
1362++}
1363++
1364++#define make_atomic_load(S) \
1365++static inline int ## S my_atomic_load ## S(Uv_ ## S U_a) \
1366++{ \
1367++ int ## S ret; \
1368++ make_atomic_load_body(S); \
1369++ return ret; \
1370++}
1371++
1372++#define make_atomic_store(S) \
1373++static inline void my_atomic_store ## S( \
1374++ Uv_ ## S U_a, U_ ## S U_v) \
1375++{ \
1376++ make_atomic_store_body(S); \
1377++}
1378++
1379++#ifdef MY_ATOMIC_HAS_8_16
1380++make_atomic_cas(8)
1381++make_atomic_cas(16)
1382++#endif
1383++make_atomic_cas(32)
1384++make_atomic_cas(64)
1385++make_atomic_cas(ptr)
1386++
1387++#ifdef MY_ATOMIC_HAS_8_16
1388++make_atomic_add(8)
1389++make_atomic_add(16)
1390++#endif
1391++make_atomic_add(32)
1392++make_atomic_add(64)
1393++
1394++#ifdef MY_ATOMIC_HAS_8_16
1395++make_atomic_load(8)
1396++make_atomic_load(16)
1397++#endif
1398++make_atomic_load(32)
1399++make_atomic_load(64)
1400++make_atomic_load(ptr)
1401++
1402++#ifdef MY_ATOMIC_HAS_8_16
1403++make_atomic_fas(8)
1404++make_atomic_fas(16)
1405++#endif
1406++make_atomic_fas(32)
1407++make_atomic_fas(64)
1408++make_atomic_fas(ptr)
1409++
1410++#ifdef MY_ATOMIC_HAS_8_16
1411++make_atomic_store(8)
1412++make_atomic_store(16)
1413++#endif
1414++make_atomic_store(32)
1415++make_atomic_store(64)
1416++make_atomic_store(ptr)
1417++
1418++#ifdef _atomic_h_cleanup_
1419++#include _atomic_h_cleanup_
1420++#undef _atomic_h_cleanup_
1421++#endif
1422++
1423++#undef U_8
1424++#undef U_16
1425++#undef U_32
1426++#undef U_64
1427++#undef U_ptr
1428++#undef Uv_8
1429++#undef Uv_16
1430++#undef Uv_32
1431++#undef Uv_64
1432++#undef Uv_ptr
1433++#undef a
1434++#undef cmp
1435++#undef v
1436++#undef set
1437++#undef U_a
1438++#undef U_cmp
1439++#undef U_v
1440++#undef U_set
1441++#undef make_atomic_add
1442++#undef make_atomic_cas
1443++#undef make_atomic_load
1444++#undef make_atomic_store
1445++#undef make_atomic_fas
1446++#undef make_atomic_add_body
1447++#undef make_atomic_cas_body
1448++#undef make_atomic_load_body
1449++#undef make_atomic_store_body
1450++#undef make_atomic_fas_body
1451++#undef intptr
1452++
1453++/*
1454++ the macro below defines (as an expression) the code that
1455++ will be run in spin-loops. Intel manuals recummend to have PAUSE there.
1456++ It is expected to be defined in include/atomic/ *.h files
1457++*/
1458++#ifndef LF_BACKOFF
1459++#define LF_BACKOFF (1)
1460++#endif
1461++
1462++#define MY_ATOMIC_OK 0
1463++#define MY_ATOMIC_NOT_1CPU 1
1464++extern int my_atomic_initialize();
1465++
1466++#endif
1467++
1468++#endif /* MY_ATOMIC_INCLUDED */

Subscribers

People subscribed via source and target branches