Skip to content

Commit

Permalink
Auto merge of rust-lang#44978 - jamesmunns:armv5te-os-atomics, r=alex…
Browse files Browse the repository at this point in the history
…crichton

Allow atomic operations up to 32 bits

The ARMv5te platform does not have instruction-level support for atomics, however the kernel provides [user space helpers] which can be used to perform atomic operations. When linked with `libgcc`, the atomic symbols needed by Rust will be provided, rather than CPU level intrinsics.

[user space helpers]: https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt

32-bit versions of these kernel level helpers were introduced in Linux Kernel 2.6.12, and 64-bit version of these kernel level helpers were introduced in Linux Kernel 3.1. I have selected 32 bit versions as std currently only requires Linux version 2.6.18 and above as far as I am aware.

As this target is specifically linux and gnueabi, it is reasonable to assume the Linux Kernel and libc will be available for the target. There is a large performance penalty, as we are not using CPU level intrinsics, however this penalty is likely preferable to not having the target at all.

I have used this change in a custom target (along with xargo) to build std, as well as a number of higher level crates.

## Additional information

For reference, here is what a a code snippet decompiles to:

```rust
use std::sync::atomic::{AtomicIsize, Ordering};

#[no_mangle]
pub extern fn foo(a: &AtomicIsize) -> isize {

    a.fetch_add(1, Ordering::SeqCst)
}
```

```
Disassembly of section .text.foo:

00000000 <foo>:
   0:	e92d4800 	push	{fp, lr}
   4:	e3a01001 	mov	r1, #1
   8:	ebfffffe 	bl	0 <__sync_fetch_and_add_4>
   c:	e8bd8800 	pop	{fp, pc}
```

Which in turn is provided by `libgcc.a`, which has code which looks like this:

```
Disassembly of section .text:

00000000 <__sync_fetch_and_add_4>:
       0:	e92d40f8 	push	{r3, r4, r5, r6, r7, lr}
       4:	e1a05000 	mov	r5, r0
       8:	e1a07001 	mov	r7, r1
       c:	e59f6028 	ldr	r6, [pc, rust-lang#40]	; 3c <__sync_fetch_and_add_4+0x3c>
      10:	e5954000 	ldr	r4, [r5]
      14:	e1a02005 	mov	r2, r5
      18:	e1a00004 	mov	r0, r4
      1c:	e0841007 	add	r1, r4, r7
      20:	e1a0e00f 	mov	lr, pc
      24:	e12fff16 	bx	r6
      28:	e3500000 	cmp	r0, #0
      2c:	1afffff7 	bne	10 <__sync_fetch_and_add_4+0x10>
      30:	e1a00004 	mov	r0, r4
      34:	e8bd40f8 	pop	{r3, r4, r5, r6, r7, lr}
      38:	e12fff1e 	bx	lr
      3c:	ffff0fc0 	.word	0xffff0fc0
```

Where you can see the reference to `0xffff0fc0`, which is provided by the [user space helpers].
  • Loading branch information
bors committed Oct 8, 2017
2 parents ac76206 + 1e26094 commit f47f53c
Showing 1 changed file with 6 additions and 2 deletions.
8 changes: 6 additions & 2 deletions src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@ pub fn target() -> TargetResult {

options: TargetOptions {
features: "+soft-float,+strict-align".to_string(),
// No atomic instructions on ARMv5
max_atomic_width: Some(0),

// Atomic operations provided when linked with libgcc.
// FIXME: If the following PR is merged, the atomic operations would be
// provided by compiler-builtins instead with no change of behavior:
// https://github.com/rust-lang-nursery/compiler-builtins/pull/115/files
max_atomic_width: Some(32),
abi_blacklist: super::arm_base::abi_blacklist(),
.. base
}
Expand Down

0 comments on commit f47f53c

Please sign in to comment.