Home | History | Annotate | Download | only in Support
      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 header file implements atomic operations.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "llvm/Support/Atomic.h"
     15 #include "llvm/Config/config.h"
     16 
     17 using namespace llvm;
     18 
     19 #if defined(_MSC_VER)
     20 #include <intrin.h>
     21 #include <windows.h>
     22 #undef MemoryFence
     23 #endif
     24 
     25 void sys::MemoryFence() {
     26 #if LLVM_HAS_ATOMICS == 0
     27   return;
     28 #else
     29 #  if defined(__GNUC__)
     30   __sync_synchronize();
     31 #  elif defined(_MSC_VER)
     32   MemoryBarrier();
     33 #  else
     34 # error No memory fence implementation for your platform!
     35 #  endif
     36 #endif
     37 }
     38 
     39 sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr,
     40                                   sys::cas_flag new_value,
     41                                   sys::cas_flag old_value) {
     42 #if LLVM_HAS_ATOMICS == 0
     43   sys::cas_flag result = *ptr;
     44   if (result == old_value)
     45     *ptr = new_value;
     46   return result;
     47 #elif defined(__GNUC__)
     48   return __sync_val_compare_and_swap(ptr, old_value, new_value);
     49 #elif defined(_MSC_VER)
     50   return InterlockedCompareExchange(ptr, new_value, old_value);
     51 #else
     52 #  error No compare-and-swap implementation for your platform!
     53 #endif
     54 }
     55 
     56 sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) {
     57 #if LLVM_HAS_ATOMICS == 0
     58   ++(*ptr);
     59   return *ptr;
     60 #elif defined(__GNUC__)
     61   return __sync_add_and_fetch(ptr, 1);
     62 #elif defined(_MSC_VER)
     63   return InterlockedIncrement(ptr);
     64 #else
     65 #  error No atomic increment implementation for your platform!
     66 #endif
     67 }
     68 
     69 sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) {
     70 #if LLVM_HAS_ATOMICS == 0
     71   --(*ptr);
     72   return *ptr;
     73 #elif defined(__GNUC__)
     74   return __sync_sub_and_fetch(ptr, 1);
     75 #elif defined(_MSC_VER)
     76   return InterlockedDecrement(ptr);
     77 #else
     78 #  error No atomic decrement implementation for your platform!
     79 #endif
     80 }
     81 
     82 sys::cas_flag sys::AtomicAdd(volatile sys::cas_flag* ptr, sys::cas_flag val) {
     83 #if LLVM_HAS_ATOMICS == 0
     84   *ptr += val;
     85   return *ptr;
     86 #elif defined(__GNUC__)
     87   return __sync_add_and_fetch(ptr, val);
     88 #elif defined(_MSC_VER)
     89   return InterlockedExchangeAdd(ptr, val) + val;
     90 #else
     91 #  error No atomic add implementation for your platform!
     92 #endif
     93 }
     94 
     95 sys::cas_flag sys::AtomicMul(volatile sys::cas_flag* ptr, sys::cas_flag val) {
     96   sys::cas_flag original, result;
     97   do {
     98     original = *ptr;
     99     result = original * val;
    100   } while (sys::CompareAndSwap(ptr, result, original) != original);
    101 
    102   return result;
    103 }
    104 
    105 sys::cas_flag sys::AtomicDiv(volatile sys::cas_flag* ptr, sys::cas_flag val) {
    106   sys::cas_flag original, result;
    107   do {
    108     original = *ptr;
    109     result = original / val;
    110   } while (sys::CompareAndSwap(ptr, result, original) != original);
    111 
    112   return result;
    113 }
    114