sudog represents goroutine in the waiting queue, such as channel sending acceptance. Since the relationship between goroutine and synchronous object is many-to-many, sudog mapping is required
type sudog struct { // Point to goroutine g *g // Pointer to the front and back sudog next *sudog prev *sudog // Point to data elem // data element (may point to stack) // The following fields are never accessed concurrently. // For channels, waitlink is only accessed by g. // For semaphores, all fields (including the ones above) // are only accessed when holding a semaRoot lock. // Get time acquiretime int64 // Release time releasetime int64 // Identification as a queue element ticket uint32 // isSelect indicates g is participating in a select, so // must be CAS'd to win the wake-up race. isSelect bool // success indicates whether communication over channel c // succeeded. It is true if the goroutine was awoken because a // value was delivered over channel c, and false if awoken // because c was closed. success bool parent *sudog // semaRoot binary tree waitlink *sudog // list or semaRoot waittail *sudog // semaRoot c *hchan // channel }
acquireSudog()
func acquireSudog() *sudog { // Add m lock to prevent garbage collection from being called during this period mp := acquirem() pp := () // If the local cache is empty if len() == 0 { lock(&) // Migrate cache items from the central cache to up to half the local cache capacity to the local cache for len() < cap()/2 && != nil { s := = = nil = append(, s) } unlock(&) // If the local cache is still empty, create a new cache entry if len() == 0 { = append(, new(sudog)) } } //Return the last cache item from the local cache n := len() s := [n-1] [n-1] = nil = [:n-1] if != nil { throw("acquireSudog: found != nil in cache") } // Reduce m locks and allow garbage collection calls releasem(mp) return s }
releaseSudog()
func releaseSudog(s *sudog) { // Determine whether the data and status of sudog are correct if != nil { throw("runtime: sudog with non-nil elem") } if { throw("runtime: sudog with non-false isSelect") } if != nil { throw("runtime: sudog with non-nil next") } if != nil { throw("runtime: sudog with non-nil prev") } if != nil { throw("runtime: sudog with non-nil waitlink") } if != nil { throw("runtime: sudog with non-nil c") } gp := getg() if != nil { throw("runtime: releaseSudog with non-nil ") } mp := acquirem() // avoid rescheduling to another P pp := () // If the local cache is full, migrate to more than half of the capacity cache items to the central cache if len() == cap() { // Transfer half of local cache to the central cache. var first, last *sudog for len() > cap()/2 { n := len() p := [n-1] [n-1] = nil = [:n-1] if first == nil { first = p } else { = p } last = p } lock(&) // Hang the migrated local cache linked list directly into the central cache = = first unlock(&) } // Add the released sudog to the local cache = append(, s) releasem(mp) }
What is golang sudog here? That’s all for the article. For more related golang sudog content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!