Skip to content

Commit

Permalink
runtime/internal/atomic: add mips operators for And/Or
Browse files Browse the repository at this point in the history
These primitives will be used by the new And/Or sync/atomic apis.

Implemented for mips/mipsle and mips64/mips64le.

For golang#61395

Change-Id: Icc604a2b5cdfe72646d47d3c6a0bb49a0fd0d353
GitHub-Last-Rev: 95dca2a
GitHub-Pull-Request: golang#63297
Reviewed-on: https://go-review.googlesource.com/c/go/+/531835
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
  • Loading branch information
mauri870 authored and lifubang committed May 20, 2024
1 parent 7f9edb4 commit 49cb8ac
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/internal/runtime/atomic/atomic_andor_generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build arm || mips || mipsle || mips64 || mips64le || wasm
//go:build arm || wasm

package atomic

Expand Down
18 changes: 18 additions & 0 deletions src/internal/runtime/atomic/atomic_mips64x.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,24 @@ func And(ptr *uint32, val uint32)
//go:noescape
func Or(ptr *uint32, val uint32)

//go:noescape
func And32(ptr *uint32, val uint32) uint32

//go:noescape
func Or32(ptr *uint32, val uint32) uint32

//go:noescape
func And64(ptr *uint64, val uint64) uint64

//go:noescape
func Or64(ptr *uint64, val uint64) uint64

//go:noescape
func Anduintptr(ptr *uintptr, val uintptr) uintptr

//go:noescape
func Oruintptr(ptr *uintptr, val uintptr) uintptr

//go:noescape
func Cas64(ptr *uint64, old, new uint64) bool

Expand Down
64 changes: 64 additions & 0 deletions src/internal/runtime/atomic/atomic_mips64x.s
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,70 @@ TEXT ·And(SB), NOSPLIT, $0-12
SYNC
RET

// func Or32(addr *uint32, v uint32) old uint32
TEXT ·Or32(SB), NOSPLIT, $0-20
MOVV ptr+0(FP), R1
MOVW val+8(FP), R2

SYNC
LL (R1), R3
OR R2, R3, R4
SC R4, (R1)
BEQ R4, -3(PC)
SYNC
MOVW R3, ret+16(FP)
RET

// func And32(addr *uint32, v uint32) old uint32
TEXT ·And32(SB), NOSPLIT, $0-20
MOVV ptr+0(FP), R1
MOVW val+8(FP), R2

SYNC
LL (R1), R3
AND R2, R3, R4
SC R4, (R1)
BEQ R4, -3(PC)
SYNC
MOVW R3, ret+16(FP)
RET

// func Or64(addr *uint64, v uint64) old uint64
TEXT ·Or64(SB), NOSPLIT, $0-24
MOVV ptr+0(FP), R1
MOVV val+8(FP), R2

SYNC
LLV (R1), R3
OR R2, R3, R4
SCV R4, (R1)
BEQ R4, -3(PC)
SYNC
MOVV R3, ret+16(FP)
RET

// func And64(addr *uint64, v uint64) old uint64
TEXT ·And64(SB), NOSPLIT, $0-24
MOVV ptr+0(FP), R1
MOVV val+8(FP), R2

SYNC
LLV (R1), R3
AND R2, R3, R4
SCV R4, (R1)
BEQ R4, -3(PC)
SYNC
MOVV R3, ret+16(FP)
RET

// func Anduintptr(addr *uintptr, v uintptr) old uintptr
TEXT ·Anduintptr(SB), NOSPLIT, $0-24
JMP ·And64(SB)

// func Oruintptr(addr *uintptr, v uintptr) old uintptr
TEXT ·Oruintptr(SB), NOSPLIT, $0-24
JMP ·Or64(SB)

// uint32 ·Load(uint32 volatile* ptr)
TEXT ·Load(SB),NOSPLIT|NOFRAME,$0-12
MOVV ptr+0(FP), R1
Expand Down
32 changes: 32 additions & 0 deletions src/internal/runtime/atomic/atomic_mipsx.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,26 @@ func Store64(addr *uint64, val uint64) {
return
}

