Seastar
High performance C++ framework for concurrent servers
spinlock.hh
1 /*
2  * This file is open source software, licensed to you under the terms
3  * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4  * distributed with this work for additional information regarding copyright
5  * ownership. You may not use this file except in compliance with the License.
6  *
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an
13  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14  * KIND, either express or implied. See the License for the
15  * specific language governing permissions and limitations
16  * under the License.
17  */
18 /*
19  * Copyright 2016 ScyllaDB
20  */
21 
22 #pragma once
23 
24 #include <seastar/util/modules.hh>
25 
26 #ifndef SEASTAR_MODULE
27 #include <atomic>
28 #include <cassert>
29 
30 #if defined(__x86_64__) || defined(__i386__)
31 #include <xmmintrin.h>
32 #endif
33 #endif
34 
35 namespace seastar {
36 
37 namespace internal {
38 #if defined(__x86_64__) || defined(__i386__)
39 
45 [[gnu::always_inline]]
46 inline void cpu_relax() {
47  _mm_pause();
48 }
49 
50 #elif defined(__PPC__)
51 
52 [[gnu::always_inline]]
53 inline void cpu_relax() {
54  __asm__ volatile("yield");
55 }
56 
57 #elif defined(__s390x__) || defined(__zarch__)
58 
59 // FIXME: there must be a better way
60 [[gnu::always_inline]]
61 inline void cpu_relax() {}
62 
63 #elif defined(__aarch64__)
64 
65 [[gnu::always_inline]]
66 inline void cpu_relax() {
67  __asm__ volatile("yield");
68 }
69 
70 #else
71 
72 [[gnu::always_inline]]
73 inline void cpu_relax() {}
74 #warn "Using an empty cpu_relax() for this architecture"
75 
76 #endif
77 
78 
79 }
80 
81 namespace util {
82 
83 // Spin lock implementation.
84 // BasicLockable.
85 // Async-signal safe.
86 // unlock() "synchronizes with" lock().
87 SEASTAR_MODULE_EXPORT
88 class spinlock {
89  std::atomic<bool> _busy = { false };
90 public:
91  spinlock() = default;
92  spinlock(const spinlock&) = delete;
93  ~spinlock() { assert(!_busy.load(std::memory_order_relaxed)); }
94  bool try_lock() noexcept {
95  return !_busy.exchange(true, std::memory_order_acquire);
96  }
97  void lock() noexcept {
98  while (_busy.exchange(true, std::memory_order_acquire)) {
99  internal::cpu_relax();
100  }
101  }
102  void unlock() noexcept {
103  _busy.store(false, std::memory_order_release);
104  }
105 };
106 
107 }
108 
109 }
Definition: spinlock.hh:88
Seastar API namespace.
Definition: abort_on_ebadf.hh:26