Arquivos
hhvm/hphp/util/atomic.h
T
Jordan Delong 363d1bb20f Code move src/ -> hphp/
This change is mostly for FB internal organizational reasons.
Building is not effected beyond the fact that the target now
lands in hphp/hhvm/hhvm rather than src/hhvm/hhvm.
2013-02-11 02:10:41 -08:00

95 linhas
3.3 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_ATOMIC_H_
#define incl_ATOMIC_H_
#include <stdint.h>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include "util/assertions.h"
#include "util/util.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
template<class T>
inline void assert_address_is_atomically_accessible(T* address) {
static_assert(
sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8,
"T must be a 1, 2, 4, or 8 byte object for atomic access");
static_assert(
boost::is_arithmetic<T>::value || boost::is_pointer<T>::value,
"Atomic operations only supported for built in integer, floating point "
"and pointer types.");
#ifdef __x86_64__
assert(((uintptr_t(address) + sizeof(T) - 1) & ~63ul) ==
( uintptr_t(address) & ~63ul) &&
"Atomically accessed addresses may not span cache lines");
#elif __AARCH64EL__
// N-byte accesses must be N-byte aligned
assert((uintptr_t(address) & (sizeof(T) - 1)) == 0);
#else
# error What kind of memory accesses are atomic on this architecture?
#endif
}
/**
* Use of the functions below is DISCOURAGED.
* Prefer the std::atomic library in C++11.
*
* Not only does it relieve you of worrying about architecture and compiler
* portability issues, but it also encourages you to really reason through the
* concurrency you're aiming to manage, by treating atomically-accessed data as
* a distinct type.
*/
template<class T> inline T atomic_acquire_load(const T* address) {
assert_address_is_atomically_accessible(address);
T ret = *address; // acquire barrier on x64
Util::compiler_membar();
return ret;
}
template<class T, class U>
inline void atomic_release_store(T* address, U val) {
assert_address_is_atomically_accessible(address);
Util::compiler_membar();
*address = val; // release barrier on x64 (as long as no one is
// doing any non-temporal moves or whatnot).
}
template<typename T>
static inline T atomic_inc(T &count) {
assert_address_is_atomically_accessible(&count);
return __sync_fetch_and_add(&count, 1) + 1;
}
static inline int atomic_dec(int &count) {
assert_address_is_atomically_accessible(&count);
return __sync_fetch_and_add(&count, -1) - 1;
}
///////////////////////////////////////////////////////////////////////////////
}
#endif // __ATOMIC_H__