1// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// +build mips mipsle
6
7package atomic
8
9import (
10	"runtime/internal/sys"
11	"unsafe"
12)
13
14// TODO implement lock striping
15var lock struct {
16	state uint32
17	pad   [sys.CacheLineSize - 4]byte
18}
19
20//go:noescape
21func spinLock(state *uint32)
22
23//go:noescape
24func spinUnlock(state *uint32)
25
26//go:nosplit
27func lockAndCheck(addr *uint64) {
28	// ensure 8-byte alignement
29	if uintptr(unsafe.Pointer(addr))&7 != 0 {
30		addr = nil
31	}
32	// force dereference before taking lock
33	_ = *addr
34
35	spinLock(&lock.state)
36}
37
38//go:nosplit
39func unlock() {
40	spinUnlock(&lock.state)
41}
42
43//go:nosplit
44func unlockNoFence() {
45	lock.state = 0
46}
47
48//go:nosplit
49func Xadd64(addr *uint64, delta int64) (new uint64) {
50	lockAndCheck(addr)
51
52	new = *addr + uint64(delta)
53	*addr = new
54
55	unlock()
56	return
57}
58
59//go:nosplit
60func Xchg64(addr *uint64, new uint64) (old uint64) {
61	lockAndCheck(addr)
62
63	old = *addr
64	*addr = new
65
66	unlock()
67	return
68}
69
70//go:nosplit
71func Cas64(addr *uint64, old, new uint64) (swapped bool) {
72	lockAndCheck(addr)
73
74	if (*addr) == old {
75		*addr = new
76		unlock()
77		return true
78	}
79
80	unlockNoFence()
81	return false
82}
83
84//go:nosplit
85func Load64(addr *uint64) (val uint64) {
86	lockAndCheck(addr)
87
88	val = *addr
89
90	unlock()
91	return
92}
93
94//go:nosplit
95func Store64(addr *uint64, val uint64) {
96	lockAndCheck(addr)
97
98	*addr = val
99
100	unlock()
101	return
102}
103
104//go:noescape
105func Xadd(ptr *uint32, delta int32) uint32
106
107//go:noescape
108func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
109
110//go:noescape
111func Xchg(ptr *uint32, new uint32) uint32
112
113//go:noescape
114func Xchguintptr(ptr *uintptr, new uintptr) uintptr
115
116//go:noescape
117func Load(ptr *uint32) uint32
118
119//go:noescape
120func Loadp(ptr unsafe.Pointer) unsafe.Pointer
121
122//go:noescape
123func And8(ptr *uint8, val uint8)
124
125//go:noescape
126func Or8(ptr *uint8, val uint8)
127
128//go:noescape
129func Store(ptr *uint32, val uint32)
130
131// NO go:noescape annotation; see atomic_pointer.go.
132func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer)
133