blob: f6865405c2b8500a01a4b3650f9b49a0629ba076 [file] [log] [blame]
Owen Andersone5370f42009-05-20 18:26:15 +00001//===-- Atomic.cpp - Atomic Operations --------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Owen Andersone5370f42009-05-20 18:26:15 +00006//
7//===----------------------------------------------------------------------===//
8//
Hans Wennborgcfe341f2014-06-20 01:36:00 +00009// This file implements atomic operations.
Owen Andersone5370f42009-05-20 18:26:15 +000010//
11//===----------------------------------------------------------------------===//
12
Michael J. Spencer447762d2010-11-29 18:16:10 +000013#include "llvm/Support/Atomic.h"
Dylan Noblesmith9e5b1782011-12-22 23:04:07 +000014#include "llvm/Config/llvm-config.h"
Owen Andersone5370f42009-05-20 18:26:15 +000015
16using namespace llvm;
17
18#if defined(_MSC_VER)
Nico Weber0a920e72017-08-03 20:10:47 +000019#include <intrin.h>
Chandler Carruthaaeada62017-06-06 12:43:20 +000020
Nico Weber0a920e72017-08-03 20:10:47 +000021// We must include windows.h after intrin.h.
Owen Andersone5370f42009-05-20 18:26:15 +000022#include <windows.h>
Owen Anderson5bd914d2009-06-02 17:35:55 +000023#undef MemoryFence
Owen Andersone5370f42009-05-20 18:26:15 +000024#endif
25
Rafael Espindola2f92f612012-11-02 20:54:45 +000026#if defined(__GNUC__) || (defined(__IBMCPP__) && __IBMCPP__ >= 1210)
27#define GNU_ATOMICS
28#endif
29
Owen Andersone5370f42009-05-20 18:26:15 +000030void sys::MemoryFence() {
Eric Christopher4418a602011-09-19 20:43:23 +000031#if LLVM_HAS_ATOMICS == 0
Owen Andersone5370f42009-05-20 18:26:15 +000032 return;
33#else
Rafael Espindola2f92f612012-11-02 20:54:45 +000034# if defined(GNU_ATOMICS)
Owen Andersone5370f42009-05-20 18:26:15 +000035 __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
Owen Anderson5cc41312009-06-23 20:17:22 +000044sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr,
45 sys::cas_flag new_value,
46 sys::cas_flag old_value) {
Eric Christopher4418a602011-09-19 20:43:23 +000047#if LLVM_HAS_ATOMICS == 0
Owen Anderson5cc41312009-06-23 20:17:22 +000048 sys::cas_flag result = *ptr;
Owen Anderson5b9400d2009-05-20 19:01:50 +000049 if (result == old_value)
50 *ptr = new_value;
Owen Andersone5370f42009-05-20 18:26:15 +000051 return result;
Rafael Espindola2f92f612012-11-02 20:54:45 +000052#elif defined(GNU_ATOMICS)
Owen Andersone5370f42009-05-20 18:26:15 +000053 return __sync_val_compare_and_swap(ptr, old_value, new_value);
54#elif defined(_MSC_VER)
Owen Anderson76ae5dd2009-05-20 19:06:49 +000055 return InterlockedCompareExchange(ptr, new_value, old_value);
Owen Andersone5370f42009-05-20 18:26:15 +000056#else
57# error No compare-and-swap implementation for your platform!
58#endif
Duncan Sands06b61a22009-06-03 11:54:28 +000059}