Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 0 additions & 25 deletions src/runtime/runtime_rp2.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,31 +297,6 @@ var (
futexLock = spinLock{id: 3}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

id is an implementation detail of rp2040 spinlocks, whereas on rp2350 ids have some meaning but are unusued. I suggest moving the spinlock variables to the rpXXXX.go files and avoid the id field on rp2350.

)

// A hardware spinlock, one of the 32 spinlocks defined in the SIO peripheral.
type spinLock struct {
id uint8
}

// Return the spinlock register: rp.SIO.SPINLOCKx
func (l *spinLock) spinlock() *volatile.Register32 {
return (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&rp.SIO.SPINLOCK0), l.id*4))
}

func (l *spinLock) Lock() {
// Wait for the lock to be available.
spinlock := l.spinlock()
for spinlock.Get() == 0 {
// TODO: use wfe and send an event when unlocking so the CPU can go to
// sleep while waiting for the lock.
// Unfortunately when doing that, time.Sleep() seems to hang somewhere.
// This needs some debugging to figure out.
}
}

func (l *spinLock) Unlock() {
l.spinlock().Set(0)
}

// Wait until a signal is received, indicating that it can resume from the
// spinloop.
func spinLoopWait() {
Expand Down
27 changes: 27 additions & 0 deletions src/runtime/runtime_rp2040.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,36 @@ package runtime

import (
"device/rp"
"runtime/volatile"
"unsafe"
)

const (
sioIrqFifoProc0 = rp.IRQ_SIO_IRQ_PROC0
sioIrqFifoProc1 = rp.IRQ_SIO_IRQ_PROC1
)

// A hardware spinlock, one of the 32 spinlocks defined in the SIO peripheral.
type spinLock struct {
id uint8
}

// Return the spinlock register: rp.SIO.SPINLOCKx
func (l *spinLock) spinlock() *volatile.Register32 {
return (*volatile.Register32)(unsafe.Add(unsafe.Pointer(&rp.SIO.SPINLOCK0), l.id*4))
}

func (l *spinLock) Lock() {
// Wait for the lock to be available.
spinlock := l.spinlock()
for spinlock.Get() == 0 {
// TODO: use wfe and send an event when unlocking so the CPU can go to
// sleep while waiting for the lock.
// Unfortunately when doing that, time.Sleep() seems to hang somewhere.
// This needs some debugging to figure out.
}
}

func (l *spinLock) Unlock() {
l.spinlock().Set(0)
}
23 changes: 23 additions & 0 deletions src/runtime/runtime_rp2350.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package runtime

import (
"device/rp"
"sync/atomic"
)

const (
Expand All @@ -14,3 +15,25 @@ const (
sioIrqFifoProc0 = rp.IRQ_SIO_IRQ_FIFO
sioIrqFifoProc1 = rp.IRQ_SIO_IRQ_FIFO
)

type spinLock struct {
atomic.Uint32
id uint8
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete field.

}

func (l *spinLock) Lock() {
// Try to replace 0 with 1. Once we succeed, the lock has been acquired.
for !l.Uint32.CompareAndSwap(0, 1) {
spinLoopWait()
}
}

func (l *spinLock) Unlock() {
// Safety check: the spinlock should have been locked.
if schedulerAsserts && l.Uint32.Load() != 1 {
runtimePanic("unlock of unlocked spinlock")
}

// Unlock the lock. Simply write 0, because we already know it is locked.
l.Uint32.Store(0)
}
Loading