Skip to content

Commit 0ab64e2

Browse files
prattmiccagedmantis
authored andcommitted
[release-branch.go1.24] runtime: cleanup M vgetrandom state before dropping P
When an M is destroyed, we put its vgetrandom state back on the shared list for another M to reuse. This list is simply a slice, so appending to the slice may allocate. Currently this operation is performed in mdestroy, after the P is released, meaning allocation is not allowed. More the cleanup earlier in mdestroy when allocation is still OK. Also add //go:nowritebarrierrec to mdestroy since it runs without a P, which would have caught this bug. Fixes #73144. For #73141. Change-Id: I6a6a636c3fbf5c6eec09d07a260e39dbb4d2db12 Reviewed-on: https://go-review.googlesource.com/c/go/+/662455 Reviewed-by: Jason Donenfeld <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Keith Randall <[email protected]> Reviewed-by: Keith Randall <[email protected]> (cherry picked from commit 0b31e6d) Reviewed-on: https://go-review.googlesource.com/c/go/+/662496
1 parent 56eb998 commit 0ab64e2

12 files changed

+48
-16
lines changed

src/runtime/os3_solaris.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,11 @@ func unminit() {
234234
getg().m.procid = 0
235235
}
236236

237-
// Called from exitm, but not from drop, to undo the effect of thread-owned
237+
// Called from mexit, but not from dropm, to undo the effect of thread-owned
238238
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
239+
//
240+
// This always runs without a P, so //go:nowritebarrierrec is required.
241+
//go:nowritebarrierrec
239242
func mdestroy(mp *m) {
240243
}
241244

src/runtime/os_aix.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,11 @@ func unminit() {
186186
getg().m.procid = 0
187187
}
188188

189-
// Called from exitm, but not from drop, to undo the effect of thread-owned
189+
// Called from mexit, but not from dropm, to undo the effect of thread-owned
190190
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
191+
//
192+
// This always runs without a P, so //go:nowritebarrierrec is required.
193+
//go:nowritebarrierrec
191194
func mdestroy(mp *m) {
192195
}
193196

src/runtime/os_darwin.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,11 @@ func unminit() {
344344
getg().m.procid = 0
345345
}
346346

347-
// Called from exitm, but not from drop, to undo the effect of thread-owned
347+
// Called from mexit, but not from dropm, to undo the effect of thread-owned
348348
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
349+
//
350+
// This always runs without a P, so //go:nowritebarrierrec is required.
351+
//go:nowritebarrierrec
349352
func mdestroy(mp *m) {
350353
}
351354

src/runtime/os_dragonfly.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,11 @@ func unminit() {
216216
getg().m.procid = 0
217217
}
218218

219-
// Called from exitm, but not from drop, to undo the effect of thread-owned
219+
// Called from mexit, but not from dropm, to undo the effect of thread-owned
220220
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
221+
//
222+
// This always runs without a P, so //go:nowritebarrierrec is required.
223+
//go:nowritebarrierrec
221224
func mdestroy(mp *m) {
222225
}
223226

src/runtime/os_linux.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -412,13 +412,12 @@ func unminit() {
412412
getg().m.procid = 0
413413
}
414414

415-
// Called from exitm, but not from drop, to undo the effect of thread-owned
415+
// Called from mexit, but not from dropm, to undo the effect of thread-owned
416416
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
417+
//
418+
// This always runs without a P, so //go:nowritebarrierrec is required.
419+
//go:nowritebarrierrec
417420
func mdestroy(mp *m) {
418-
if mp.vgetrandomState != 0 {
419-
vgetrandomPutState(mp.vgetrandomState)
420-
mp.vgetrandomState = 0
421-
}
422421
}
423422

424423
// #ifdef GOARCH_386

src/runtime/os_netbsd.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,11 @@ func unminit() {
320320
// must continue working after unminit.
321321
}
322322

323-
// Called from exitm, but not from drop, to undo the effect of thread-owned
323+
// Called from mexit, but not from dropm, to undo the effect of thread-owned
324324
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
325+
//
326+
// This always runs without a P, so //go:nowritebarrierrec is required.
327+
//go:nowritebarrierrec
325328
func mdestroy(mp *m) {
326329
}
327330

src/runtime/os_openbsd.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,11 @@ func unminit() {
182182
getg().m.procid = 0
183183
}
184184

185-
// Called from exitm, but not from drop, to undo the effect of thread-owned
185+
// Called from mexit, but not from dropm, to undo the effect of thread-owned
186186
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
187+
//
188+
// This always runs without a P, so //go:nowritebarrierrec is required.
189+
//go:nowritebarrierrec
187190
func mdestroy(mp *m) {
188191
}
189192

src/runtime/os_plan9.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,11 @@ func minit() {
217217
func unminit() {
218218
}
219219

220-
// Called from exitm, but not from drop, to undo the effect of thread-owned
220+
// Called from mexit, but not from dropm, to undo the effect of thread-owned
221221
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
222+
//
223+
// This always runs without a P, so //go:nowritebarrierrec is required.
224+
//go:nowritebarrierrec
222225
func mdestroy(mp *m) {
223226
}
224227

src/runtime/os_windows.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -906,9 +906,11 @@ func unminit() {
906906
mp.procid = 0
907907
}
908908

909-
// Called from exitm, but not from drop, to undo the effect of thread-owned
909+
// Called from mexit, but not from dropm, to undo the effect of thread-owned
910910
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
911911
//
912+
// This always runs without a P, so //go:nowritebarrierrec is required.
913+
//go:nowritebarrierrec
912914
//go:nosplit
913915
func mdestroy(mp *m) {
914916
if mp.highResTimer != 0 {

src/runtime/proc.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,6 +1935,9 @@ func mexit(osStack bool) {
19351935
mp.gsignal = nil
19361936
}
19371937

1938+
// Free vgetrandom state.
1939+
vgetrandomDestroy(mp)
1940+
19381941
// Remove m from allm.
19391942
lock(&sched.lock)
19401943
for pprev := &allm; *pprev != nil; pprev = &(*pprev).alllink {

src/runtime/vgetrandom_linux.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,16 @@ func vgetrandomGetState() uintptr {
7373
return state
7474
}
7575

76-
func vgetrandomPutState(state uintptr) {
76+
// Free vgetrandom state from the M (if any) prior to destroying the M.
77+
//
78+
// This may allocate, so it must have a P.
79+
func vgetrandomDestroy(mp *m) {
80+
if mp.vgetrandomState == 0 {
81+
return
82+
}
83+
7784
lock(&vgetrandomAlloc.statesLock)
78-
vgetrandomAlloc.states = append(vgetrandomAlloc.states, state)
85+
vgetrandomAlloc.states = append(vgetrandomAlloc.states, mp.vgetrandomState)
7986
unlock(&vgetrandomAlloc.statesLock)
8087
}
8188

src/runtime/vgetrandom_unsupported.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ func vgetrandom(p []byte, flags uint32) (ret int, supported bool) {
1313
return -1, false
1414
}
1515

16-
func vgetrandomPutState(state uintptr) {}
16+
func vgetrandomDestroy(mp *m) {}
1717

1818
func vgetrandomInit() {}

0 commit comments

Comments
 (0)