| // 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. |