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