CUBRID Engine  latest
spinlock.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_SPINLOCK_H
19 #define HL_SPINLOCK_H
20 
21 #if (__cplusplus < 201103) || defined(__SUNPRO_CC) // Still no support for atomic...
22 #include "spinlock-old.h"
23 #else
24 
25 #include <atomic> // C++11
26 
27 #if defined(unix)
28 #include <sched.h>
29 #endif
30 
31 #if defined(__SVR4)
32 #include <thread.h>
33 #endif
34 
35 #include "threads/cpuinfo.h"
36 
37 #if defined(_MSC_VER)
38 
39 #if !defined(NO_INLINE)
40 #pragma inline_depth(255)
41 #define NO_INLINE __declspec(noinline)
42 #define INLINE __forceinline
43 #define inline __forceinline
44 #endif // !defined(NO_INLINE)
45 
46 #else
47 
48 #endif // defined(_MSC_VER)
49 
50 
51 #if defined(_WIN32) && !defined(_WIN64)
52 
53 #ifndef _WIN32_WINNT
54 #define _WIN32_WINNT 0x0500
55 #endif
56 
57 #endif
58 
59 #define _MM_PAUSE
60 
61 // The use of the PAUSE instruction has now been disabled, as it can be insanely costly.
62 // See https://aloiskraus.wordpress.com/2018/06/16/why-skylakex-cpus-are-sometimes-50-slower-how-intel-has-broken-existing-code/amp
63 
64 /*
65 
66 #if defined(_WIN32) // includes WIN64
67 
68 // NOTE: Below is the new "pause" instruction, which is inocuous for
69 // previous architectures, but crucial for Intel chips with
70 // hyperthreading. See
71 // http://www.usenix.org/events/wiess02/tech/full_papers/nakajima/nakajima.pdf
72 // for discussion.
73 
74 #define _MM_PAUSE YieldProcessor() // {__asm{_emit 0xf3};__asm {_emit 0x90}}
75 #include <windows.h>
76 
77 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
78 
79 #define _MM_PAUSE { asm (".byte 0xf3; .byte 0x90" : : : "memory"); }
80 
81 #else
82 
83 #define _MM_PAUSE
84 
85 #endif
86 
87 */
88 
89 namespace HL {
90 
91  class SpinLockType {
92  private:
93  std::atomic<bool> _mutex;
94  public:
95 
96  SpinLockType()
97  : _mutex (false)
98  {}
99 
100  ~SpinLockType()
101  {}
102 
103  inline void lock() {
104  if (_mutex.exchange(true)) {
105  contendedLock();
106  }
107  }
108 
109  inline bool didLock() {
110  return !_mutex.exchange(true);
111  }
112 
113  inline void unlock() {
114  _mutex = false;
115  }
116 
117  private:
118 
119  NO_INLINE
120  void contendedLock() {
121  const int MAX_SPIN = 1000;
122  while (true) {
123  if (!_mutex.exchange(true)) {
124  return;
125  }
126  int count = 0;
127  while (_mutex && (count < MAX_SPIN)) {
128  _MM_PAUSE;
129  count++;
130  }
131  if (count == MAX_SPIN) {
132  yieldProcessor();
133  }
134  }
135  }
136 
137  // Is this system a multiprocessor?
138  inline bool onMultiprocessor (void) {
139  static CPUInfo cpuInfo;
140  return (cpuInfo.getNumProcessors() > 1);
141  }
142 
143  inline void yieldProcessor (void) {
144 #if defined(_WIN32)
145  Sleep(0);
146 #elif defined(__SVR4)
147  thr_yield();
148 #else
149  sched_yield();
150 #endif
151  }
152 
153  enum { MAX_SPIN_LIMIT = 1024 };
154  };
155 
156  typedef SpinLockType SpinLock;
157 
158 }
159 
160 #endif
161 
162 #endif // _SPINLOCK_H_
void yieldProcessor(void)
Definition: spinlock-old.h:167
Definition: heaplayers.h:34
#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)
bool onMultiprocessor(void)
Definition: spinlock-old.h:162
NO_INLINE void contendedLock()
Definition: spinlock-old.h:143
#define _MM_PAUSE
Definition: spinlock-old.h:80