2025-08-21 16:41:50 +02:00
|
|
|
//go:build go1.22 && !go1.26
|
2025-04-07 11:04:45 +01:00
|
|
|
|
|
|
|
|
package mutexes
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"sync"
|
|
|
|
|
"sync/atomic"
|
|
|
|
|
"unsafe"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// syncCond_last_ticket is an unsafe function that returns
|
|
|
|
|
// the ticket of the last awoken / notified goroutine by a
|
|
|
|
|
// a sync.Cond{}. it relies on expected memory layout.
|
|
|
|
|
func syncCond_last_ticket(c *sync.Cond) uint32 {
|
|
|
|
|
|
|
|
|
|
// NOTE: must remain in
|
|
|
|
|
// sync with runtime.notifyList{}.
|
|
|
|
|
//
|
|
|
|
|
// goexperiment.staticlockranking
|
|
|
|
|
// does change it slightly, but
|
|
|
|
|
// this does not alter the first
|
|
|
|
|
// 2 fields which are all we need.
|
|
|
|
|
type notifyList struct {
|
2025-08-21 16:41:50 +02:00
|
|
|
_ uint32
|
2025-04-07 11:04:45 +01:00
|
|
|
notify uint32
|
|
|
|
|
// ... other fields
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NOTE: must remain in
|
|
|
|
|
// sync with sync.Cond{}.
|
|
|
|
|
type syncCond struct {
|
|
|
|
|
_ struct{}
|
|
|
|
|
L sync.Locker
|
|
|
|
|
n notifyList
|
|
|
|
|
// ... other fields
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This field must be atomcially accessed.
|
|
|
|
|
cptr := (*syncCond)(unsafe.Pointer(c))
|
|
|
|
|
return atomic.LoadUint32(&cptr.n.notify)
|
|
|
|
|
}
|