1//===-- Atomic.cpp - Atomic Operations --------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements atomic operations.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/Support/Atomic.h"
14#include "llvm/Config/llvm-config.h"
15
16using namespace llvm;
17
18#if defined(_MSC_VER)
19#include <intrin.h>
20
21// We must include windows.h after intrin.h.
22#include <windows.h>
23#undef MemoryFence
24#endif
25
26#if defined(__GNUC__) || (defined(__IBMCPP__) && __IBMCPP__ >= 1210)
27#define GNU_ATOMICS
28#endif
29
30void sys::MemoryFence() {
31#if LLVM_HAS_ATOMICS == 0
32 return;
33#else
34# if defined(GNU_ATOMICS)
35 __sync_synchronize();
36# elif defined(_MSC_VER)
37 MemoryBarrier();
38# else
39# error No memory fence implementation for your platform!
40# endif
41#endif
42}
43
44sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr,
45 sys::cas_flag new_value,
46 sys::cas_flag old_value) {
47#if LLVM_HAS_ATOMICS == 0
48 sys::cas_flag result = *ptr;
49 if (result == old_value)
50 *ptr = new_value;
51 return result;
52#elif defined(GNU_ATOMICS)
53 return __sync_val_compare_and_swap(ptr, old_value, new_value);
54#elif defined(_MSC_VER)
55 return InterlockedCompareExchange(ptr, new_value, old_value);
56#else
57# error No compare-and-swap implementation for your platform!
58#endif
59}
60