Skip to content

Commit 76d5b3d

Browse files
committed
sync: don't use volatile in Mutex
Volatile loads/stors are only useful for communication with interrupts or for memory-mapped I/O. They do not provide any sort of safety for sync.Mutex, while making it *appear* as if it is more safe. * `sync.Mutex` cannot be used safely inside interrupts, because any blocking calls (including `Lock`) will cause a runtime panic. * For multithreading, `volatile` is also the wrong choice. Atomic operations should be used instead, and the current code would not work for multithreaded programs anyway.
1 parent 9151326 commit 76d5b3d

File tree

1 file changed

+6
-23
lines changed

1 file changed

+6
-23
lines changed

src/sync/mutex.go

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,37 @@ package sync
33
import (
44
"internal/task"
55
_ "unsafe"
6-
7-
"runtime/volatile"
86
)
97

108
type Mutex struct {
11-
state uint8 // Set to non-zero if locked.
9+
locked bool
1210
blocked task.Stack
1311
}
1412

1513
//go:linkname scheduleTask runtime.runqueuePushBack
1614
func scheduleTask(*task.Task)
1715

1816
func (m *Mutex) Lock() {
19-
if m.islocked() {
17+
if m.locked {
2018
// Push self onto stack of blocked tasks, and wait to be resumed.
2119
m.blocked.Push(task.Current())
2220
task.Pause()
2321
return
2422
}
2523

26-
m.setlock(true)
24+
m.locked = true
2725
}
2826

2927
func (m *Mutex) Unlock() {
30-
if !m.islocked() {
28+
if !m.locked {
3129
panic("sync: unlock of unlocked Mutex")
3230
}
3331

3432
// Wake up a blocked task, if applicable.
3533
if t := m.blocked.Pop(); t != nil {
3634
scheduleTask(t)
3735
} else {
38-
m.setlock(false)
36+
m.locked = false
3937
}
4038
}
4139

@@ -45,28 +43,13 @@ func (m *Mutex) Unlock() {
4543
// and use of TryLock is often a sign of a deeper problem
4644
// in a particular use of mutexes.
4745
func (m *Mutex) TryLock() bool {
48-
if m.islocked() {
46+
if m.locked {
4947
return false
5048
}
5149
m.Lock()
5250
return true
5351
}
5452

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-
7053
type RWMutex struct {
7154
// waitingWriters are all of the tasks waiting for write locks.
7255
waitingWriters task.Stack

0 commit comments

Comments
 (0)