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