if sg := c.recvq.dequeue(); sg != nil {
// Found a waiting receiver. We pass the value we want to send
// directly to the receiver, bypassing the channel buffer (if any).
- send(c, sg, ep, func() { unlock(&c.lock) })
+ send(c, sg, ep, func() { unlock(&c.lock) }, 3)
return true
}
// Channel c must be empty and locked. send unlocks c with unlockf.
// sg must already be dequeued from c.
// ep must be non-nil and point to the heap or the caller's stack.
-func send(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func()) {
+func send(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func(), skip int) {
if raceenabled {
if c.dataqsiz == 0 {
racesync(c, sg)
if sg.releasetime != 0 {
sg.releasetime = cputicks()
}
- goready(gp, 4)
+ goready(gp, skip+1)
}
// Sends and receives on unbuffered or empty-buffered channels are the
// directly from sender. Otherwise, receive from head of queue
// and add sender's value to the tail of the queue (both map to
// the same buffer slot because the queue is full).
- recv(c, sg, ep, func() { unlock(&c.lock) })
+ recv(c, sg, ep, func() { unlock(&c.lock) }, 3)
return true, true
}
// Channel c must be full and locked. recv unlocks c with unlockf.
// sg must already be dequeued from c.
// A non-nil ep must point to the heap or the caller's stack.
-func recv(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func()) {
+func recv(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func(), skip int) {
if c.dataqsiz == 0 {
if raceenabled {
racesync(c, sg)
if sg.releasetime != 0 {
sg.releasetime = cputicks()
}
- goready(gp, 4)
+ goready(gp, skip+1)
}
// compiler implements
//
// selectgo returns the index of the chosen scase, which matches the
// ordinal position of its respective select{recv,send,default} call.
-//go:nosplit
func selectgo(sel *hselect) int {
- return selectgoImpl(sel)
-}
-
-// Separate function to keep runtime/trace.TestTraceSymbolize happy.
-func selectgoImpl(sel *hselect) int {
if debugSelect {
print("select: sel=", sel, "\n")
}
// wait for someone to wake us up
gp.param = nil
- gopark(selparkcommit, nil, "select", traceEvGoBlockSelect, 2)
+ gopark(selparkcommit, nil, "select", traceEvGoBlockSelect, 1)
// While we were asleep, some goroutine came along and completed
// one of the cases in the select and woke us up (called ready).
recv:
// can receive from sleeping sender (sg)
- recv(c, sg, cas.elem, func() { selunlock(scases, lockorder) })
+ recv(c, sg, cas.elem, func() { selunlock(scases, lockorder) }, 2)
if debugSelect {
print("syncrecv: sel=", sel, " c=", c, "\n")
}
if msanenabled {
msanread(cas.elem, c.elemtype.size)
}
- send(c, sg, cas.elem, func() { selunlock(scases, lockorder) })
+ send(c, sg, cas.elem, func() { selunlock(scases, lockorder) }, 2)
if debugSelect {
print("syncsend: sel=", sel, " c=", c, "\n")
}
retc:
if cas.releasetime > 0 {
- blockevent(cas.releasetime-t0, 2)
+ blockevent(cas.releasetime-t0, 1)
}
return casi