spinlock_linux.inc (2387B)
1 // Copyright 2018 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // This file is a Linux-specific part of spinlock_wait.cc 16 17 #include <linux/futex.h> 18 #include <sys/syscall.h> 19 #include <unistd.h> 20 21 #include <atomic> 22 #include <climits> 23 #include <cstdint> 24 #include <ctime> 25 26 #include "absl/base/attributes.h" 27 #include "absl/base/internal/errno_saver.h" 28 29 // The SpinLock lockword is `std::atomic<uint32_t>`. Here we assert that 30 // `std::atomic<uint32_t>` is bitwise equivalent of the `int` expected 31 // by SYS_futex. We also assume that reads/writes done to the lockword 32 // by SYS_futex have rational semantics with regard to the 33 // std::atomic<> API. C++ provides no guarantees of these assumptions, 34 // but they are believed to hold in practice. 35 static_assert(sizeof(std::atomic<uint32_t>) == sizeof(int), 36 "SpinLock lockword has the wrong size for a futex"); 37 38 // Some Android headers are missing these definitions even though they 39 // support these futex operations. 40 #ifdef __BIONIC__ 41 #ifndef SYS_futex 42 #define SYS_futex __NR_futex 43 #endif 44 #ifndef FUTEX_PRIVATE_FLAG 45 #define FUTEX_PRIVATE_FLAG 128 46 #endif 47 #endif 48 49 #if defined(__NR_futex_time64) && !defined(SYS_futex_time64) 50 #define SYS_futex_time64 __NR_futex_time64 51 #endif 52 53 #if defined(SYS_futex_time64) && !defined(SYS_futex) 54 #define SYS_futex SYS_futex_time64 55 #endif 56 57 extern "C" { 58 59 ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)( 60 std::atomic<uint32_t> *w, uint32_t value, int, 61 absl::base_internal::SchedulingMode) { 62 absl::base_internal::ErrnoSaver errno_saver; 63 syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, nullptr); 64 } 65 66 ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)( 67 std::atomic<uint32_t> *w, bool all) { 68 syscall(SYS_futex, w, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, all ? INT_MAX : 1, 0); 69 } 70 71 } // extern "C"