| // Copyright 2015 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| #include "textflag.h" |
| |
| // Use kernel version instead of native armcas in asm_arm.s. |
| // See ../../../sync/atomic/asm_linux_arm.s for details. |
| TEXT cas<>(SB),NOSPLIT,$0 |
| MOVW $0xffff0fc0, R15 // R15 is hardware PC. |
| |
| TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0 |
| MOVW ptr+0(FP), R2 |
| MOVW old+4(FP), R0 |
| loop: |
| MOVW new+8(FP), R1 |
| BL cas<>(SB) |
| BCC check |
| MOVW $1, R0 |
| MOVB R0, ret+12(FP) |
| RET |
| check: |
| // Kernel lies; double-check. |
| MOVW ptr+0(FP), R2 |
| MOVW old+4(FP), R0 |
| MOVW 0(R2), R3 |
| CMP R0, R3 |
| BEQ loop |
| MOVW $0, R0 |
| MOVB R0, ret+12(FP) |
| RET |
| |
| TEXT runtime∕internal∕atomic·Casp1(SB),NOSPLIT,$0 |
| B runtime∕internal∕atomic·Cas(SB) |
| |
| // As for cas, memory barriers are complicated on ARM, but the kernel |
| // provides a user helper. ARMv5 does not support SMP and has no |
| // memory barrier instruction at all. ARMv6 added SMP support and has |
| // a memory barrier, but it requires writing to a coprocessor |
| // register. ARMv7 introduced the DMB instruction, but it's expensive |
| // even on single-core devices. The kernel helper takes care of all of |
| // this for us. |