//go:nosplit
func Or64(addr *uint64, val uint64) (old uint64) {
for {
old = *addr
if Cas64(addr, old, old|val) {
return old
}
}
}

//go:nosplit
func And64(addr *uint64, val uint64) (old uint64) {
for {
old = *addr
if Cas64(addr, old, old&val) {
return old
}
}
}

//go:noescape
func Xadd(ptr *uint32, delta int32) uint32

Expand Down Expand Up @@ -143,6 +163,18 @@ func And(ptr *uint32, val uint32)
//go:noescape
func Or(ptr *uint32, val uint32)

//go:noescape
func And32(ptr *uint32, val uint32) uint32

//go:noescape
func Or32(ptr *uint32, val uint32) uint32

//go:noescape
func Anduintptr(ptr *uintptr, val uintptr) uintptr

//go:noescape
func Oruintptr(ptr *uintptr, val uintptr) uintptr

//go:noescape
func Store(ptr *uint32, val uint32)

Expand Down
36 changes: 36 additions & 0 deletions src/internal/runtime/atomic/atomic_mipsx.s
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,42 @@ TEXT ·And(SB), NOSPLIT, $0-8
SYNC
RET

// func Or32(addr *uint32, v uint32) old uint32
TEXT ·Or32(SB), NOSPLIT, $0-12
MOVW ptr+0(FP), R1
MOVW val+4(FP), R2

SYNC
LL (R1), R3
OR R2, R3, R4
SC R4, (R1)
BEQ R4, -4(PC)
SYNC
MOVW R3, ret+8(FP)
RET

// func And32(addr *uint32, v uint32) old uint32
TEXT ·And32(SB), NOSPLIT, $0-12
MOVW ptr+0(FP), R1
MOVW val+4(FP), R2

SYNC
LL (R1), R3
AND R2, R3, R4
SC R4, (R1)
BEQ R4, -4(PC)
SYNC
MOVW R3, ret+8(FP)
RET

// func Anduintptr(addr *uintptr, v uintptr) old uintptr
TEXT ·Anduintptr(SB), NOSPLIT, $0-12
JMP ·And32(SB)

// func Oruintptr(addr *uintptr, v uintptr) old uintptr
TEXT ·Oruintptr(SB), NOSPLIT, $0-12
JMP ·Or32(SB)

TEXT ·spinLock(SB),NOSPLIT,$0-4
MOVW state+0(FP), R1
MOVW $1, R2
Expand Down
10 changes: 7 additions & 3 deletions src/runtime/cgo/gcc_stack_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,24 @@ x_cgo_getstackbound(uintptr bounds[2])
pthread_attr_t attr;
void *addr;
size_t size;
int err;

#if defined(__GLIBC__) || (defined(__sun) && !defined(__illumos__))
// pthread_getattr_np is a GNU extension supported in glibc.
// Solaris is not glibc but does support pthread_getattr_np
// (and the fallback doesn't work...). Illumos does not.
pthread_getattr_np(pthread_self(), &attr); // GNU extension
err = pthread_getattr_np(pthread_self(), &attr); // GNU extension
if (err != 0) {
// This is to have a backward compatibility with glibc < 2.32
pthread_attr_init(&attr);
pthread_getattr_np(pthread_self(), &attr);
}
pthread_attr_getstack(&attr, &addr, &size); // low address
#elif defined(__illumos__)
pthread_attr_init(&attr);
pthread_attr_get_np(pthread_self(), &attr);
pthread_attr_getstack(&attr, &addr, &size); // low address
#else
// We don't know how to get the current stacks, so assume they are the
// same as the default stack bounds.
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
addr = __builtin_frame_address(0) + 4096 - size;
Expand Down

0 comments on commit 49cb8ac

Please sign in to comment.