Skip to content

#6314 Change atomic intrinsics to accept raw pointers #7638

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 22 additions & 20 deletions src/librustc/middle/typeck/check/mod.rs
Original file line number Diff line number Diff line change
@@ -3476,29 +3476,31 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {

//We only care about the operation here
match split[1] {
"cxchg" => (0, ~[ty::mk_mut_rptr(tcx,
ty::re_bound(ty::br_anon(0)),
ty::mk_int()),
ty::mk_int(),
ty::mk_int()
], ty::mk_int()),
"load" => (0,
~[
ty::mk_imm_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int())
],
ty::mk_int()),
"store" => (0,
~[
ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()),
ty::mk_int()
],
ty::mk_nil()),
"cxchg" => {
(0,
~[
ty::mk_mut_ptr(tcx, ty::mk_int()),
ty::mk_int(),
ty::mk_int()
],
ty::mk_int())
}
"load" => {
(0,
~[ty::mk_imm_ptr(tcx, ty::mk_int())],
ty::mk_int())
}
"store" => {
(0,
~[ty::mk_mut_ptr(tcx, ty::mk_int()), ty::mk_int()],
ty::mk_nil())
}

"xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
"min" | "umax" | "umin" => {
(0, ~[ty::mk_mut_rptr(tcx,
ty::re_bound(ty::br_anon(0)),
ty::mk_int()), ty::mk_int() ], ty::mk_int())
(0,
~[ty::mk_mut_ptr(tcx, ty::mk_int()), ty::mk_int()],
ty::mk_int())
}

