auto merge of #8087 : Aatch/rust/atomics, r=huonw

Adds a fence operation to close #8061

Also adds static initializers to for atomic types. Since the fields are private, you aren't able to have `static mut` variables that are an atomic type. Each atomic type's initializer starts at a 0-value (so unset for `AtomicFlag` and false for `AtomicBool`).
This commit is contained in:
bors 2013-07-28 03:55:22 -07:00
commit 5842ab36b8
9 changed files with 83 additions and 2 deletions

View File

@ -1594,6 +1594,9 @@ pub mod llvm {
Order: AtomicOrdering)
-> ValueRef;
pub unsafe fn LLVMBuildAtomicFence(B: BuilderRef, Order: AtomicOrdering);
/* Selected entries from the downcasts. */
#[fast_ffi]
pub unsafe fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;

View File

@ -660,6 +660,11 @@ pub fn CallWithConv(cx: @mut Block, Fn: ValueRef, Args: &[ValueRef],
B(cx).call_with_conv(Fn, Args, Conv)
}
pub fn AtomicFence(cx: @mut Block, order: AtomicOrdering) {
if cx.unreachable { return; }
B(cx).atomic_fence(order)
}
pub fn Select(cx: @mut Block, If: ValueRef, Then: ValueRef, Else: ValueRef) -> ValueRef {
if cx.unreachable { return _Undef(Then); }
B(cx).select(If, Then, Else)

View File

@ -943,4 +943,10 @@ impl Builder {
llvm::LLVMBuildAtomicRMW(self.llbuilder, op, dst, src, order)
}
}
pub fn atomic_fence(&self, order: AtomicOrdering) {
unsafe {
llvm::LLVMBuildAtomicFence(self.llbuilder, order);
}
}
}

View File

@ -661,6 +661,10 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
order);
RetVoid(bcx);
}
"fence" => {
AtomicFence(bcx, order);
RetVoid(bcx);
}
op => {
// These are all AtomicRMW ops
let atom_op = match op {

View File

@ -3521,7 +3521,9 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
ty::re_bound(ty::br_anon(0)),
ty::mk_int()), ty::mk_int() ], ty::mk_int())
}
"fence" => {
(0, ~[], ty::mk_nil())
}
op => {
tcx.sess.span_err(it.span,
fmt!("unrecognized atomic operation function: `%s`",

View File

@ -75,6 +75,10 @@ pub enum Ordering {
SeqCst
}
pub static INIT_ATOMIC_FLAG : AtomicFlag = AtomicFlag { v: 0 };
pub static INIT_ATOMIC_BOOL : AtomicBool = AtomicBool { v: 0 };
pub static INIT_ATOMIC_INT : AtomicInt = AtomicInt { v: 0 };
pub static INIT_ATOMIC_UINT : AtomicUint = AtomicUint { v: 0 };
impl AtomicFlag {
@ -569,6 +573,35 @@ pub unsafe fn atomic_umin<T>(dst: &mut T, val: T, order: Ordering) -> T {
})
}
/**
* An atomic fence.
*
* A fence 'A' which has `Release` ordering semantics, synchronizes with a
* fence 'B' with (at least) `Acquire` semantics, if and only if there exists
* atomic operations X and Y, both operating on some atomic object 'M' such
* that A is sequenced before X, Y is synchronized before B and Y obsevers
* the change to M. This provides a happens-before dependence between A and B.
*
* Atomic operations with `Release` or `Acquire` semantics can also synchronize
* with a fence.
*
* A fence with has `SeqCst` ordering, in addition to having both `Acquire` and
* `Release` semantics, participates in the global program order of the other
* `SeqCst` operations and/or fences.
*
* Accepts `Acquire`, `Release`, `AcqRel` and `SeqCst` orderings.
*/
#[inline] #[cfg(not(stage0))]
pub fn fence(order: Ordering) {
unsafe {
match order {
Acquire => intrinsics::atomic_fence_acq(),
Release => intrinsics::atomic_fence_rel(),
AcqRel => intrinsics::atomic_fence_rel(),
_ => intrinsics::atomic_fence(),
}
}
}
#[cfg(test)]
mod test {
@ -630,4 +663,19 @@ mod test {
assert_eq!(a.fetch_and(false, SeqCst),true);
assert_eq!(a.load(SeqCst),false);
}
static mut S_FLAG : AtomicFlag = INIT_ATOMIC_FLAG;
static mut S_BOOL : AtomicBool = INIT_ATOMIC_BOOL;
static mut S_INT : AtomicInt = INIT_ATOMIC_INT;
static mut S_UINT : AtomicUint = INIT_ATOMIC_UINT;
#[test]
fn static_init() {
unsafe {
assert!(!S_FLAG.test_and_set(SeqCst));
assert!(!S_BOOL.load(SeqCst));
assert!(S_INT.load(SeqCst) == 0);
assert!(S_UINT.load(SeqCst) == 0);
}
}
}

View File

@ -256,6 +256,15 @@ extern "rust-intrinsic" {
pub fn atomic_umax_acqrel(dst: &mut int, src: int) -> int;
pub fn atomic_umax_relaxed(dst: &mut int, src: int) -> int;
#[cfg(not(stage0))]
pub fn atomic_fence();
#[cfg(not(stage0))]
pub fn atomic_fence_acq();
#[cfg(not(stage0))]
pub fn atomic_fence_rel();
#[cfg(not(stage0))]
pub fn atomic_fence_acqrel();
/// The size of a type in bytes.
///
/// This is the exact number of bytes in memory taken up by a

View File

@ -513,6 +513,9 @@ extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
return wrap(unwrap(B)->CreateAtomicCmpXchg(unwrap(target), unwrap(old),
unwrap(source), order));
}
extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B, AtomicOrdering order) {
return wrap(unwrap(B)->CreateFence(order));
}
extern "C" LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,
AtomicRMWInst::BinOp op,
LLVMValueRef target,
@ -838,4 +841,4 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
Flags,
unwrapDI<DIArray>(Elements),
RunTimeLang));
}
}

View File

@ -90,6 +90,7 @@ LLVMBuildAtomicLoad
LLVMBuildAtomicStore
LLVMBuildAtomicCmpXchg
LLVMBuildAtomicRMW
LLVMBuildAtomicFence
LLVMBuildAdd
LLVMBuildAggregateRet
LLVMBuildAlloca