blob: 7ba8b774d5e0a0b3e590806e468f599d3b138100 [file] [log] [blame]
Shih-wei Liaoe264f622010-02-10 11:10:31 -08001//===-- 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>
21#undef MemoryFence
22#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
38sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr,
39 sys::cas_flag new_value,
40 sys::cas_flag old_value) {
41#if LLVM_MULTITHREADED==0
42 sys::cas_flag result = *ptr;
43 if (result == old_value)
44 *ptr = new_value;
45 return result;
46#elif defined(__GNUC__)
47 return __sync_val_compare_and_swap(ptr, old_value, new_value);
48#elif defined(_MSC_VER)
49 return InterlockedCompareExchange(ptr, new_value, old_value);
50#else
51# error No compare-and-swap implementation for your platform!
52#endif
53}
54
55sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) {
56#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)
62 return InterlockedIncrement(ptr);
63#else
64# error No atomic increment implementation for your platform!
65#endif
66}
67
68sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) {
69#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)
75 return InterlockedDecrement(ptr);
76#else
77# error No atomic decrement implementation for your platform!
78#endif
79}
80
81sys::cas_flag sys::AtomicAdd(volatile sys::cas_flag* ptr, sys::cas_flag val) {
82#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 InterlockedExchangeAdd(ptr, val) + val;
89#else
90# error No atomic add implementation for your platform!
91#endif
92}
93
94sys::cas_flag sys::AtomicMul(volatile sys::cas_flag* ptr, sys::cas_flag val) {
95 sys::cas_flag original, result;
96 do {
97 original = *ptr;
98 result = original * val;
99 } while (sys::CompareAndSwap(ptr, result, original) != original);
100
101 return result;
102}
103
104sys::cas_flag sys::AtomicDiv(volatile sys::cas_flag* ptr, sys::cas_flag val) {
105 sys::cas_flag original, result;
106 do {
107 original = *ptr;
108 result = original / val;
109 } while (sys::CompareAndSwap(ptr, result, original) != original);
110
111 return result;
112}