diff --git a/clang-tools-extra/clangd/CMakeLists.txt b/clang-tools-extra/clangd/CMakeLists.txt --- a/clang-tools-extra/clangd/CMakeLists.txt +++ b/clang-tools-extra/clangd/CMakeLists.txt @@ -25,12 +25,12 @@ ) if(CLANG_BUILT_STANDALONE) - # needed to get HAVE_CXX_ATOMICS64_WITHOUT_LIB defined + # needed to get HAVE_ATOMICS64_WITHOUT_LIB defined include(CheckAtomic) endif() set(CLANGD_ATOMIC_LIB "") -if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) +if(NOT HAVE_ATOMICS64_WITHOUT_LIB) list(APPEND CLANGD_ATOMIC_LIB "atomic") endif() diff --git a/lldb/source/Utility/CMakeLists.txt b/lldb/source/Utility/CMakeLists.txt --- a/lldb/source/Utility/CMakeLists.txt +++ b/lldb/source/Utility/CMakeLists.txt @@ -6,7 +6,7 @@ list(APPEND LLDB_SYSTEM_LIBS ws2_32 rpcrt4) endif () -if (NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB ) +if (NOT HAVE_ATOMICS64_WITHOUT_LIB) list(APPEND LLDB_SYSTEM_LIBS atomic) endif() diff --git a/llvm/cmake/modules/CheckAtomic.cmake b/llvm/cmake/modules/CheckAtomic.cmake --- a/llvm/cmake/modules/CheckAtomic.cmake +++ b/llvm/cmake/modules/CheckAtomic.cmake @@ -6,48 +6,44 @@ # Sometimes linking against libatomic is required for atomic ops, if # the platform doesn't support lock-free atomics. -function(check_working_cxx_atomics varname) +function(check_working_atomics varname) set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11") - CHECK_CXX_SOURCE_COMPILES(" -#include -std::atomic x; + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c11") + CHECK_C_SOURCE_COMPILES(" +_Atomic int x; int main() { return x; } " ${varname}) set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) -endfunction(check_working_cxx_atomics) +endfunction(check_working_atomics) -function(check_working_cxx_atomics64 varname) +function(check_working_atomics64 varname) set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) - set(CMAKE_REQUIRED_FLAGS "-std=c++11 ${CMAKE_REQUIRED_FLAGS}") - CHECK_CXX_SOURCE_COMPILES(" -#include -#include -std::atomic x (0); + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c11") + CHECK_C_SOURCE_COMPILES(" +_Atomic long long x; int main() { - uint64_t i = x.load(std::memory_order_relaxed); - return 0; + return x; } " ${varname}) set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) -endfunction(check_working_cxx_atomics64) +endfunction(check_working_atomics64) # This isn't necessary on MSVC, so avoid command-line switch annoyance # by only running on GCC-like hosts. if (LLVM_COMPILER_IS_GCC_COMPATIBLE) # First check if atomics work without the library. - check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB) + check_working_atomics(HAVE_ATOMICS_WITHOUT_LIB) # If not, check if the library exists, and atomics work with it. - if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB) + if(NOT HAVE_ATOMICS_WITHOUT_LIB) check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) if( HAVE_LIBATOMIC ) list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") - check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB) - if (NOT HAVE_CXX_ATOMICS_WITH_LIB) - message(FATAL_ERROR "Host compiler must support std::atomic!") + check_working_atomics(HAVE_ATOMICS_WITH_LIB) + if (NOT HAVE_ATOMICS_WITH_LIB) + message(FATAL_ERROR "Host compiler must support atomic!") endif() else() message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.") @@ -57,50 +53,25 @@ # Check for 64 bit atomic operations. if(MSVC) - set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True) + set(HAVE_ATOMICS64_WITHOUT_LIB True) else() - check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB) + check_working_atomics64(HAVE_ATOMICS64_WITHOUT_LIB) endif() # If not, check if the library exists, and atomics work with it. -if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) +if(NOT HAVE_ATOMICS64_WITHOUT_LIB) check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64) if(HAVE_CXX_LIBATOMICS64) list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") - check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB) - if (NOT HAVE_CXX_ATOMICS64_WITH_LIB) - message(FATAL_ERROR "Host compiler must support 64-bit std::atomic!") + check_working_atomics64(HAVE_ATOMICS64_WITH_LIB) + if (NOT HAVE_ATOMICS64_WITH_LIB) + message(FATAL_ERROR "Host compiler must support 64-bit atomic!") endif() else() message(FATAL_ERROR "Host compiler appears to require libatomic for 64-bit operations, but cannot find it.") endif() endif() -## TODO: This define is only used for the legacy atomic operations in -## llvm's Atomic.h, which should be replaced. Other code simply -## assumes C++11 works. -CHECK_CXX_SOURCE_COMPILES(" -#ifdef _MSC_VER -#include -#endif -int main() { -#ifdef _MSC_VER - volatile LONG val = 1; - MemoryBarrier(); - InterlockedCompareExchange(&val, 0, 1); - InterlockedIncrement(&val); - InterlockedDecrement(&val); -#else - volatile unsigned long val = 1; - __sync_synchronize(); - __sync_val_compare_and_swap(&val, 1, 0); - __sync_add_and_fetch(&val, 1); - __sync_sub_and_fetch(&val, 1); -#endif - return 0; - } -" LLVM_HAS_ATOMICS) - if( NOT LLVM_HAS_ATOMICS ) message(STATUS "Warning: LLVM will be built thread-unsafe because atomic builtins are missing") endif() diff --git a/llvm/include/llvm/Support/Atomic.h b/llvm/include/llvm/Support/Atomic.h deleted file mode 100644 --- a/llvm/include/llvm/Support/Atomic.h +++ /dev/null @@ -1,42 +0,0 @@ -//===- llvm/Support/Atomic.h - Atomic Operations -----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the llvm::sys atomic operations. -// -// DO NOT USE IN NEW CODE! -// -// New code should always rely on the std::atomic facilities in C++11. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_ATOMIC_H -#define LLVM_SUPPORT_ATOMIC_H - -#include "llvm/Support/DataTypes.h" - -// Windows will at times define MemoryFence. -#ifdef MemoryFence -#undef MemoryFence -#endif - -namespace llvm { - namespace sys { - void MemoryFence(); - -#ifdef _MSC_VER - typedef long cas_flag; -#else - typedef uint32_t cas_flag; -#endif - cas_flag CompareAndSwap(volatile cas_flag* ptr, - cas_flag new_value, - cas_flag old_value); - } -} - -#endif diff --git a/llvm/include/llvm/Support/Threading.h b/llvm/include/llvm/Support/Threading.h --- a/llvm/include/llvm/Support/Threading.h +++ b/llvm/include/llvm/Support/Threading.h @@ -17,6 +17,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX #include "llvm/Support/Compiler.h" +#include #include // So we can check the C++ standard lib macros. #include @@ -41,8 +42,6 @@ #if LLVM_THREADING_USE_STD_CALL_ONCE #include -#else -#include "llvm/Support/Atomic.h" #endif namespace llvm { @@ -69,7 +68,7 @@ #if LLVM_THREADING_USE_STD_CALL_ONCE - typedef std::once_flag once_flag; + using once_flag = std::once_flag; #else @@ -81,7 +80,7 @@ /// This structure must be used as an opaque object. It is a struct to force /// autoinitialization and behave like std::once_flag. struct once_flag { - volatile sys::cas_flag status = Uninitialized; + std::atomic status = ATOMIC_VAR_INIT(Uninitialized); }; #endif @@ -104,23 +103,22 @@ std::call_once(flag, std::forward(F), std::forward(ArgList)...); #else - // For other platforms we use a generic (if brittle) version based on our - // atomics. - sys::cas_flag old_val = sys::CompareAndSwap(&flag.status, Wait, Uninitialized); - if (old_val == Uninitialized) { + InitStatus Expect = Uninitialized; + bool Success = flag.status.compare_exchange_strong(Expect, Wait); + if (Success) { std::forward(F)(std::forward(ArgList)...); - sys::MemoryFence(); + std::atomic_thread_fence(std::memory_order_seq_cst); TsanIgnoreWritesBegin(); TsanHappensBefore(&flag.status); flag.status = Done; TsanIgnoreWritesEnd(); } else { // Wait until any thread doing the call has finished. - sys::cas_flag tmp = flag.status; - sys::MemoryFence(); + InitStatus tmp = flag.status; + std::atomic_thread_fence(std::memory_order_seq_cst); while (tmp != Done) { tmp = flag.status; - sys::MemoryFence(); + std::atomic_thread_fence(std::memory_order_seq_cst); } } TsanHappensAfter(&flag.status); diff --git a/llvm/lib/Support/Atomic.cpp b/llvm/lib/Support/Atomic.cpp deleted file mode 100644 --- a/llvm/lib/Support/Atomic.cpp +++ /dev/null @@ -1,59 +0,0 @@ -//===-- Atomic.cpp - Atomic Operations --------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements atomic operations. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/Atomic.h" -#include "llvm/Config/llvm-config.h" - -using namespace llvm; - -#if defined(_MSC_VER) -#include - -// We must include windows.h after intrin.h. -#include -#undef MemoryFence -#endif - -#if defined(__GNUC__) || (defined(__IBMCPP__) && __IBMCPP__ >= 1210) -#define GNU_ATOMICS -#endif - -void sys::MemoryFence() { -#if LLVM_HAS_ATOMICS == 0 - return; -#else -# if defined(GNU_ATOMICS) - __sync_synchronize(); -# elif defined(_MSC_VER) - MemoryBarrier(); -# else -# error No memory fence implementation for your platform! -# endif -#endif -} - -sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr, - sys::cas_flag new_value, - sys::cas_flag old_value) { -#if LLVM_HAS_ATOMICS == 0 - sys::cas_flag result = *ptr; - if (result == old_value) - *ptr = new_value; - return result; -#elif defined(GNU_ATOMICS) - return __sync_val_compare_and_swap(ptr, old_value, new_value); -#elif defined(_MSC_VER) - return InterlockedCompareExchange(ptr, new_value, old_value); -#else -# error No compare-and-swap implementation for your platform! -#endif -} diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt --- a/llvm/lib/Support/CMakeLists.txt +++ b/llvm/lib/Support/CMakeLists.txt @@ -165,7 +165,6 @@ Z3Solver.cpp # System - Atomic.cpp DynamicLibrary.cpp Errno.cpp Host.cpp diff --git a/llvm/lib/Support/Windows/Threading.inc b/llvm/lib/Support/Windows/Threading.inc --- a/llvm/lib/Support/Windows/Threading.inc +++ b/llvm/lib/Support/Windows/Threading.inc @@ -16,11 +16,6 @@ #include "WindowsSupport.h" #include -// Windows will at times define MemoryFence. -#ifdef MemoryFence -#undef MemoryFence -#endif - namespace { struct ThreadInfo { void(*func)(void*);