OSDN Git Service

rebuid:
[eos/hostdependX86MAC64.git] / util / X86MAC64 / include / postgresql / server / storage / barrier.h
1 /*-------------------------------------------------------------------------
2  *
3  * barrier.h
4  *        Memory barrier operations.
5  *
6  * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * src/include/storage/barrier.h
10  *
11  *-------------------------------------------------------------------------
12  */
13 #ifndef BARRIER_H
14 #define BARRIER_H
15
16 #include "storage/s_lock.h"
17
18 extern slock_t dummy_spinlock;
19
20 /*
21  * A compiler barrier need not (and preferably should not) emit any actual
22  * machine code, but must act as an optimization fence: the compiler must not
23  * reorder loads or stores to main memory around the barrier.  However, the
24  * CPU may still reorder loads or stores at runtime, if the architecture's
25  * memory model permits this.
26  *
27  * A memory barrier must act as a compiler barrier, and in addition must
28  * guarantee that all loads and stores issued prior to the barrier are
29  * completed before any loads or stores issued after the barrier.  Unless
30  * loads and stores are totally ordered (which is not the case on most
31  * architectures) this requires issuing some sort of memory fencing
32  * instruction.
33  *
34  * A read barrier must act as a compiler barrier, and in addition must
35  * guarantee that any loads issued prior to the barrier are completed before
36  * any loads issued after the barrier.  Similarly, a write barrier acts
37  * as a compiler barrier, and also orders stores.  Read and write barriers
38  * are thus weaker than a full memory barrier, but stronger than a compiler
39  * barrier.  In practice, on machines with strong memory ordering, read and
40  * write barriers may require nothing more than a compiler barrier.
41  *
42  * For an introduction to using memory barriers within the PostgreSQL backend,
43  * see src/backend/storage/lmgr/README.barrier
44  */
45
46 #if defined(DISABLE_BARRIERS)
47
48 /*
49  * Fall through to the spinlock-based implementation.
50  */
51 #elif defined(__INTEL_COMPILER)
52
53 /*
54  * icc defines __GNUC__, but doesn't support gcc's inline asm syntax
55  */
56 #if defined(__ia64__) || defined(__ia64)
57 #define pg_memory_barrier()             __mf()
58 #elif defined(__i386__) || defined(__x86_64__)
59 #define pg_memory_barrier()             _mm_mfence()
60 #endif
61
62 #define pg_compiler_barrier()   __memory_barrier()
63 #elif defined(__GNUC__)
64
65 /* This works on any architecture, since it's only talking to GCC itself. */
66 #define pg_compiler_barrier()   __asm__ __volatile__("" : : : "memory")
67
68 #if defined(__i386__)
69
70 /*
71  * i386 does not allow loads to be reordered with other loads, or stores to be
72  * reordered with other stores, but a load can be performed before a subsequent
73  * store.
74  *
75  * "lock; addl" has worked for longer than "mfence".
76  */
77 #define pg_memory_barrier()             \
78         __asm__ __volatile__ ("lock; addl $0,0(%%esp)" : : : "memory", "cc")
79 #define pg_read_barrier()               pg_compiler_barrier()
80 #define pg_write_barrier()              pg_compiler_barrier()
81 #elif defined(__x86_64__)               /* 64 bit x86 */
82
83 /*
84  * x86_64 has similar ordering characteristics to i386.
85  *
86  * Technically, some x86-ish chips support uncached memory access and/or
87  * special instructions that are weakly ordered.  In those cases we'd need
88  * the read and write barriers to be lfence and sfence.  But since we don't
89  * do those things, a compiler barrier should be enough.
90  */
91 #define pg_memory_barrier()             \
92         __asm__ __volatile__ ("lock; addl $0,0(%%rsp)" : : : "memory", "cc")
93 #define pg_read_barrier()               pg_compiler_barrier()
94 #define pg_write_barrier()              pg_compiler_barrier()
95 #elif defined(__ia64__) || defined(__ia64)
96
97 /*
98  * Itanium is weakly ordered, so read and write barriers require a full
99  * fence.
100  */
101 #define pg_memory_barrier()             __asm__ __volatile__ ("mf" : : : "memory")
102 #elif defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
103
104 /*
105  * lwsync orders loads with respect to each other, and similarly with stores.
106  * But a load can be performed before a subsequent store, so sync must be used
107  * for a full memory barrier.
108  */
109 #define pg_memory_barrier()             __asm__ __volatile__ ("sync" : : : "memory")
110 #define pg_read_barrier()               __asm__ __volatile__ ("lwsync" : : : "memory")
111 #define pg_write_barrier()              __asm__ __volatile__ ("lwsync" : : : "memory")
112 #elif defined(__alpha) || defined(__alpha__)    /* Alpha */
113
114 /*
115  * Unlike all other known architectures, Alpha allows dependent reads to be
116  * reordered, but we don't currently find it necessary to provide a conditional
117  * read barrier to cover that case.  We might need to add that later.
118  */
119 #define pg_memory_barrier()             __asm__ __volatile__ ("mb" : : : "memory")
120 #define pg_read_barrier()               __asm__ __volatile__ ("rmb" : : : "memory")
121 #define pg_write_barrier()              __asm__ __volatile__ ("wmb" : : : "memory")
122 #elif defined(__hppa) || defined(__hppa__)              /* HP PA-RISC */
123
124 /* HPPA doesn't do either read or write reordering */
125 #define pg_memory_barrier()             pg_compiler_barrier()
126 #elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
127
128 /*
129  * If we're on GCC 4.1.0 or higher, we should be able to get a memory
130  * barrier out of this compiler built-in.  But we prefer to rely on our
131  * own definitions where possible, and use this only as a fallback.
132  */
133 #define pg_memory_barrier()             __sync_synchronize()
134 #endif
135 #elif defined(__ia64__) || defined(__ia64)
136
137 #define pg_compiler_barrier()   _Asm_sched_fence()
138 #define pg_memory_barrier()             _Asm_mf()
139 #elif defined(WIN32_ONLY_COMPILER)
140
141 /* Should work on both MSVC and Borland. */
142 #include <intrin.h>
143 #pragma intrinsic(_ReadWriteBarrier)
144 #define pg_compiler_barrier()   _ReadWriteBarrier()
145 #define pg_memory_barrier()             MemoryBarrier()
146 #endif
147
148 /*
149  * If we have no memory barrier implementation for this architecture, we
150  * fall back to acquiring and releasing a spinlock.  This might, in turn,
151  * fall back to the semaphore-based spinlock implementation, which will be
152  * amazingly slow.
153  *
154  * It's not self-evident that every possible legal implementation of a
155  * spinlock acquire-and-release would be equivalent to a full memory barrier.
156  * For example, I'm not sure that Itanium's acq and rel add up to a full
157  * fence.  But all of our actual implementations seem OK in this regard.
158  */
159 #if !defined(pg_memory_barrier)
160 #define pg_memory_barrier() \
161         do { S_LOCK(&dummy_spinlock); S_UNLOCK(&dummy_spinlock); } while (0)
162 #endif
163
164 /*
165  * If read or write barriers are undefined, we upgrade them to full memory
166  * barriers.
167  *
168  * If a compiler barrier is unavailable, you probably don't want a full
169  * memory barrier instead, so if you have a use case for a compiler barrier,
170  * you'd better use #ifdef.
171  */
172 #if !defined(pg_read_barrier)
173 #define pg_read_barrier()                       pg_memory_barrier()
174 #endif
175 #if !defined(pg_write_barrier)
176 #define pg_write_barrier()                      pg_memory_barrier()
177 #endif
178
179 #endif   /* BARRIER_H */