mirror of
https://github.com/golang/go.git
synced 2025-05-05 23:53:05 +00:00
[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 <Jason@zx2c4.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com> (cherry picked from commit 0b31e6d4cc804ab76ae8ced151ee2f50657aec14) Reviewed-on: https://go-review.googlesource.com/c/go/+/662496
This commit is contained in:
parent
56eb99859d
commit
0ab64e2caa
@ -234,8 +234,11 @@ func unminit() {
|
|||||||
getg().m.procid = 0
|
getg().m.procid = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from exitm, but not from drop, to undo the effect of thread-owned
|
// Called from mexit, but not from dropm, to undo the effect of thread-owned
|
||||||
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
||||||
|
//
|
||||||
|
// This always runs without a P, so //go:nowritebarrierrec is required.
|
||||||
|
//go:nowritebarrierrec
|
||||||
func mdestroy(mp *m) {
|
func mdestroy(mp *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,8 +186,11 @@ func unminit() {
|
|||||||
getg().m.procid = 0
|
getg().m.procid = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from exitm, but not from drop, to undo the effect of thread-owned
|
// Called from mexit, but not from dropm, to undo the effect of thread-owned
|
||||||
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
||||||
|
//
|
||||||
|
// This always runs without a P, so //go:nowritebarrierrec is required.
|
||||||
|
//go:nowritebarrierrec
|
||||||
func mdestroy(mp *m) {
|
func mdestroy(mp *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,8 +344,11 @@ func unminit() {
|
|||||||
getg().m.procid = 0
|
getg().m.procid = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from exitm, but not from drop, to undo the effect of thread-owned
|
// Called from mexit, but not from dropm, to undo the effect of thread-owned
|
||||||
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
||||||
|
//
|
||||||
|
// This always runs without a P, so //go:nowritebarrierrec is required.
|
||||||
|
//go:nowritebarrierrec
|
||||||
func mdestroy(mp *m) {
|
func mdestroy(mp *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,8 +216,11 @@ func unminit() {
|
|||||||
getg().m.procid = 0
|
getg().m.procid = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from exitm, but not from drop, to undo the effect of thread-owned
|
// Called from mexit, but not from dropm, to undo the effect of thread-owned
|
||||||
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
||||||
|
//
|
||||||
|
// This always runs without a P, so //go:nowritebarrierrec is required.
|
||||||
|
//go:nowritebarrierrec
|
||||||
func mdestroy(mp *m) {
|
func mdestroy(mp *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,13 +412,12 @@ func unminit() {
|
|||||||
getg().m.procid = 0
|
getg().m.procid = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from exitm, but not from drop, to undo the effect of thread-owned
|
// Called from mexit, but not from dropm, to undo the effect of thread-owned
|
||||||
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
||||||
|
//
|
||||||
|
// This always runs without a P, so //go:nowritebarrierrec is required.
|
||||||
|
//go:nowritebarrierrec
|
||||||
func mdestroy(mp *m) {
|
func mdestroy(mp *m) {
|
||||||
if mp.vgetrandomState != 0 {
|
|
||||||
vgetrandomPutState(mp.vgetrandomState)
|
|
||||||
mp.vgetrandomState = 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// #ifdef GOARCH_386
|
// #ifdef GOARCH_386
|
||||||
|
@ -320,8 +320,11 @@ func unminit() {
|
|||||||
// must continue working after unminit.
|
// must continue working after unminit.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from exitm, but not from drop, to undo the effect of thread-owned
|
// Called from mexit, but not from dropm, to undo the effect of thread-owned
|
||||||
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
||||||
|
//
|
||||||
|
// This always runs without a P, so //go:nowritebarrierrec is required.
|
||||||
|
//go:nowritebarrierrec
|
||||||
func mdestroy(mp *m) {
|
func mdestroy(mp *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,8 +182,11 @@ func unminit() {
|
|||||||
getg().m.procid = 0
|
getg().m.procid = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from exitm, but not from drop, to undo the effect of thread-owned
|
// Called from mexit, but not from dropm, to undo the effect of thread-owned
|
||||||
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
||||||
|
//
|
||||||
|
// This always runs without a P, so //go:nowritebarrierrec is required.
|
||||||
|
//go:nowritebarrierrec
|
||||||
func mdestroy(mp *m) {
|
func mdestroy(mp *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,8 +217,11 @@ func minit() {
|
|||||||
func unminit() {
|
func unminit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from exitm, but not from drop, to undo the effect of thread-owned
|
// Called from mexit, but not from dropm, to undo the effect of thread-owned
|
||||||
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
||||||
|
//
|
||||||
|
// This always runs without a P, so //go:nowritebarrierrec is required.
|
||||||
|
//go:nowritebarrierrec
|
||||||
func mdestroy(mp *m) {
|
func mdestroy(mp *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -906,9 +906,11 @@ func unminit() {
|
|||||||
mp.procid = 0
|
mp.procid = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from exitm, but not from drop, to undo the effect of thread-owned
|
// Called from mexit, but not from dropm, to undo the effect of thread-owned
|
||||||
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
// resources in minit, semacreate, or elsewhere. Do not take locks after calling this.
|
||||||
//
|
//
|
||||||
|
// This always runs without a P, so //go:nowritebarrierrec is required.
|
||||||
|
//go:nowritebarrierrec
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func mdestroy(mp *m) {
|
func mdestroy(mp *m) {
|
||||||
if mp.highResTimer != 0 {
|
if mp.highResTimer != 0 {
|
||||||
|
@ -1935,6 +1935,9 @@ func mexit(osStack bool) {
|
|||||||
mp.gsignal = nil
|
mp.gsignal = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Free vgetrandom state.
|
||||||
|
vgetrandomDestroy(mp)
|
||||||
|
|
||||||
// Remove m from allm.
|
// Remove m from allm.
|
||||||
lock(&sched.lock)
|
lock(&sched.lock)
|
||||||
for pprev := &allm; *pprev != nil; pprev = &(*pprev).alllink {
|
for pprev := &allm; *pprev != nil; pprev = &(*pprev).alllink {
|
||||||
|
@ -73,9 +73,16 @@ func vgetrandomGetState() uintptr {
|
|||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
func vgetrandomPutState(state uintptr) {
|
// Free vgetrandom state from the M (if any) prior to destroying the M.
|
||||||
|
//
|
||||||
|
// This may allocate, so it must have a P.
|
||||||
|
func vgetrandomDestroy(mp *m) {
|
||||||
|
if mp.vgetrandomState == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
lock(&vgetrandomAlloc.statesLock)
|
lock(&vgetrandomAlloc.statesLock)
|
||||||
vgetrandomAlloc.states = append(vgetrandomAlloc.states, state)
|
vgetrandomAlloc.states = append(vgetrandomAlloc.states, mp.vgetrandomState)
|
||||||
unlock(&vgetrandomAlloc.statesLock)
|
unlock(&vgetrandomAlloc.statesLock)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,6 @@ func vgetrandom(p []byte, flags uint32) (ret int, supported bool) {
|
|||||||
return -1, false
|
return -1, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func vgetrandomPutState(state uintptr) {}
|
func vgetrandomDestroy(mp *m) {}
|
||||||
|
|
||||||
func vgetrandomInit() {}
|
func vgetrandomInit() {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user