blob: 7328a93052ccbd92f975101ad16c0ba3d14a9763 [file] [log] [blame]
Owen Andersone5370f42009-05-20 18:26:15 +00001//===-- 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//
Hans Wennborgcfe341f2014-06-20 01:36:00 +000010// This file implements atomic operations.
Owen Andersone5370f42009-05-20 18:26:15 +000011//
12//===----------------------------------------------------------------------===//
13
Michael J. Spencer447762d2010-11-29 18:16:10 +000014#include "llvm/Support/Atomic.h"
Dylan Noblesmith9e5b1782011-12-22 23:04:07 +000015#include "llvm/Config/llvm-config.h"
Owen Andersone5370f42009-05-20 18:26:15 +000016
17using namespace llvm;
18
19#if defined(_MSC_VER)
Nico Weber0a920e72017-08-03 20:10:47 +000020#include <intrin.h>
Chandler Carruthaaeada62017-06-06 12:43:20 +000021
Nico Weber0a920e72017-08-03 20:10:47 +000022// We must include windows.h after intrin.h.
Owen Andersone5370f42009-05-20 18:26:15 +000023#include <windows.h>
Owen Anderson5bd914d2009-06-02 17:35:55 +000024#undef MemoryFence
Owen Andersone5370f42009-05-20 18:26:15 +000025#endif
26
Rafael Espindola2f92f612012-11-02 20:54:45 +000027#if defined(__GNUC__) || (defined(__IBMCPP__) && __IBMCPP__ >= 1210)
28#define GNU_ATOMICS
29#endif
30
Owen Andersone5370f42009-05-20 18:26:15 +000031void sys::MemoryFence() {
Eric Christopher4418a602011-09-19 20:43:23 +000032#if LLVM_HAS_ATOMICS == 0
Owen Andersone5370f42009-05-20 18:26:15 +000033 return;
34#else
Rafael Espindola2f92f612012-11-02 20:54:45 +000035# if defined(GNU_ATOMICS)
Owen Andersone5370f42009-05-20 18:26:15 +000036 __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
Owen Anderson5cc41312009-06-23 20:17:22 +000045sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr,
46 sys::cas_flag new_value,
47 sys::cas_flag old_value) {
Eric Christopher4418a602011-09-19 20:43:23 +000048#if LLVM_HAS_ATOMICS == 0
Owen Anderson5cc41312009-06-23 20:17:22 +000049 sys::cas_flag result = *ptr;
Owen Anderson5b9400d2009-05-20 19:01:50 +000050 if (result == old_value)
51 *ptr = new_value;
Owen Andersone5370f42009-05-20 18:26:15 +000052 return result;
Rafael Espindola2f92f612012-11-02 20:54:45 +000053#elif defined(GNU_ATOMICS)
Owen Andersone5370f42009-05-20 18:26:15 +000054 return __sync_val_compare_and_swap(ptr, old_value, new_value);
55#elif defined(_MSC_VER)
Owen Anderson76ae5dd2009-05-20 19:06:49 +000056 return InterlockedCompareExchange(ptr, new_value, old_value);
Owen Andersone5370f42009-05-20 18:26:15 +000057#else
58# error No compare-and-swap implementation for your platform!
59#endif
Duncan Sands06b61a22009-06-03 11:54:28 +000060}