Skip to content

Commit

Permalink
auto merge of #8087 : Aatch/rust/atomics, r=huonw
Browse files Browse the repository at this point in the history
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`).
  • Loading branch information
bors committed Jul 28, 2013
2 parents fe9929e + 639819f commit 5842ab3
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 2 deletions.
3 changes: 3 additions & 0 deletions src/librustc/lib/llvm.rs
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions src/librustc/middle/trans/build.rs
Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions src/librustc/middle/trans/builder.rs
Expand Up @@ -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);
}
}
}
4 changes: 4 additions & 0 deletions src/librustc/middle/trans/foreign.rs
Expand Up @@ -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 {
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/middle/typeck/check/mod.rs
Expand Up @@ -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`",
Expand Down
48 changes: 48 additions & 0 deletions src/libstd/unstable/atomics.rs
Expand Up @@ -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 {

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
}
}
}
9 changes: 9 additions & 0 deletions src/libstd/unstable/intrinsics.rs
Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion src/rustllvm/RustWrapper.cpp
Expand Up @@ -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,
Expand Down Expand Up @@ -838,4 +841,4 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
Flags,
unwrapDI<DIArray>(Elements),
RunTimeLang));
}
}
1 change: 1 addition & 0 deletions src/rustllvm/rustllvm.def.in
Expand Up @@ -90,6 +90,7 @@ LLVMBuildAtomicLoad
LLVMBuildAtomicStore
LLVMBuildAtomicCmpXchg
LLVMBuildAtomicRMW
LLVMBuildAtomicFence
LLVMBuildAdd
LLVMBuildAggregateRet
LLVMBuildAlloca
Expand Down

0 comments on commit 5842ab3

Please sign in to comment.