blob: fda27088da136cd9775237561e9d97a6a781aa38 [file] [log] [blame]
Owen Anderson3c1eaa02009-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//
10// This header file implements atomic operations.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/System/Atomic.h"
15#include "llvm/Config/config.h"
16
17using namespace llvm;
18
19#if defined(_MSC_VER)
20#include <windows.h>
Owen Andersond8cf4032009-06-02 17:35:55 +000021#undef MemoryFence
Owen Anderson3c1eaa02009-05-20 18:26:15 +000022#endif
23
24void sys::MemoryFence() {
25#if LLVM_MULTITHREADED==0
26 return;
27#else
28# if defined(__GNUC__)
29 __sync_synchronize();
30# elif defined(_MSC_VER)
31 MemoryBarrier();
32# else
33# error No memory fence implementation for your platform!
34# endif
35#endif
36}
37
Owen Anderson0de99532009-06-23 18:01:04 +000038uint32_t sys::CompareAndSwap32(volatile uint32_t* ptr,
39 uint32_t new_value,
40 uint32_t old_value) {
Owen Anderson3c1eaa02009-05-20 18:26:15 +000041#if LLVM_MULTITHREADED==0
Owen Anderson0de99532009-06-23 18:01:04 +000042 uint32_t result = *ptr;
Owen Anderson41583b92009-05-20 19:01:50 +000043 if (result == old_value)
44 *ptr = new_value;
Owen Anderson3c1eaa02009-05-20 18:26:15 +000045 return result;
46#elif defined(__GNUC__)
47 return __sync_val_compare_and_swap(ptr, old_value, new_value);
48#elif defined(_MSC_VER)
Owen Anderson2aa783b2009-05-20 19:06:49 +000049 return InterlockedCompareExchange(ptr, new_value, old_value);
Owen Anderson3c1eaa02009-05-20 18:26:15 +000050#else
51# error No compare-and-swap implementation for your platform!
52#endif
Duncan Sands05a8c872009-06-03 11:54:28 +000053}
Owen Anderson9a3df672009-06-17 00:13:00 +000054
Owen Andersonf43f9d02009-06-23 18:30:27 +000055int32_t sys::AtomicIncrement32(volatile int32_t* ptr) {
Owen Anderson9a3df672009-06-17 00:13:00 +000056#if LLVM_MULTITHREADED==0
57 ++(*ptr);
58 return *ptr;
59#elif defined(__GNUC__)
60 return __sync_add_and_fetch(ptr, 1);
61#elif defined(_MSC_VER)
Owen Andersonb9c2f582009-06-19 18:37:50 +000062 return InterlockedIncrement(ptr);
Owen Anderson9a3df672009-06-17 00:13:00 +000063#else
64# error No atomic increment implementation for your platform!
65#endif
66}
67
Owen Andersonf43f9d02009-06-23 18:30:27 +000068int32_t sys::AtomicDecrement32(volatile int32_t* ptr) {
Owen Anderson9a3df672009-06-17 00:13:00 +000069#if LLVM_MULTITHREADED==0
70 --(*ptr);
71 return *ptr;
72#elif defined(__GNUC__)
73 return __sync_sub_and_fetch(ptr, 1);
74#elif defined(_MSC_VER)
Owen Andersonb9c2f582009-06-19 18:37:50 +000075 return InterlockedDecrement(ptr);
Owen Anderson9a3df672009-06-17 00:13:00 +000076#else
77# error No atomic decrement implementation for your platform!
78#endif
79}
80
Owen Andersonf43f9d02009-06-23 18:30:27 +000081int32_t sys::AtomicAdd32(volatile int32_t* ptr, int32_t val) {
Owen Anderson5a9c0ee2009-06-23 17:39:31 +000082#if LLVM_MULTITHREADED==0
83 *ptr += val;
84 return *ptr;
85#elif defined(__GNUC__)
86 return __sync_add_and_fetch(ptr, val);
87#elif defined(_MSC_VER)
88 return InterlockedAdd(ptr, val);
89#else
90# error No atomic add implementation for your platform!
91#endif
92}
93
Owen Andersonf43f9d02009-06-23 18:30:27 +000094int64_t sys::AtomicAdd64(volatile int64_t* ptr, int64_t val) {
Owen Anderson0de99532009-06-23 18:01:04 +000095#if LLVM_MULTITHREADED==0
96 *ptr += val;
97 return *ptr;
98#elif defined(__GNUC__)
99 return __sync_add_and_fetch(ptr, val);
100#elif defined(_MSC_VER)
101 return InterlockedAdd64(ptr, val);
102#else
103# error No atomic add implementation for your platform!
104#endif
105}
Owen Anderson9a3df672009-06-17 00:13:00 +0000106