mirror of
https://github.com/golang/go.git
synced 2025-05-29 11:25:43 +00:00
runtime: cleanup chan code
Move type definitions from chan1.go to chan.go and select.go. Remove underscores from names. Make c.buf unsafe.Pointer instead of *uint8. Change-Id: I75cf8385bdb9f79eb5a7f7ad319495abbacbe942 Reviewed-on: https://go-review.googlesource.com/4900 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Dmitry Vyukov <dvyukov@google.com>
This commit is contained in:
parent
04a3a74456
commit
fcc164d783
@ -14,7 +14,24 @@ const (
|
|||||||
debugChan = false
|
debugChan = false
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO(khr): make hchan.buf an unsafe.Pointer, not a *uint8
|
type hchan struct {
|
||||||
|
qcount uint // total data in the queue
|
||||||
|
dataqsiz uint // size of the circular queue
|
||||||
|
buf unsafe.Pointer // points to an array of dataqsiz elements
|
||||||
|
elemsize uint16
|
||||||
|
closed uint32
|
||||||
|
elemtype *_type // element type
|
||||||
|
sendx uint // send index
|
||||||
|
recvx uint // receive index
|
||||||
|
recvq waitq // list of recv waiters
|
||||||
|
sendq waitq // list of send waiters
|
||||||
|
lock mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
type waitq struct {
|
||||||
|
first *sudog
|
||||||
|
last *sudog
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname reflect_makechan reflect.makechan
|
//go:linkname reflect_makechan reflect.makechan
|
||||||
func reflect_makechan(t *chantype, size int64) *hchan {
|
func reflect_makechan(t *chantype, size int64) *hchan {
|
||||||
@ -44,15 +61,15 @@ func makechan(t *chantype, size int64) *hchan {
|
|||||||
// TODO(dvyukov,rlh): Rethink when collector can move allocated objects.
|
// TODO(dvyukov,rlh): Rethink when collector can move allocated objects.
|
||||||
c = (*hchan)(mallocgc(hchanSize+uintptr(size)*uintptr(elem.size), nil, flagNoScan))
|
c = (*hchan)(mallocgc(hchanSize+uintptr(size)*uintptr(elem.size), nil, flagNoScan))
|
||||||
if size > 0 && elem.size != 0 {
|
if size > 0 && elem.size != 0 {
|
||||||
c.buf = (*uint8)(add(unsafe.Pointer(c), hchanSize))
|
c.buf = add(unsafe.Pointer(c), hchanSize)
|
||||||
} else {
|
} else {
|
||||||
// race detector uses this location for synchronization
|
// race detector uses this location for synchronization
|
||||||
// Also prevents us from pointing beyond the allocation (see issue 9401).
|
// Also prevents us from pointing beyond the allocation (see issue 9401).
|
||||||
c.buf = (*uint8)(unsafe.Pointer(c))
|
c.buf = unsafe.Pointer(c)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c = new(hchan)
|
c = new(hchan)
|
||||||
c.buf = (*uint8)(newarray(elem, uintptr(size)))
|
c.buf = newarray(elem, uintptr(size))
|
||||||
}
|
}
|
||||||
c.elemsize = uint16(elem.size)
|
c.elemsize = uint16(elem.size)
|
||||||
c.elemtype = elem
|
c.elemtype = elem
|
||||||
@ -66,7 +83,7 @@ func makechan(t *chantype, size int64) *hchan {
|
|||||||
|
|
||||||
// chanbuf(c, i) is pointer to the i'th slot in the buffer.
|
// chanbuf(c, i) is pointer to the i'th slot in the buffer.
|
||||||
func chanbuf(c *hchan, i uint) unsafe.Pointer {
|
func chanbuf(c *hchan, i uint) unsafe.Pointer {
|
||||||
return add(unsafe.Pointer(c.buf), uintptr(i)*uintptr(c.elemsize))
|
return add(c.buf, uintptr(i)*uintptr(c.elemsize))
|
||||||
}
|
}
|
||||||
|
|
||||||
// entry point for c <- x from compiled code
|
// entry point for c <- x from compiled code
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package runtime
|
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
//#define MAXALIGN 8
|
|
||||||
|
|
||||||
type waitq struct {
|
|
||||||
first *sudog
|
|
||||||
last *sudog
|
|
||||||
}
|
|
||||||
|
|
||||||
type hchan struct {
|
|
||||||
qcount uint // total data in the q
|
|
||||||
dataqsiz uint // size of the circular q
|
|
||||||
buf *byte
|
|
||||||
elemsize uint16
|
|
||||||
closed uint32
|
|
||||||
elemtype *_type // element type
|
|
||||||
sendx uint // send index
|
|
||||||
recvx uint // receive index
|
|
||||||
recvq waitq // list of recv waiters
|
|
||||||
sendq waitq // list of send waiters
|
|
||||||
lock mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// Buffer follows Hchan immediately in memory.
|
|
||||||
// chanbuf(c, i) is pointer to the i'th slot in the buffer.
|
|
||||||
// #define chanbuf(c, i) ((byte*)((c)->buf)+(uintptr)(c)->elemsize*(i))
|
|
||||||
|
|
||||||
const (
|
|
||||||
// scase.kind
|
|
||||||
_CaseRecv = iota
|
|
||||||
_CaseSend
|
|
||||||
_CaseDefault
|
|
||||||
)
|
|
||||||
|
|
||||||
// Known to compiler.
|
|
||||||
// Changes here must also be made in src/cmd/gc/select.c's selecttype.
|
|
||||||
type scase struct {
|
|
||||||
elem unsafe.Pointer // data element
|
|
||||||
_chan *hchan // chan
|
|
||||||
pc uintptr // return pc
|
|
||||||
kind uint16
|
|
||||||
so uint16 // vararg of selected bool
|
|
||||||
receivedp *bool // pointer to received bool (recv2)
|
|
||||||
releasetime int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// Known to compiler.
|
|
||||||
// Changes here must also be made in src/cmd/gc/select.c's selecttype.
|
|
||||||
type _select struct {
|
|
||||||
tcase uint16 // total count of scase[]
|
|
||||||
ncase uint16 // currently filled scase[]
|
|
||||||
pollorder *uint16 // case poll order
|
|
||||||
lockorder **hchan // channel lock order
|
|
||||||
scase [1]scase // one per case (in order of appearance)
|
|
||||||
}
|
|
@ -10,30 +10,59 @@ import "unsafe"
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
debugSelect = false
|
debugSelect = false
|
||||||
|
|
||||||
|
// scase.kind
|
||||||
|
caseRecv = iota
|
||||||
|
caseSend
|
||||||
|
caseDefault
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Select statement header.
|
||||||
|
// Known to compiler.
|
||||||
|
// Changes here must also be made in src/cmd/internal/gc/select.go's selecttype.
|
||||||
|
type hselect struct {
|
||||||
|
tcase uint16 // total count of scase[]
|
||||||
|
ncase uint16 // currently filled scase[]
|
||||||
|
pollorder *uint16 // case poll order
|
||||||
|
lockorder **hchan // channel lock order
|
||||||
|
scase [1]scase // one per case (in order of appearance)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select case descriptor.
|
||||||
|
// Known to compiler.
|
||||||
|
// Changes here must also be made in src/cmd/internal/gc/select.go's selecttype.
|
||||||
|
type scase struct {
|
||||||
|
elem unsafe.Pointer // data element
|
||||||
|
c *hchan // chan
|
||||||
|
pc uintptr // return pc
|
||||||
|
kind uint16
|
||||||
|
so uint16 // vararg of selected bool
|
||||||
|
receivedp *bool // pointer to received bool (recv2)
|
||||||
|
releasetime int64
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
chansendpc = funcPC(chansend)
|
chansendpc = funcPC(chansend)
|
||||||
chanrecvpc = funcPC(chanrecv)
|
chanrecvpc = funcPC(chanrecv)
|
||||||
)
|
)
|
||||||
|
|
||||||
func selectsize(size uintptr) uintptr {
|
func selectsize(size uintptr) uintptr {
|
||||||
selsize := unsafe.Sizeof(_select{}) +
|
selsize := unsafe.Sizeof(hselect{}) +
|
||||||
(size-1)*unsafe.Sizeof(_select{}.scase[0]) +
|
(size-1)*unsafe.Sizeof(hselect{}.scase[0]) +
|
||||||
size*unsafe.Sizeof(*_select{}.lockorder) +
|
size*unsafe.Sizeof(*hselect{}.lockorder) +
|
||||||
size*unsafe.Sizeof(*_select{}.pollorder)
|
size*unsafe.Sizeof(*hselect{}.pollorder)
|
||||||
return round(selsize, _Int64Align)
|
return round(selsize, _Int64Align)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newselect(sel *_select, selsize int64, size int32) {
|
func newselect(sel *hselect, selsize int64, size int32) {
|
||||||
if selsize != int64(selectsize(uintptr(size))) {
|
if selsize != int64(selectsize(uintptr(size))) {
|
||||||
print("runtime: bad select size ", selsize, ", want ", selectsize(uintptr(size)), "\n")
|
print("runtime: bad select size ", selsize, ", want ", selectsize(uintptr(size)), "\n")
|
||||||
throw("bad select size")
|
throw("bad select size")
|
||||||
}
|
}
|
||||||
sel.tcase = uint16(size)
|
sel.tcase = uint16(size)
|
||||||
sel.ncase = 0
|
sel.ncase = 0
|
||||||
sel.lockorder = (**hchan)(add(unsafe.Pointer(&sel.scase), uintptr(size)*unsafe.Sizeof(_select{}.scase[0])))
|
sel.lockorder = (**hchan)(add(unsafe.Pointer(&sel.scase), uintptr(size)*unsafe.Sizeof(hselect{}.scase[0])))
|
||||||
sel.pollorder = (*uint16)(add(unsafe.Pointer(sel.lockorder), uintptr(size)*unsafe.Sizeof(*_select{}.lockorder)))
|
sel.pollorder = (*uint16)(add(unsafe.Pointer(sel.lockorder), uintptr(size)*unsafe.Sizeof(*hselect{}.lockorder)))
|
||||||
|
|
||||||
if debugSelect {
|
if debugSelect {
|
||||||
print("newselect s=", sel, " size=", size, "\n")
|
print("newselect s=", sel, " size=", size, "\n")
|
||||||
@ -41,7 +70,7 @@ func newselect(sel *_select, selsize int64, size int32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func selectsend(sel *_select, c *hchan, elem unsafe.Pointer) (selected bool) {
|
func selectsend(sel *hselect, c *hchan, elem unsafe.Pointer) (selected bool) {
|
||||||
// nil cases do not compete
|
// nil cases do not compete
|
||||||
if c != nil {
|
if c != nil {
|
||||||
selectsendImpl(sel, c, getcallerpc(unsafe.Pointer(&sel)), elem, uintptr(unsafe.Pointer(&selected))-uintptr(unsafe.Pointer(&sel)))
|
selectsendImpl(sel, c, getcallerpc(unsafe.Pointer(&sel)), elem, uintptr(unsafe.Pointer(&selected))-uintptr(unsafe.Pointer(&sel)))
|
||||||
@ -50,7 +79,7 @@ func selectsend(sel *_select, c *hchan, elem unsafe.Pointer) (selected bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cut in half to give stack a chance to split
|
// cut in half to give stack a chance to split
|
||||||
func selectsendImpl(sel *_select, c *hchan, pc uintptr, elem unsafe.Pointer, so uintptr) {
|
func selectsendImpl(sel *hselect, c *hchan, pc uintptr, elem unsafe.Pointer, so uintptr) {
|
||||||
i := sel.ncase
|
i := sel.ncase
|
||||||
if i >= sel.tcase {
|
if i >= sel.tcase {
|
||||||
throw("selectsend: too many cases")
|
throw("selectsend: too many cases")
|
||||||
@ -59,18 +88,18 @@ func selectsendImpl(sel *_select, c *hchan, pc uintptr, elem unsafe.Pointer, so
|
|||||||
cas := (*scase)(add(unsafe.Pointer(&sel.scase), uintptr(i)*unsafe.Sizeof(sel.scase[0])))
|
cas := (*scase)(add(unsafe.Pointer(&sel.scase), uintptr(i)*unsafe.Sizeof(sel.scase[0])))
|
||||||
|
|
||||||
cas.pc = pc
|
cas.pc = pc
|
||||||
cas._chan = c
|
cas.c = c
|
||||||
cas.so = uint16(so)
|
cas.so = uint16(so)
|
||||||
cas.kind = _CaseSend
|
cas.kind = caseSend
|
||||||
cas.elem = elem
|
cas.elem = elem
|
||||||
|
|
||||||
if debugSelect {
|
if debugSelect {
|
||||||
print("selectsend s=", sel, " pc=", hex(cas.pc), " chan=", cas._chan, " so=", cas.so, "\n")
|
print("selectsend s=", sel, " pc=", hex(cas.pc), " chan=", cas.c, " so=", cas.so, "\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func selectrecv(sel *_select, c *hchan, elem unsafe.Pointer) (selected bool) {
|
func selectrecv(sel *hselect, c *hchan, elem unsafe.Pointer) (selected bool) {
|
||||||
// nil cases do not compete
|
// nil cases do not compete
|
||||||
if c != nil {
|
if c != nil {
|
||||||
selectrecvImpl(sel, c, getcallerpc(unsafe.Pointer(&sel)), elem, nil, uintptr(unsafe.Pointer(&selected))-uintptr(unsafe.Pointer(&sel)))
|
selectrecvImpl(sel, c, getcallerpc(unsafe.Pointer(&sel)), elem, nil, uintptr(unsafe.Pointer(&selected))-uintptr(unsafe.Pointer(&sel)))
|
||||||
@ -79,7 +108,7 @@ func selectrecv(sel *_select, c *hchan, elem unsafe.Pointer) (selected bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func selectrecv2(sel *_select, c *hchan, elem unsafe.Pointer, received *bool) (selected bool) {
|
func selectrecv2(sel *hselect, c *hchan, elem unsafe.Pointer, received *bool) (selected bool) {
|
||||||
// nil cases do not compete
|
// nil cases do not compete
|
||||||
if c != nil {
|
if c != nil {
|
||||||
selectrecvImpl(sel, c, getcallerpc(unsafe.Pointer(&sel)), elem, received, uintptr(unsafe.Pointer(&selected))-uintptr(unsafe.Pointer(&sel)))
|
selectrecvImpl(sel, c, getcallerpc(unsafe.Pointer(&sel)), elem, received, uintptr(unsafe.Pointer(&selected))-uintptr(unsafe.Pointer(&sel)))
|
||||||
@ -87,7 +116,7 @@ func selectrecv2(sel *_select, c *hchan, elem unsafe.Pointer, received *bool) (s
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func selectrecvImpl(sel *_select, c *hchan, pc uintptr, elem unsafe.Pointer, received *bool, so uintptr) {
|
func selectrecvImpl(sel *hselect, c *hchan, pc uintptr, elem unsafe.Pointer, received *bool, so uintptr) {
|
||||||
i := sel.ncase
|
i := sel.ncase
|
||||||
if i >= sel.tcase {
|
if i >= sel.tcase {
|
||||||
throw("selectrecv: too many cases")
|
throw("selectrecv: too many cases")
|
||||||
@ -95,24 +124,24 @@ func selectrecvImpl(sel *_select, c *hchan, pc uintptr, elem unsafe.Pointer, rec
|
|||||||
sel.ncase = i + 1
|
sel.ncase = i + 1
|
||||||
cas := (*scase)(add(unsafe.Pointer(&sel.scase), uintptr(i)*unsafe.Sizeof(sel.scase[0])))
|
cas := (*scase)(add(unsafe.Pointer(&sel.scase), uintptr(i)*unsafe.Sizeof(sel.scase[0])))
|
||||||
cas.pc = pc
|
cas.pc = pc
|
||||||
cas._chan = c
|
cas.c = c
|
||||||
cas.so = uint16(so)
|
cas.so = uint16(so)
|
||||||
cas.kind = _CaseRecv
|
cas.kind = caseRecv
|
||||||
cas.elem = elem
|
cas.elem = elem
|
||||||
cas.receivedp = received
|
cas.receivedp = received
|
||||||
|
|
||||||
if debugSelect {
|
if debugSelect {
|
||||||
print("selectrecv s=", sel, " pc=", hex(cas.pc), " chan=", cas._chan, " so=", cas.so, "\n")
|
print("selectrecv s=", sel, " pc=", hex(cas.pc), " chan=", cas.c, " so=", cas.so, "\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func selectdefault(sel *_select) (selected bool) {
|
func selectdefault(sel *hselect) (selected bool) {
|
||||||
selectdefaultImpl(sel, getcallerpc(unsafe.Pointer(&sel)), uintptr(unsafe.Pointer(&selected))-uintptr(unsafe.Pointer(&sel)))
|
selectdefaultImpl(sel, getcallerpc(unsafe.Pointer(&sel)), uintptr(unsafe.Pointer(&selected))-uintptr(unsafe.Pointer(&sel)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func selectdefaultImpl(sel *_select, callerpc uintptr, so uintptr) {
|
func selectdefaultImpl(sel *hselect, callerpc uintptr, so uintptr) {
|
||||||
i := sel.ncase
|
i := sel.ncase
|
||||||
if i >= sel.tcase {
|
if i >= sel.tcase {
|
||||||
throw("selectdefault: too many cases")
|
throw("selectdefault: too many cases")
|
||||||
@ -120,16 +149,16 @@ func selectdefaultImpl(sel *_select, callerpc uintptr, so uintptr) {
|
|||||||
sel.ncase = i + 1
|
sel.ncase = i + 1
|
||||||
cas := (*scase)(add(unsafe.Pointer(&sel.scase), uintptr(i)*unsafe.Sizeof(sel.scase[0])))
|
cas := (*scase)(add(unsafe.Pointer(&sel.scase), uintptr(i)*unsafe.Sizeof(sel.scase[0])))
|
||||||
cas.pc = callerpc
|
cas.pc = callerpc
|
||||||
cas._chan = nil
|
cas.c = nil
|
||||||
cas.so = uint16(so)
|
cas.so = uint16(so)
|
||||||
cas.kind = _CaseDefault
|
cas.kind = caseDefault
|
||||||
|
|
||||||
if debugSelect {
|
if debugSelect {
|
||||||
print("selectdefault s=", sel, " pc=", hex(cas.pc), " so=", cas.so, "\n")
|
print("selectdefault s=", sel, " pc=", hex(cas.pc), " so=", cas.so, "\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sellock(sel *_select) {
|
func sellock(sel *hselect) {
|
||||||
lockslice := sliceStruct{unsafe.Pointer(sel.lockorder), int(sel.ncase), int(sel.ncase)}
|
lockslice := sliceStruct{unsafe.Pointer(sel.lockorder), int(sel.ncase), int(sel.ncase)}
|
||||||
lockorder := *(*[]*hchan)(unsafe.Pointer(&lockslice))
|
lockorder := *(*[]*hchan)(unsafe.Pointer(&lockslice))
|
||||||
var c *hchan
|
var c *hchan
|
||||||
@ -141,7 +170,7 @@ func sellock(sel *_select) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func selunlock(sel *_select) {
|
func selunlock(sel *hselect) {
|
||||||
// We must be very careful here to not touch sel after we have unlocked
|
// We must be very careful here to not touch sel after we have unlocked
|
||||||
// the last lock, because sel can be freed right after the last unlock.
|
// the last lock, because sel can be freed right after the last unlock.
|
||||||
// Consider the following situation.
|
// Consider the following situation.
|
||||||
@ -168,7 +197,7 @@ func selunlock(sel *_select) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func selparkcommit(gp *g, sel unsafe.Pointer) bool {
|
func selparkcommit(gp *g, sel unsafe.Pointer) bool {
|
||||||
selunlock((*_select)(sel))
|
selunlock((*hselect)(sel))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,7 +208,7 @@ func block() {
|
|||||||
// overwrites return pc on stack to signal which case of the select
|
// overwrites return pc on stack to signal which case of the select
|
||||||
// to run, so cannot appear at the top of a split stack.
|
// to run, so cannot appear at the top of a split stack.
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func selectgo(sel *_select) {
|
func selectgo(sel *hselect) {
|
||||||
pc, offset := selectgoImpl(sel)
|
pc, offset := selectgoImpl(sel)
|
||||||
*(*bool)(add(unsafe.Pointer(&sel), uintptr(offset))) = true
|
*(*bool)(add(unsafe.Pointer(&sel), uintptr(offset))) = true
|
||||||
setcallerpc(unsafe.Pointer(&sel), pc)
|
setcallerpc(unsafe.Pointer(&sel), pc)
|
||||||
@ -187,7 +216,7 @@ func selectgo(sel *_select) {
|
|||||||
|
|
||||||
// selectgoImpl returns scase.pc and scase.so for the select
|
// selectgoImpl returns scase.pc and scase.so for the select
|
||||||
// case which fired.
|
// case which fired.
|
||||||
func selectgoImpl(sel *_select) (uintptr, uint16) {
|
func selectgoImpl(sel *hselect) (uintptr, uint16) {
|
||||||
if debugSelect {
|
if debugSelect {
|
||||||
print("select: sel=", sel, "\n")
|
print("select: sel=", sel, "\n")
|
||||||
}
|
}
|
||||||
@ -230,7 +259,7 @@ func selectgoImpl(sel *_select) (uintptr, uint16) {
|
|||||||
lockorder := *(*[]*hchan)(unsafe.Pointer(&lockslice))
|
lockorder := *(*[]*hchan)(unsafe.Pointer(&lockslice))
|
||||||
for i := 0; i < int(sel.ncase); i++ {
|
for i := 0; i < int(sel.ncase); i++ {
|
||||||
j := i
|
j := i
|
||||||
c := scases[j]._chan
|
c := scases[j].c
|
||||||
for j > 0 && lockorder[(j-1)/2].sortkey() < c.sortkey() {
|
for j > 0 && lockorder[(j-1)/2].sortkey() < c.sortkey() {
|
||||||
k := (j - 1) / 2
|
k := (j - 1) / 2
|
||||||
lockorder[j] = lockorder[k]
|
lockorder[j] = lockorder[k]
|
||||||
@ -287,10 +316,10 @@ loop:
|
|||||||
var cas *scase
|
var cas *scase
|
||||||
for i := 0; i < int(sel.ncase); i++ {
|
for i := 0; i < int(sel.ncase); i++ {
|
||||||
cas = &scases[pollorder[i]]
|
cas = &scases[pollorder[i]]
|
||||||
c = cas._chan
|
c = cas.c
|
||||||
|
|
||||||
switch cas.kind {
|
switch cas.kind {
|
||||||
case _CaseRecv:
|
case caseRecv:
|
||||||
if c.dataqsiz > 0 {
|
if c.dataqsiz > 0 {
|
||||||
if c.qcount > 0 {
|
if c.qcount > 0 {
|
||||||
goto asyncrecv
|
goto asyncrecv
|
||||||
@ -305,7 +334,7 @@ loop:
|
|||||||
goto rclose
|
goto rclose
|
||||||
}
|
}
|
||||||
|
|
||||||
case _CaseSend:
|
case caseSend:
|
||||||
if raceenabled {
|
if raceenabled {
|
||||||
racereadpc(unsafe.Pointer(c), cas.pc, chansendpc)
|
racereadpc(unsafe.Pointer(c), cas.pc, chansendpc)
|
||||||
}
|
}
|
||||||
@ -323,7 +352,7 @@ loop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case _CaseDefault:
|
case caseDefault:
|
||||||
dfl = cas
|
dfl = cas
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -339,7 +368,7 @@ loop:
|
|||||||
done = 0
|
done = 0
|
||||||
for i := 0; i < int(sel.ncase); i++ {
|
for i := 0; i < int(sel.ncase); i++ {
|
||||||
cas = &scases[pollorder[i]]
|
cas = &scases[pollorder[i]]
|
||||||
c = cas._chan
|
c = cas.c
|
||||||
sg := acquireSudog()
|
sg := acquireSudog()
|
||||||
sg.g = gp
|
sg.g = gp
|
||||||
// Note: selectdone is adjusted for stack copies in stack.c:adjustsudogs
|
// Note: selectdone is adjusted for stack copies in stack.c:adjustsudogs
|
||||||
@ -353,10 +382,10 @@ loop:
|
|||||||
gp.waiting = sg
|
gp.waiting = sg
|
||||||
|
|
||||||
switch cas.kind {
|
switch cas.kind {
|
||||||
case _CaseRecv:
|
case caseRecv:
|
||||||
c.recvq.enqueue(sg)
|
c.recvq.enqueue(sg)
|
||||||
|
|
||||||
case _CaseSend:
|
case caseSend:
|
||||||
c.sendq.enqueue(sg)
|
c.sendq.enqueue(sg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -392,8 +421,8 @@ loop:
|
|||||||
// sg has already been dequeued by the G that woke us up.
|
// sg has already been dequeued by the G that woke us up.
|
||||||
cas = k
|
cas = k
|
||||||
} else {
|
} else {
|
||||||
c = k._chan
|
c = k.c
|
||||||
if k.kind == _CaseSend {
|
if k.kind == caseSend {
|
||||||
c.sendq.dequeueSudoG(sglist)
|
c.sendq.dequeueSudoG(sglist)
|
||||||
} else {
|
} else {
|
||||||
c.recvq.dequeueSudoG(sglist)
|
c.recvq.dequeueSudoG(sglist)
|
||||||
@ -409,7 +438,7 @@ loop:
|
|||||||
goto loop
|
goto loop
|
||||||
}
|
}
|
||||||
|
|
||||||
c = cas._chan
|
c = cas.c
|
||||||
|
|
||||||
if c.dataqsiz > 0 {
|
if c.dataqsiz > 0 {
|
||||||
throw("selectgo: shouldn't happen")
|
throw("selectgo: shouldn't happen")
|
||||||
@ -419,16 +448,16 @@ loop:
|
|||||||
print("wait-return: sel=", sel, " c=", c, " cas=", cas, " kind=", cas.kind, "\n")
|
print("wait-return: sel=", sel, " c=", c, " cas=", cas, " kind=", cas.kind, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
if cas.kind == _CaseRecv {
|
if cas.kind == caseRecv {
|
||||||
if cas.receivedp != nil {
|
if cas.receivedp != nil {
|
||||||
*cas.receivedp = true
|
*cas.receivedp = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if raceenabled {
|
if raceenabled {
|
||||||
if cas.kind == _CaseRecv && cas.elem != nil {
|
if cas.kind == caseRecv && cas.elem != nil {
|
||||||
raceWriteObjectPC(c.elemtype, cas.elem, cas.pc, chanrecvpc)
|
raceWriteObjectPC(c.elemtype, cas.elem, cas.pc, chanrecvpc)
|
||||||
} else if cas.kind == _CaseSend {
|
} else if cas.kind == caseSend {
|
||||||
raceReadObjectPC(c.elemtype, cas.elem, cas.pc, chansendpc)
|
raceReadObjectPC(c.elemtype, cas.elem, cas.pc, chansendpc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -599,7 +628,7 @@ const (
|
|||||||
func reflect_rselect(cases []runtimeSelect) (chosen int, recvOK bool) {
|
func reflect_rselect(cases []runtimeSelect) (chosen int, recvOK bool) {
|
||||||
// flagNoScan is safe here, because all objects are also referenced from cases.
|
// flagNoScan is safe here, because all objects are also referenced from cases.
|
||||||
size := selectsize(uintptr(len(cases)))
|
size := selectsize(uintptr(len(cases)))
|
||||||
sel := (*_select)(mallocgc(size, nil, flagNoScan))
|
sel := (*hselect)(mallocgc(size, nil, flagNoScan))
|
||||||
newselect(sel, int64(size), int32(len(cases)))
|
newselect(sel, int64(size), int32(len(cases)))
|
||||||
r := new(bool)
|
r := new(bool)
|
||||||
for i := range cases {
|
for i := range cases {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user