Skip to content

Commit 5842ab3

Browse files
committed
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`).
2 parents fe9929e + 639819f commit 5842ab3

File tree

9 files changed

+83
-2
lines changed

9 files changed

+83
-2
lines changed

src/librustc/lib/llvm.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,6 +1594,9 @@ pub mod llvm {
15941594
Order: AtomicOrdering)
15951595
-> ValueRef;
15961596

1597+
pub unsafe fn LLVMBuildAtomicFence(B: BuilderRef, Order: AtomicOrdering);
1598+
1599+
15971600
/* Selected entries from the downcasts. */
15981601
#[fast_ffi]
15991602
pub unsafe fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef;

src/librustc/middle/trans/build.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,11 @@ pub fn CallWithConv(cx: @mut Block, Fn: ValueRef, Args: &[ValueRef],
660660
B(cx).call_with_conv(Fn, Args, Conv)
661661
}
662662

663+
pub fn AtomicFence(cx: @mut Block, order: AtomicOrdering) {
664+
if cx.unreachable { return; }
665+
B(cx).atomic_fence(order)
666+
}
667+
663668
pub fn Select(cx: @mut Block, If: ValueRef, Then: ValueRef, Else: ValueRef) -> ValueRef {
664669
if cx.unreachable { return _Undef(Then); }
665670
B(cx).select(If, Then, Else)

src/librustc/middle/trans/builder.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,4 +943,10 @@ impl Builder {
943943
llvm::LLVMBuildAtomicRMW(self.llbuilder, op, dst, src, order)
944944
}
945945
}
946+
947+
pub fn atomic_fence(&self, order: AtomicOrdering) {
948+
unsafe {
949+
llvm::LLVMBuildAtomicFence(self.llbuilder, order);
950+
}
951+
}
946952
}

src/librustc/middle/trans/foreign.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,10 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
661661
order);
662662
RetVoid(bcx);
663663
}
664+
"fence" => {
665+
AtomicFence(bcx, order);
666+
RetVoid(bcx);
667+
}
664668
op => {
665669
// These are all AtomicRMW ops
666670
let atom_op = match op {

src/librustc/middle/typeck/check/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3521,7 +3521,9 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
35213521
ty::re_bound(ty::br_anon(0)),
35223522
ty::mk_int()), ty::mk_int() ], ty::mk_int())
35233523
}
3524-
3524+
"fence" => {
3525+
(0, ~[], ty::mk_nil())
3526+
}
35253527
op => {
35263528
tcx.sess.span_err(it.span,
35273529
fmt!("unrecognized atomic operation function: `%s`",

src/libstd/unstable/atomics.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ pub enum Ordering {
7575
SeqCst
7676
}
7777

78+
pub static INIT_ATOMIC_FLAG : AtomicFlag = AtomicFlag { v: 0 };
79+
pub static INIT_ATOMIC_BOOL : AtomicBool = AtomicBool { v: 0 };
80+
pub static INIT_ATOMIC_INT : AtomicInt = AtomicInt { v: 0 };
81+
pub static INIT_ATOMIC_UINT : AtomicUint = AtomicUint { v: 0 };
7882

7983
impl AtomicFlag {
8084

@@ -569,6 +573,35 @@ pub unsafe fn atomic_umin<T>(dst: &mut T, val: T, order: Ordering) -> T {
569573
})
570574
}
571575

576+
/**
577+
* An atomic fence.
578+
*
579+
* A fence 'A' which has `Release` ordering semantics, synchronizes with a
580+
* fence 'B' with (at least) `Acquire` semantics, if and only if there exists
581+
* atomic operations X and Y, both operating on some atomic object 'M' such
582+
* that A is sequenced before X, Y is synchronized before B and Y obsevers
583+
* the change to M. This provides a happens-before dependence between A and B.
584+
*
585+
* Atomic operations with `Release` or `Acquire` semantics can also synchronize
586+
* with a fence.
587+
*
588+
* A fence with has `SeqCst` ordering, in addition to having both `Acquire` and
589+
* `Release` semantics, participates in the global program order of the other
590+
* `SeqCst` operations and/or fences.
591+
*
592+
* Accepts `Acquire`, `Release`, `AcqRel` and `SeqCst` orderings.
593+
*/
594+
#[inline] #[cfg(not(stage0))]
595+
pub fn fence(order: Ordering) {
596+
unsafe {
597+
match order {
598+
Acquire => intrinsics::atomic_fence_acq(),
599+
Release => intrinsics::atomic_fence_rel(),
600+
AcqRel => intrinsics::atomic_fence_rel(),
601+
_ => intrinsics::atomic_fence(),
602+
}
603+
}
604+
}
572605

573606
#[cfg(test)]
574607
mod test {
@@ -630,4 +663,19 @@ mod test {
630663
assert_eq!(a.fetch_and(false, SeqCst),true);
631664
assert_eq!(a.load(SeqCst),false);
632665
}
666+
667+
static mut S_FLAG : AtomicFlag = INIT_ATOMIC_FLAG;
668+
static mut S_BOOL : AtomicBool = INIT_ATOMIC_BOOL;
669+
static mut S_INT : AtomicInt = INIT_ATOMIC_INT;
670+
static mut S_UINT : AtomicUint = INIT_ATOMIC_UINT;
671+
672+
#[test]
673+
fn static_init() {
674+
unsafe {
675+
assert!(!S_FLAG.test_and_set(SeqCst));
676+
assert!(!S_BOOL.load(SeqCst));
677+
assert!(S_INT.load(SeqCst) == 0);
678+
assert!(S_UINT.load(SeqCst) == 0);
679+
}
680+
}
633681
}

src/libstd/unstable/intrinsics.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,15 @@ extern "rust-intrinsic" {
256256
pub fn atomic_umax_acqrel(dst: &mut int, src: int) -> int;
257257
pub fn atomic_umax_relaxed(dst: &mut int, src: int) -> int;
258258

259+
#[cfg(not(stage0))]
260+
pub fn atomic_fence();
261+
#[cfg(not(stage0))]
262+
pub fn atomic_fence_acq();
263+
#[cfg(not(stage0))]
264+
pub fn atomic_fence_rel();
265+
#[cfg(not(stage0))]
266+
pub fn atomic_fence_acqrel();
267+
259268
/// The size of a type in bytes.
260269
///
261270
/// This is the exact number of bytes in memory taken up by a

src/rustllvm/RustWrapper.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,9 @@ extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
513513
return wrap(unwrap(B)->CreateAtomicCmpXchg(unwrap(target), unwrap(old),
514514
unwrap(source), order));
515515
}
516+
extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B, AtomicOrdering order) {
517+
return wrap(unwrap(B)->CreateFence(order));
518+
}
516519
extern "C" LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,
517520
AtomicRMWInst::BinOp op,
518521
LLVMValueRef target,
@@ -838,4 +841,4 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
838841
Flags,
839842
unwrapDI<DIArray>(Elements),
840843
RunTimeLang));
841-
}
844+
}

src/rustllvm/rustllvm.def.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ LLVMBuildAtomicLoad
9090
LLVMBuildAtomicStore
9191
LLVMBuildAtomicCmpXchg
9292
LLVMBuildAtomicRMW
93+
LLVMBuildAtomicFence
9394
LLVMBuildAdd
9495
LLVMBuildAggregateRet
9596
LLVMBuildAlloca

0 commit comments

Comments
 (0)