aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2024-10-28 14:43:04 +0100
committerAyke <[email protected]>2024-10-28 16:43:28 +0100
commit76d5b3d786034b5d58167a4b47ec36539bbdf55a (patch)
treeaa45b6ce6a3324d800d3c83c4420d5abd2277147
parent915132645eb29eed4de3fbf78d0e1077a8c6a8cf (diff)
downloadtinygo-76d5b3d786034b5d58167a4b47ec36539bbdf55a.tar.gz
tinygo-76d5b3d786034b5d58167a4b47ec36539bbdf55a.zip
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.
-rw-r--r--src/sync/mutex.go29
1 files changed, 6 insertions, 23 deletions
diff --git a/src/sync/mutex.go b/src/sync/mutex.go
index 59f320d5d..3db705af0 100644
--- a/src/sync/mutex.go
+++ b/src/sync/mutex.go
@@ -3,12 +3,10 @@ package sync
import (
"internal/task"
_ "unsafe"
-
- "runtime/volatile"
)
type Mutex struct {
- state uint8 // Set to non-zero if locked.
+ locked bool
blocked task.Stack
}
@@ -16,18 +14,18 @@ type Mutex struct {
func scheduleTask(*task.Task)
func (m *Mutex) Lock() {
- if m.islocked() {
+ if m.locked {
// Push self onto stack of blocked tasks, and wait to be resumed.
m.blocked.Push(task.Current())
task.Pause()
return
}
- m.setlock(true)
+ m.locked = true
}
func (m *Mutex) Unlock() {
- if !m.islocked() {
+ if !m.locked {
panic("sync: unlock of unlocked Mutex")
}
@@ -35,7 +33,7 @@ func (m *Mutex) Unlock() {
if t := m.blocked.Pop(); t != nil {
scheduleTask(t)
} else {
- m.setlock(false)
+ m.locked = false
}
}
@@ -45,28 +43,13 @@ func (m *Mutex) Unlock() {
// and use of TryLock is often a sign of a deeper problem
// in a particular use of mutexes.
func (m *Mutex) TryLock() bool {
- if m.islocked() {
+ if m.locked {
return false
}
m.Lock()
return true
}
-func (m *Mutex) islocked() bool {
- return volatile.LoadUint8(&m.state) != 0
-}
-
-func (m *Mutex) setlock(b bool) {
- volatile.StoreUint8(&m.state, boolToU8(b))
-}
-
-func boolToU8(b bool) uint8 {
- if b {
- return 1
- }
- return 0
-}
-
type RWMutex struct {
// waitingWriters are all of the tasks waiting for write locks.
waitingWriters task.Stack