mirror of
https://github.com/golang/go
synced 2024-11-20 06:34:40 -07:00
f5d494bbdf
Currently its possible for the garbage collector to observe uninitialized memory or stale heap bitmap bits on weakly ordered architectures such as ARM and PPC. On such architectures, the stores that zero newly allocated memory and initialize its heap bitmap may move after a store in user code that makes the allocated object observable by the garbage collector. To fix this, add a "publication barrier" (also known as an "export barrier") before returning from mallocgc. This is a store/store barrier that ensures any write done by user code that makes the returned object observable to the garbage collector will be ordered after the initialization performed by mallocgc. No barrier is necessary on the reading side because of the data dependency between loading the pointer and loading the contents of the object. Fixes one of the issues raised in #9984. Change-Id: Ia3d96ad9c5fc7f4d342f5e05ec0ceae700cd17c8 Reviewed-on: https://go-review.googlesource.com/11083 Reviewed-by: Rick Hudson <rlh@golang.org> Reviewed-by: Dmitry Vyukov <dvyukov@google.com> Reviewed-by: Minux Ma <minux@golang.org> Reviewed-by: Martin Capitanio <capnm9@gmail.com> Reviewed-by: Russ Cox <rsc@golang.org>
118 lines
2.3 KiB
ArmAsm
118 lines
2.3 KiB
ArmAsm
// Copyright 2014 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"
|
|
|
|
// uint32 runtime·atomicload(uint32 volatile* addr)
|
|
TEXT ·atomicload(SB),NOSPLIT,$-8-12
|
|
MOVD ptr+0(FP), R0
|
|
LDARW (R0), R0
|
|
MOVW R0, ret+8(FP)
|
|
RET
|
|
|
|
// uint64 runtime·atomicload64(uint64 volatile* addr)
|
|
TEXT ·atomicload64(SB),NOSPLIT,$-8-16
|
|
MOVD ptr+0(FP), R0
|
|
LDAR (R0), R0
|
|
MOVD R0, ret+8(FP)
|
|
RET
|
|
|
|
// void *runtime·atomicloadp(void *volatile *addr)
|
|
TEXT ·atomicloadp(SB),NOSPLIT,$-8-16
|
|
MOVD ptr+0(FP), R0
|
|
LDAR (R0), R0
|
|
MOVD R0, ret+8(FP)
|
|
RET
|
|
|
|
TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-16
|
|
B runtime·atomicstore64(SB)
|
|
|
|
TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
|
|
MOVD ptr+0(FP), R0
|
|
MOVW val+8(FP), R1
|
|
STLRW R1, (R0)
|
|
RET
|
|
|
|
TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
|
|
MOVD ptr+0(FP), R0
|
|
MOVD val+8(FP), R1
|
|
STLR R1, (R0)
|
|
RET
|
|
|
|
TEXT runtime·xchg(SB), NOSPLIT, $0-20
|
|
again:
|
|
MOVD ptr+0(FP), R0
|
|
MOVW new+8(FP), R1
|
|
LDAXRW (R0), R2
|
|
STLXRW R1, (R0), R3
|
|
CBNZ R3, again
|
|
MOVW R2, ret+16(FP)
|
|
RET
|
|
|
|
TEXT runtime·xchg64(SB), NOSPLIT, $0-24
|
|
again:
|
|
MOVD ptr+0(FP), R0
|
|
MOVD new+8(FP), R1
|
|
LDAXR (R0), R2
|
|
STLXR R1, (R0), R3
|
|
CBNZ R3, again
|
|
MOVD R2, ret+16(FP)
|
|
RET
|
|
|
|
// bool runtime·cas64(uint64 *ptr, uint64 old, uint64 new)
|
|
// Atomically:
|
|
// if(*val == *old){
|
|
// *val = new;
|
|
// return 1;
|
|
// } else {
|
|
// return 0;
|
|
// }
|
|
TEXT runtime·cas64(SB), NOSPLIT, $0-25
|
|
MOVD ptr+0(FP), R0
|
|
MOVD old+8(FP), R1
|
|
MOVD new+16(FP), R2
|
|
again:
|
|
LDAXR (R0), R3
|
|
CMP R1, R3
|
|
BNE ok
|
|
STLXR R2, (R0), R3
|
|
CBNZ R3, again
|
|
ok:
|
|
CSET EQ, R0
|
|
MOVB R0, ret+24(FP)
|
|
RET
|
|
|
|
// uint32 xadd(uint32 volatile *ptr, int32 delta)
|
|
// Atomically:
|
|
// *val += delta;
|
|
// return *val;
|
|
TEXT runtime·xadd(SB), NOSPLIT, $0-20
|
|
again:
|
|
MOVD ptr+0(FP), R0
|
|
MOVW delta+8(FP), R1
|
|
LDAXRW (R0), R2
|
|
ADDW R2, R1, R2
|
|
STLXRW R2, (R0), R3
|
|
CBNZ R3, again
|
|
MOVW R2, ret+16(FP)
|
|
RET
|
|
|
|
TEXT runtime·xadd64(SB), NOSPLIT, $0-24
|
|
again:
|
|
MOVD ptr+0(FP), R0
|
|
MOVD delta+8(FP), R1
|
|
LDAXR (R0), R2
|
|
ADD R2, R1, R2
|
|
STLXR R2, (R0), R3
|
|
CBNZ R3, again
|
|
MOVD R2, ret+16(FP)
|
|
RET
|
|
|
|
TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24
|
|
B runtime·xchg64(SB)
|
|
|
|
TEXT ·publicationBarrier(SB),NOSPLIT,$-8-0
|
|
DMB $0xe // DMB ST
|
|
RET
|