op => {
2 changes: 1 addition & 1 deletion src/libstd/rt/comm.rs
Original file line number Diff line number Diff line change
@@ -210,7 +210,7 @@ impl<T> Peekable<T> for PortOne<T> {
fn peek(&self) -> bool {
unsafe {
let packet: *mut Packet<T> = self.inner.packet();
let oldstate = atomic_load(&mut (*packet).state);
let oldstate = atomic_load(&(*packet).state);
match oldstate {
STATE_BOTH => false,
STATE_ONE => (*packet).payload.is_some(),
240 changes: 239 additions & 1 deletion src/libstd/unstable/intrinsics.rs
Original file line number Diff line number Diff line change
@@ -158,105 +158,343 @@ pub trait TyVisitor {

#[abi = "rust-intrinsic"]
pub extern "rust-intrinsic" {
// XXX: Remove stage0 cfg attributes and borrowed pointer versions
// of atomics after next snapshot.

/// Atomic compare and exchange, sequentially consistent.
#[cfg(not(stage0))]
pub fn atomic_cxchg(dst: *mut int, old: int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_cxchg(dst: &mut int, old: int, src: int) -> int;
/// Atomic compare and exchange, acquire ordering.
#[cfg(not(stage0))]
pub fn atomic_cxchg_acq(dst: *mut int, old: int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_cxchg_acq(dst: &mut int, old: int, src: int) -> int;
/// Atomic compare and exchange, release ordering.
#[cfg(not(stage0))]
pub fn atomic_cxchg_rel(dst: *mut int, old: int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_cxchg_acqrel(dst: *mut int, old: int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_cxchg_acqrel(dst: &mut int, old: int, src: int) -> int;
pub fn atomic_cxchg_relaxed(dst: &mut int, old: int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_cxchg_relaxed(dst: *mut int, old: int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_cxchg_relaxed(dst: &mut int, old: int, src: int) -> int;

/// Atomic load, sequentially consistent.
#[cfg(not(stage0))]
pub fn atomic_load(src: *int) -> int;
#[cfg(stage0)]
pub fn atomic_load(src: &int) -> int;
/// Atomic load, acquire ordering.
#[cfg(not(stage0))]
pub fn atomic_load_acq(src: *int) -> int;
#[cfg(stage0)]
pub fn atomic_load_acq(src: &int) -> int;

#[cfg(not(stage0))]
pub fn atomic_load_relaxed(src: *int) -> int;
#[cfg(stage0)]
pub fn atomic_load_relaxed(src: &int) -> int;

/// Atomic store, sequentially consistent.
#[cfg(not(stage0))]
pub fn atomic_store(dst: *mut int, val: int);
#[cfg(stage0)]
pub fn atomic_store(dst: &mut int, val: int);
/// Atomic store, release ordering.
#[cfg(not(stage0))]
pub fn atomic_store_rel(dst: *mut int, val: int);
#[cfg(stage0)]
pub fn atomic_store_rel(dst: &mut int, val: int);

#[cfg(not(stage0))]
pub fn atomic_store_relaxed(dst: *mut int, val: int);
#[cfg(stage0)]
pub fn atomic_store_relaxed(dst: &mut int, val: int);

/// Atomic exchange, sequentially consistent.
#[cfg(not(stage0))]
pub fn atomic_xchg(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xchg(dst: &mut int, src: int) -> int;
/// Atomic exchange, acquire ordering.
#[cfg(not(stage0))]
pub fn atomic_xchg_acq(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xchg_acq(dst: &mut int, src: int) -> int;
/// Atomic exchange, release ordering.
#[cfg(not(stage0))]
pub fn atomic_xchg_rel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xchg_rel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_xchg_acqrel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xchg_acqrel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_xchg_relaxed(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xchg_relaxed(dst: &mut int, src: int) -> int;

/// Atomic addition, sequentially consistent.
#[cfg(not(stage0))]
pub fn atomic_xadd(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xadd(dst: &mut int, src: int) -> int;
/// Atomic addition, acquire ordering.
#[cfg(not(stage0))]
pub fn atomic_xadd_acq(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xadd_acq(dst: &mut int, src: int) -> int;
/// Atomic addition, release ordering.
#[cfg(not(stage0))]
pub fn atomic_xadd_rel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xadd_rel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_xadd_acqrel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xadd_acqrel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_xadd_relaxed(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xadd_relaxed(dst: &mut int, src: int) -> int;

/// Atomic subtraction, sequentially consistent.
#[cfg(not(stage0))]
pub fn atomic_xsub(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xsub(dst: &mut int, src: int) -> int;
/// Atomic subtraction, acquire ordering.
#[cfg(not(stage0))]
pub fn atomic_xsub_acq(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xsub_acq(dst: &mut int, src: int) -> int;
/// Atomic subtraction, release ordering.
#[cfg(not(stage0))]
pub fn atomic_xsub_rel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xsub_rel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_xsub_acqrel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xsub_acqrel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_xsub_relaxed(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xsub_relaxed(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_and(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_and(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_and_acq(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_and_acq(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_and_rel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_and_rel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_and_acqrel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_and_acqrel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_and_relaxed(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_and_relaxed(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_nand(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_nand(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_nand_acq(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_nand_acq(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_nand_rel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_nand_rel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_nand_acqrel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_nand_acqrel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_nand_relaxed(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_nand_relaxed(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_or(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_or(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_or_acq(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_or_acq(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_or_rel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_or_rel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_or_acqrel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_or_acqrel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_or_relaxed(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_or_relaxed(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_xor(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xor(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_xor_acq(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xor_acq(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_xor_rel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xor_rel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_xor_acqrel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xor_acqrel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_xor_relaxed(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_xor_relaxed(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_max(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_max(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_max_acq(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_max_acq(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_max_rel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_max_rel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_max_acqrel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_max_acqrel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_max_relaxed(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_max_relaxed(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_min(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_min(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_min_acq(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_min_acq(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_min_rel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_min_rel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_min_acqrel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_min_acqrel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_min_relaxed(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_min_relaxed(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_umin(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_umin(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_umin_acq(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_umin_acq(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_umin_rel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_umin_rel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_umin_acqrel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_umin_acqrel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_umin_relaxed(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_umin_relaxed(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_umax(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_umax(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_umax_acq(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_umax_acq(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_umax_rel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_umax_rel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_umax_acqrel(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_umax_acqrel(dst: &mut int, src: int) -> int;

#[cfg(not(stage0))]
pub fn atomic_umax_relaxed(dst: *mut int, src: int) -> int;
#[cfg(stage0)]
pub fn atomic_umax_relaxed(dst: &mut int, src: int) -> int;

/// The size of a type in bytes.
26 changes: 13 additions & 13 deletions src/test/auxiliary/cci_intrinsic.rs
Original file line number Diff line number Diff line change
@@ -11,26 +11,26 @@
pub mod rusti {
#[abi = "rust-intrinsic"]
pub extern "rust-intrinsic" {
fn atomic_cxchg(dst: &mut int, old: int, src: int) -> int;
fn atomic_cxchg_acq(dst: &mut int, old: int, src: int) -> int;
fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int;
fn atomic_cxchg(dst: *mut int, old: int, src: int) -> int;
fn atomic_cxchg_acq(dst: *mut int, old: int, src: int) -> int;
fn atomic_cxchg_rel(dst: *mut int, old: int, src: int) -> int;

fn atomic_xchg(dst: &mut int, src: int) -> int;
fn atomic_xchg_acq(dst: &mut int, src: int) -> int;
fn atomic_xchg_rel(dst: &mut int, src: int) -> int;
fn atomic_xchg(dst: *mut int, src: int) -> int;
fn atomic_xchg_acq(dst: *mut int, src: int) -> int;
fn atomic_xchg_rel(dst: *mut int, src: int) -> int;

fn atomic_xadd(dst: &mut int, src: int) -> int;
fn atomic_xadd_acq(dst: &mut int, src: int) -> int;
fn atomic_xadd_rel(dst: &mut int, src: int) -> int;
fn atomic_xadd(dst: *mut int, src: int) -> int;
fn atomic_xadd_acq(dst: *mut int, src: int) -> int;
fn atomic_xadd_rel(dst: *mut int, src: int) -> int;

fn atomic_xsub(dst: &mut int, src: int) -> int;
fn atomic_xsub_acq(dst: &mut int, src: int) -> int;
fn atomic_xsub_rel(dst: &mut int, src: int) -> int;
fn atomic_xsub(dst: *mut int, src: int) -> int;
fn atomic_xsub_acq(dst: *mut int, src: int) -> int;
fn atomic_xsub_rel(dst: *mut int, src: int) -> int;
}
}

#[inline(always)]
pub fn atomic_xchg(dst: &mut int, src: int) -> int {
pub fn atomic_xchg(dst: *mut int, src: int) -> int {
unsafe {
rusti::atomic_xchg(dst, src)
}
88 changes: 44 additions & 44 deletions src/test/run-pass/intrinsic-atomics.rs
Original file line number Diff line number Diff line change
@@ -11,69 +11,69 @@
mod rusti {
#[abi = "rust-intrinsic"]
pub extern "rust-intrinsic" {
pub fn atomic_cxchg(dst: &mut int, old: int, src: int) -> int;
pub fn atomic_cxchg_acq(dst: &mut int, old: int, src: int) -> int;
pub fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int;
pub fn atomic_cxchg(dst: *mut int, old: int, src: int) -> int;
pub fn atomic_cxchg_acq(dst: *mut int, old: int, src: int) -> int;
pub fn atomic_cxchg_rel(dst: *mut int, old: int, src: int) -> int;

pub fn atomic_load(src: &int) -> int;
pub fn atomic_load_acq(src: &int) -> int;
pub fn atomic_load(src: *int) -> int;
pub fn atomic_load_acq(src: *int) -> int;

pub fn atomic_store(dst: &mut int, val: int);
pub fn atomic_store_rel(dst: &mut int, val: int);
pub fn atomic_store(dst: *mut int, val: int);
pub fn atomic_store_rel(dst: *mut int, val: int);

pub fn atomic_xchg(dst: &mut int, src: int) -> int;
pub fn atomic_xchg_acq(dst: &mut int, src: int) -> int;
pub fn atomic_xchg_rel(dst: &mut int, src: int) -> int;
pub fn atomic_xchg(dst: *mut int, src: int) -> int;
pub fn atomic_xchg_acq(dst: *mut int, src: int) -> int;
pub fn atomic_xchg_rel(dst: *mut int, src: int) -> int;

pub fn atomic_xadd(dst: &mut int, src: int) -> int;
pub fn atomic_xadd_acq(dst: &mut int, src: int) -> int;
pub fn atomic_xadd_rel(dst: &mut int, src: int) -> int;
pub fn atomic_xadd(dst: *mut int, src: int) -> int;
pub fn atomic_xadd_acq(dst: *mut int, src: int) -> int;
pub fn atomic_xadd_rel(dst: *mut int, src: int) -> int;

pub fn atomic_xsub(dst: &mut int, src: int) -> int;
pub fn atomic_xsub_acq(dst: &mut int, src: int) -> int;
pub fn atomic_xsub_rel(dst: &mut int, src: int) -> int;
pub fn atomic_xsub(dst: *mut int, src: int) -> int;
pub fn atomic_xsub_acq(dst: *mut int, src: int) -> int;
pub fn atomic_xsub_rel(dst: *mut int, src: int) -> int;
}
}

pub fn main() {
unsafe {
let mut x = ~1;
let mut x = 1;
assert_eq!(rusti::atomic_load(&x), 1);
x = 5;
assert_eq!(rusti::atomic_load_acq(&x), 5);

assert_eq!(rusti::atomic_load(x), 1);
*x = 5;
assert_eq!(rusti::atomic_load_acq(x), 5);

rusti::atomic_store(x,3);
assert_eq!(*x, 3);
rusti::atomic_store_rel(x,1);
assert_eq!(*x, 1);
rusti::atomic_store(&mut x,3);
assert_eq!(x, 3);
rusti::atomic_store_rel(&mut x,1);
assert_eq!(x, 1);

assert_eq!(rusti::atomic_cxchg(x, 1, 2), 1);
assert_eq!(*x, 2);
assert_eq!(rusti::atomic_cxchg(&mut x, 1, 2), 1);
assert_eq!(x, 2);

assert_eq!(rusti::atomic_cxchg_acq(x, 1, 3), 2);
assert_eq!(*x, 2);
assert_eq!(rusti::atomic_cxchg_acq(&mut x, 1, 3), 2);
assert_eq!(x, 2);

assert_eq!(rusti::atomic_cxchg_rel(x, 2, 1), 2);
assert_eq!(*x, 1);
assert_eq!(rusti::atomic_cxchg_rel(&mut x, 2, 1), 2);
assert_eq!(x, 1);

assert_eq!(rusti::atomic_xchg(x, 0), 1);
assert_eq!(*x, 0);
assert_eq!(rusti::atomic_xchg(&mut x, 0), 1);
assert_eq!(x, 0);

assert_eq!(rusti::atomic_xchg_acq(x, 1), 0);
assert_eq!(*x, 1);
assert_eq!(rusti::atomic_xchg_acq(&mut x, 1), 0);
assert_eq!(x, 1);

assert_eq!(rusti::atomic_xchg_rel(x, 0), 1);
assert_eq!(*x, 0);
assert_eq!(rusti::atomic_xchg_rel(&mut x, 0), 1);
assert_eq!(x, 0);

assert_eq!(rusti::atomic_xadd(x, 1), 0);
assert_eq!(rusti::atomic_xadd_acq(x, 1), 1);
assert_eq!(rusti::atomic_xadd_rel(x, 1), 2);
assert_eq!(*x, 3);
assert_eq!(rusti::atomic_xadd(&mut x, 1), 0);
assert_eq!(rusti::atomic_xadd_acq(&mut x, 1), 1);
assert_eq!(rusti::atomic_xadd_rel(&mut x, 1), 2);
assert_eq!(x, 3);

assert_eq!(rusti::atomic_xsub(x, 1), 3);
assert_eq!(rusti::atomic_xsub_acq(x, 1), 2);
assert_eq!(rusti::atomic_xsub_rel(x, 1), 1);
assert_eq!(*x, 0);
assert_eq!(rusti::atomic_xsub(&mut x, 1), 3);
assert_eq!(rusti::atomic_xsub_acq(&mut x, 1), 2);
assert_eq!(rusti::atomic_xsub_rel(&mut x, 1), 1);
assert_eq!(x, 0);
}
}