Skip to content

Commit c00fc84

Browse files
committed
Improved LockCore and UnlockCore documentation for clarity on usage, behavior, and limitations with the "cores" scheduler. Updated LockOSThread and UnlockOSThread comments to reflect core pinning behavior on RP2040/RP2350.
1 parent 870af4f commit c00fc84

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

src/machine/machine_rp2_cores.go

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,46 @@ package machine
44

55
const numCPU = 2 // RP2040 and RP2350 both have 2 cores
66

7-
// LockCore implementation for the cores scheduler.
7+
// LockCore sets the affinity for the current goroutine to the specified core.
8+
// This does not immediately migrate the goroutine; migration occurs at the next
9+
// scheduling point. See machine_rp2.go for full documentation.
10+
// Important: LockCore sets the affinity but does not immediately migrate the
11+
// goroutine to the target core. The actual migration happens at the next
12+
// scheduling point (e.g., channel operation, time.Sleep, or Gosched). After
13+
// that point, the goroutine will wait in the target core's queue if that core
14+
// is busy running another goroutine.
15+
//
16+
// To avoid potential blocking on a busy core, consider calling LockCore in an
17+
// init function before any other goroutines have started. This guarantees the
18+
// target core is available.
19+
//
20+
// This is useful for:
21+
// - Isolating time-critical operations to a dedicated core
22+
// - Improving cache locality for performance-sensitive code
23+
// - Exclusive access to core-local resources
24+
//
25+
// Warning: Pinning goroutines can lead to load imbalance. The goroutine will
26+
// wait in the specified core's queue even if other cores are idle. If a
27+
// long-running goroutine occupies the target core, LockCore may appear to
28+
// block indefinitely (until the next scheduling point on the target core).
29+
//
30+
// Valid core values are 0 and 1. Panics if core is out of range.
31+
//
32+
// Only available on RP2040 and RP2350 with the "cores" scheduler.
833
func LockCore(core int) {
934
if core < 0 || core >= numCPU {
1035
panic("machine: core out of range")
1136
}
1237
machineLockCore(core)
1338
}
1439

15-
// UnlockCore implementation for the cores scheduler.
40+
// UnlockCore unpins the calling goroutine, allowing it to run on any available core.
41+
// This undoes a previous call to LockCore.
42+
//
43+
// After calling UnlockCore, the scheduler is free to schedule the goroutine on
44+
// any core for automatic load balancing.
45+
//
46+
// Only available on RP2040 and RP2350 with the "cores" scheduler.
1647
func UnlockCore() {
1748
machineUnlockCore()
1849
}

src/runtime/runtime.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ func os_sigpipe() {
100100
// LockOSThread wires the calling goroutine to its current operating system thread.
101101
// On microcontrollers with multiple cores (e.g., RP2040/RP2350), this pins the
102102
// goroutine to the core it's currently running on.
103+
// With the "cores" scheduler on RP2040/RP2350, this pins the goroutine to the
104+
// core it's currently running on. The pinning takes effect at the next
105+
// scheduling point (e.g., channel operation, time.Sleep, or Gosched).
103106
// Called by go1.18 standard library on windows, see https://github.com/golang/go/issues/49320
104107
func LockOSThread() {
105108
lockOSThreadImpl()
@@ -108,6 +111,8 @@ func LockOSThread() {
108111
// UnlockOSThread undoes an earlier call to LockOSThread.
109112
// On microcontrollers with multiple cores, this unpins the goroutine, allowing
110113
// it to run on any available core.
114+
// With the "cores" scheduler, this unpins the goroutine, allowing it to run on
115+
// any available core.
111116
func UnlockOSThread() {
112117
unlockOSThreadImpl()
113118
}

0 commit comments

Comments
 (0)