1 /*-------------------------------------------------------------------------
4 * Memory barrier operations.
6 * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
9 * src/include/storage/barrier.h
11 *-------------------------------------------------------------------------
16 #include "storage/s_lock.h"
18 extern slock_t dummy_spinlock;
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.
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
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.
42 * For an introduction to using memory barriers within the PostgreSQL backend,
43 * see src/backend/storage/lmgr/README.barrier
46 #if defined(DISABLE_BARRIERS)
49 * Fall through to the spinlock-based implementation.
51 #elif defined(__INTEL_COMPILER)
54 * icc defines __GNUC__, but doesn't support gcc's inline asm syntax
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()
62 #define pg_compiler_barrier() __memory_barrier()
63 #elif defined(__GNUC__)
65 /* This works on any architecture, since it's only talking to GCC itself. */
66 #define pg_compiler_barrier() __asm__ __volatile__("" : : : "memory")
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
75 * "lock; addl" has worked for longer than "mfence".
77 #define pg_memory_barrier() \
78 __asm__ __volatile__ ("lock; addl $0,0(%%esp)" : : : "memory")
79 #define pg_read_barrier() pg_compiler_barrier()
80 #define pg_write_barrier() pg_compiler_barrier()
81 #elif defined(__x86_64__) /* 64 bit x86 */
84 * x86_64 has similar ordering characteristics to i386.
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.
91 #define pg_memory_barrier() \
92 __asm__ __volatile__ ("lock; addl $0,0(%%rsp)" : : : "memory")
93 #define pg_read_barrier() pg_compiler_barrier()
94 #define pg_write_barrier() pg_compiler_barrier()
95 #elif defined(__ia64__) || defined(__ia64)
98 * Itanium is weakly ordered, so read and write barriers require a full
101 #define pg_memory_barrier() __asm__ __volatile__ ("mf" : : : "memory")
102 #elif defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
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.
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 */
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.
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 */
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)
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.
133 #define pg_memory_barrier() __sync_synchronize()
135 #elif defined(__ia64__) || defined(__ia64)
137 #define pg_compiler_barrier() _Asm_sched_fence()
138 #define pg_memory_barrier() _Asm_mf()
139 #elif defined(WIN32_ONLY_COMPILER)
141 /* Should work on both MSVC and Borland. */
143 #pragma intrinsic(_ReadWriteBarrier)
144 #define pg_compiler_barrier() _ReadWriteBarrier()
145 #define pg_memory_barrier() MemoryBarrier()
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
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.
159 #if !defined(pg_memory_barrier)
160 #define pg_memory_barrier() \
161 do { S_LOCK(&dummy_spinlock); S_UNLOCK(&dummy_spinlock); } while (0)
165 * If read or write barriers are undefined, we upgrade them to full memory
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.
172 #if !defined(pg_read_barrier)
173 #define pg_read_barrier() pg_memory_barrier()
175 #if !defined(pg_write_barrier)
176 #define pg_write_barrier() pg_memory_barrier()
179 #endif /* BARRIER_H */