Skip to content

Commit 76453f5

Browse files
committed
use volatile load/store for mutex state
1 parent 34ef198 commit 76453f5

File tree

1 file changed

+23
-6
lines changed

1 file changed

+23
-6
lines changed

src/sync/mutex.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,39 @@ package sync
33
import (
44
"internal/task"
55
_ "unsafe"
6+
7+
"github.com/tinygo-org/tinygo/src/runtime/volatile"
68
)
79

810
type Mutex struct {
9-
locked bool
11+
state uint8 // Set to non-zero if locked.
1012
blocked task.Stack
1113
}
1214

1315
//go:linkname scheduleTask runtime.runqueuePushBack
1416
func scheduleTask(*task.Task)
1517

1618
func (m *Mutex) Lock() {
17-
if m.locked {
19+
if m.islocked() {
1820
// Push self onto stack of blocked tasks, and wait to be resumed.
1921
m.blocked.Push(task.Current())
2022
task.Pause()
2123
return
2224
}
2325

24-
m.locked = true
26+
m.setlock(true)
2527
}
2628

2729
func (m *Mutex) Unlock() {
28-
if !m.locked {
30+
if !m.islocked() {
2931
panic("sync: unlock of unlocked Mutex")
3032
}
3133

3234
// Wake up a blocked task, if applicable.
3335
if t := m.blocked.Pop(); t != nil {
3436
scheduleTask(t)
3537
} else {
36-
m.locked = false
38+
m.setlock(false)
3739
}
3840
}
3941

@@ -43,13 +45,28 @@ func (m *Mutex) Unlock() {
4345
// and use of TryLock is often a sign of a deeper problem
4446
// in a particular use of mutexes.
4547
func (m *Mutex) TryLock() bool {
46-
if m.locked {
48+
if m.islocked() {
4749
return false
4850
}
4951
m.Lock()
5052
return true
5153
}
5254

55+
func (m *Mutex) islocked() bool {
56+
return volatile.LoadUint8(&m.state) != 0
57+
}
58+
59+
func (m *Mutex) setlock(b bool) {
60+
volatile.StoreUint8(&m.state, boolToU8(b))
61+
}
62+
63+
func boolToU8(b bool) uint8 {
64+
if b {
65+
return 1
66+
}
67+
return 0
68+
}
69+
5370
type RWMutex struct {
5471
// waitingWriters are all of the tasks waiting for write locks.
5572
waitingWriters task.Stack

0 commit comments

Comments
 (0)