CUBRID Engine  latest
spinlock-old.h
Go to the documentation of this file.
1 /* -*- C++ -*- */
2 
3 /*
4 
5  Heap Layers: An Extensible Memory Allocation Infrastructure
6 
7  Copyright (C) 2000-2020 by Emery Berger
8  http://www.emeryberger.com
9  emery@cs.umass.edu
10 
11  Heap Layers is distributed under the terms of the Apache 2.0 license.
12 
13  You may obtain a copy of the License at
14  http://www.apache.org/licenses/LICENSE-2.0
15 
16 */
17 
18 #ifndef HL_SPINLOCKOLD_H
19 #define HL_SPINLOCKOLD_H
20 
21 #if defined(unix)
22 #include <sched.h>
23 #endif
24 
25 #if defined(__SVR4)
26 #include <thread.h>
27 #endif
28 
29 #if defined(__sgi)
30 #include <mutex.h>
31 #endif
32 
33 #if defined(__APPLE__)
34 #include <libkern/OSAtomic.h>
35 #endif
36 
37 #include "threads/cpuinfo.h"
38 
39 #if defined(_MSC_VER)
40 
41 #if !defined(NO_INLINE)
42 #pragma inline_depth(255)
43 #define NO_INLINE __declspec(noinline)
44 #define INLINE __forceinline
45 #define inline __forceinline
46 #endif // !defined(NO_INLINE)
47 
48 #else
49 
50 #endif // defined(_MSC_VER)
51 
52 
53 #if defined(__SUNPRO_CC)
54 // x86-interchange.il, x86_64-interchange.il contributed by Markus Bernhardt.
55 extern "C" size_t MyInterlockedExchange (size_t * oldval,
56  size_t newval);
57 #endif
58 
59 #if defined(_WIN32) && !defined(_WIN64)
60 
61 #ifndef _WIN32_WINNT
62 #define _WIN32_WINNT 0x0500
63 #endif
64 
65 // NOTE: Below is the new "pause" instruction, which is inocuous for
66 // previous architectures, but crucial for Intel chips with
67 // hyperthreading. See
68 // http://www.usenix.org/events/wiess02/tech/full_papers/nakajima/nakajima.pdf
69 // for discussion.
70 
71 #define _MM_PAUSE {__asm{_emit 0xf3};__asm {_emit 0x90}}
72 #include <windows.h>
73 
74 #elif defined(__GNUC__)
75 
76 #define _MM_PAUSE { asm (".byte 0xf3; .byte 0x90" : : : "memory"); }
77 
78 #else
79 
80 #define _MM_PAUSE
81 
82 #endif // defined(_WIN32) && !defined(_WIN64)
83 
84 //extern volatile bool anyThreadCreated;
85 
86 namespace HL {
87 
88  class SpinLockType {
89  private:
90 
91  enum { UNLOCKED = 0, LOCKED = 1 };
92 
93  public:
94 
95  SpinLockType (void)
96 #if defined(__APPLE__)
97  : mutex (OS_SPINLOCK_INIT)
98 #else
99  : mutex (UNLOCKED)
100 #endif
101  {}
102 
104  {}
105 
106  inline void lock() {
107  if (true) { // anyThreadCreated) {
108  if (MyInterlockedExchange (const_cast<size_t *>(&mutex), LOCKED)
109  != UNLOCKED) {
110  contendedLock();
111  }
112  } else {
113  mutex = LOCKED;
114  }
115  }
116 
117 
118 
119  inline void unlock() {
120  if (true) { // anyThreadCreated) {
121 #if defined(_WIN32) && !defined(_WIN64)
122  __asm {}
123 #elif defined(__GNUC__)
124  asm volatile ("" : : : "memory");
125 #endif
126  }
127  mutex = UNLOCKED;
128  }
129 
130 
131 #if !defined(__SUNPRO_CC)
132  inline static size_t MyInterlockedExchange (size_t *, size_t);
133 #endif
134 
135  private:
136 
137 #if 0 // defined(__APPLE__)
138  OSSpinLock mutex;
139 
140 #else
141 
142  NO_INLINE
143  void contendedLock() {
144  const int MAX_SPIN = 1000;
145  while (true) {
146  if (MyInterlockedExchange (const_cast<size_t *>(&mutex), LOCKED)
147  == UNLOCKED) {
148  return;
149  }
150  int count = 0;
151  while ((mutex == LOCKED) && (count < MAX_SPIN)) {
152  _MM_PAUSE;
153  count++;
154  }
155  if (count == MAX_SPIN) {
156  yieldProcessor();
157  }
158  }
159  }
160 
161  // Is this system a multiprocessor?
162  inline bool onMultiprocessor (void) {
163  static CPUInfo cpuInfo;
164  return (cpuInfo.getNumProcessors() > 1);
165  }
166 
167  inline void yieldProcessor (void) {
168 #if defined(_WIN32)
169  Sleep(0);
170 #elif defined(__SVR4)
171  thr_yield();
172 #else
173  sched_yield();
174 #endif
175  }
176 
177  enum { MAX_SPIN_LIMIT = 1024 };
178 
179  volatile size_t mutex;
180 #endif
181 
182  };
183 
184 }
185 
186 // Atomically:
187 // retval = *oldval;
188 // *oldval = newval;
189 // return retval;
190 
191 #if !defined(__SUNPRO_CC) // && !defined(__APPLE__)
192 inline size_t
194  size_t newval)
195 {
196 #if defined(_WIN32) && defined(_MSC_VER)
197  return InterlockedExchange ((volatile LONG *) oldval, newval);
198 
199  //#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
200  // return __sync_val_compare_and_swap(oldval, *oldval, newval);
201 
202 #elif defined(__sparc)
203  asm volatile ("swap [%1],%0"
204  :"=r" (newval)
205  :"r" (oldval), "0" (newval)
206  : "memory");
207 
208 #elif defined(__i386__)
209  asm volatile ("lock; xchgl %0, %1"
210  : "=r" (newval)
211  : "m" (*oldval), "0" (newval)
212  : "memory");
213 
214 #elif defined(__sgi)
215  newval = test_and_set (oldval, newval);
216 
217 #elif defined(__x86_64__)
218  // Contributed by Kurt Roeckx.
219  asm volatile ("lock; xchgq %0, %1"
220  : "=r" (newval)
221  : "m" (*oldval), "0" (newval)
222  : "memory");
223 
224 #elif defined(__ppc) || defined(__powerpc__) || defined(PPC)
225  // PPC assembly contributed by Maged Michael.
226  int ret;
227  asm volatile (
228  "La..%=0: lwarx %0,0,%1 ;"
229  " cmpw %0,%2;"
230  " beq La..%=1;"
231  " stwcx. %2,0,%1;"
232  " bne- La..%=0;"
233  "La..%=1: isync;"
234  : "=&r"(ret)
235  : "r"(oldval), "r"(newval)
236  : "cr0", "memory");
237  return ret;
238 
239 #elif defined(__arm__)
240  // Contributed by Bo Granlund.
241  long result;
242  asm volatile (
243  "\n\t"
244  "swp %0,%2,[%1] \n\t"
245  ""
246  : "=&r"(result)
247  : "r"(oldval), "r"(newval)
248  : "memory");
249  return (result);
250 #elif defined(__APPLE__)
251  size_t oldValue = *oldval;
252  bool swapped = OSAtomicCompareAndSwapLongBarrier (oldValue, newval, (volatile long *) oldval);
253  if (swapped) {
254  return newval;
255  } else {
256  return oldValue;
257  }
258 #else
259 #error "No spin lock implementation is available for this platform."
260 #endif
261  return newval;
262 }
263 
264 
265 #endif
266 
267 #endif // _SPINLOCK_H_
void yieldProcessor(void)
Definition: spinlock-old.h:167
Definition: heaplayers.h:34
static size_t MyInterlockedExchange(size_t *, size_t)
Definition: spinlock-old.h:193
#define NO_INLINE
Definition: heaplayers.h:65
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
static int getNumProcessors()
Definition: cpuinfo.h:87
volatile size_t mutex
Definition: spinlock-old.h:179
bool onMultiprocessor(void)
Definition: spinlock-old.h:162
Architecture-independent wrapper to get number of CPUs.
Definition: cpuinfo.h:81
NO_INLINE void contendedLock()
Definition: spinlock-old.h:143
#define _MM_PAUSE
Definition: spinlock-old.h:80