spinlock.h
3.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//
// spinlock.h
// BBAAPIRequest
//
// Created by cairui01 on 2020/05/11.
//
#ifndef spinlock_h
#define spinlock_h
#ifdef __APPLE__
#include <libkern/OSAtomic.h>
#define splock OSSpinLock
#define splockinit(lock) {*lock = OS_SPINLOCK_INIT;}
#define splocklock OSSpinLockLock
#define splockunlock OSSpinLockUnlock
#define splocktrylock OSSpinLockTry
class SpinLock
{
public:
typedef splock handle_type;
public:
SpinLock(){ splockinit(&lock_);}
bool lock()
{
splocklock(&lock_);
return true;
}
bool unlock()
{
splockunlock(&lock_);
return true;
}
bool trylock()
{
return splocktrylock(&lock_);
}
splock* internal() { return &lock_; }
private:
SpinLock(const SpinLock&);
SpinLock& operator = (const SpinLock&);
private:
splock lock_;
};
#else
#ifdef __powerpc__
#include "../../arch/powerpc/include/uapi/asm/unistd.h"
#endif
#if defined(_WIN32)
#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_ARM) )
extern "C" void YieldProcessor();
#else
extern "C" void _mm_pause();
#endif
#endif
static inline void cpu_relax() {
#if defined(__arc__) || defined(__mips__) || defined(__arm__) || defined(__powerpc__)
asm volatile("" ::: "memory");
#elif defined(__i386__) || defined(__x86_64__)
asm volatile("rep; nop" ::: "memory");
#elif defined(__aarch64__)
asm volatile("yield" ::: "memory");
#elif defined(__ia64__)
asm volatile ("hint @pause" ::: "memory");
#elif defined(_WIN32)
#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_ARM) )
YieldProcessor();
#else
_mm_pause();
#endif
#endif
}
#ifdef _WIN32
#include <thr/threads.h>
extern "C" void thrd_yield();
#define sched_yield() thrd_yield()
#else
#include <sched.h>
#endif
#include "atomic_oper.h"
class SpinLock
{
public:
typedef uint32_t handle_type;
private:
enum state
{
initial_pause = 2,
max_pause = 16
};
uint32_t state_;
public:
SpinLock() : state_(0) {}
bool trylock()
{
return (atomic_cas32((volatile uint32_t *)&state_, 1, 0) == 0);
}
bool lock()
{
/*register*/ unsigned int pause_count = initial_pause; //'register' storage class specifier is deprecated and incompatible with C++1z
while (!trylock())
{
if (pause_count < max_pause)
{
for (/*register*/ unsigned int i = 0; i < pause_count; ++i) //'register' storage class specifier is deprecated and incompatible with C++1z
{
cpu_relax();
}
pause_count += pause_count;
} else {
pause_count = initial_pause;
sched_yield();
}
}
return true;
}
bool unlock()
{
atomic_write32((volatile uint32_t *)&state_, 0);
return true;
}
uint32_t* internal() { return &state_; }
private:
SpinLock(const SpinLock&);
SpinLock& operator = (const SpinLock&);
};
#endif
#endif