mirror of https://github.com/golang/go.git
runtime: convert closechan/chanlen/chancap to Go
LGTM=bradfitz, rsc R=golang-codereviews, bradfitz, rsc CC=golang-codereviews https://golang.org/cl/135150043
This commit is contained in:
parent
b930b433b0
commit
6a76bca33f
|
|
@ -150,12 +150,7 @@ func chansend(t *chantype, c *hchan, ep unsafe.Pointer, block bool, callerpc uin
|
|||
memmove(unsafe.Pointer(sg.elem), ep, uintptr(c.elemsize))
|
||||
}
|
||||
if sg.releasetime != 0 {
|
||||
// Yes, this is ugly. On 64-bit sg.releasetime has type
|
||||
// int. On 32-bit it has type int64. There's no easy way
|
||||
// to assign to both types in Go. At some point we'll
|
||||
// write the Go types directly instead of generating them
|
||||
// via the C types. At that point, this nastiness goes away.
|
||||
*(*int64)(unsafe.Pointer(&sg.releasetime)) = cputicks()
|
||||
sg.releasetime = cputicks()
|
||||
}
|
||||
goready(recvg)
|
||||
return true
|
||||
|
|
@ -248,7 +243,7 @@ func chansend(t *chantype, c *hchan, ep unsafe.Pointer, block bool, callerpc uin
|
|||
recvg := sg.g
|
||||
unlock(&c.lock)
|
||||
if sg.releasetime != 0 {
|
||||
*(*int64)(unsafe.Pointer(&sg.releasetime)) = cputicks()
|
||||
sg.releasetime = cputicks()
|
||||
}
|
||||
goready(recvg)
|
||||
} else {
|
||||
|
|
@ -260,6 +255,72 @@ func chansend(t *chantype, c *hchan, ep unsafe.Pointer, block bool, callerpc uin
|
|||
return true
|
||||
}
|
||||
|
||||
func closechan(c *hchan) {
|
||||
if c == nil {
|
||||
panic("close of nil channel")
|
||||
}
|
||||
|
||||
lock(&c.lock)
|
||||
if c.closed != 0 {
|
||||
unlock(&c.lock)
|
||||
panic("close of closed channel")
|
||||
}
|
||||
|
||||
if raceenabled {
|
||||
callerpc := getcallerpc(unsafe.Pointer(&c))
|
||||
fn := closechan
|
||||
pc := **(**uintptr)(unsafe.Pointer(&fn))
|
||||
racewritepc(unsafe.Pointer(c), callerpc, pc)
|
||||
racerelease(unsafe.Pointer(c))
|
||||
}
|
||||
|
||||
c.closed = 1
|
||||
|
||||
// release all readers
|
||||
for {
|
||||
sg := c.recvq.dequeue()
|
||||
if sg == nil {
|
||||
break
|
||||
}
|
||||
gp := sg.g
|
||||
gp.param = nil
|
||||
if sg.releasetime != 0 {
|
||||
sg.releasetime = cputicks()
|
||||
}
|
||||
goready(gp)
|
||||
}
|
||||
|
||||
// release all writers
|
||||
for {
|
||||
sg := c.sendq.dequeue()
|
||||
if sg == nil {
|
||||
break
|
||||
}
|
||||
gp := sg.g
|
||||
gp.param = nil
|
||||
if sg.releasetime != 0 {
|
||||
sg.releasetime = cputicks()
|
||||
}
|
||||
goready(gp)
|
||||
}
|
||||
|
||||
unlock(&c.lock)
|
||||
}
|
||||
|
||||
func reflect_chanlen(c *hchan) int {
|
||||
if c == nil {
|
||||
return 0
|
||||
}
|
||||
return int(c.qcount)
|
||||
}
|
||||
|
||||
func reflect_chancap(c *hchan) int {
|
||||
if c == nil {
|
||||
return 0
|
||||
}
|
||||
return int(c.dataqsiz)
|
||||
}
|
||||
|
||||
func (q *waitq) enqueue(sgp *sudog) {
|
||||
sgp.next = nil
|
||||
if q.first == nil {
|
||||
|
|
|
|||
|
|
@ -1005,81 +1005,6 @@ func reflect·rselect(cases Slice) (chosen int, recvOK bool) {
|
|||
chosen = (intgo)(uintptr)selectgo(&sel);
|
||||
}
|
||||
|
||||
static void closechan(Hchan *c, void *pc);
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
func closechan(c *Hchan) {
|
||||
closechan(c, runtime·getcallerpc(&c));
|
||||
}
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
func reflect·chanclose(c *Hchan) {
|
||||
closechan(c, runtime·getcallerpc(&c));
|
||||
}
|
||||
|
||||
static void
|
||||
closechan(Hchan *c, void *pc)
|
||||
{
|
||||
SudoG *sg;
|
||||
G* gp;
|
||||
|
||||
if(c == nil)
|
||||
runtime·panicstring("close of nil channel");
|
||||
|
||||
runtime·lock(&c->lock);
|
||||
if(c->closed) {
|
||||
runtime·unlock(&c->lock);
|
||||
runtime·panicstring("close of closed channel");
|
||||
}
|
||||
|
||||
if(raceenabled) {
|
||||
runtime·racewritepc(c, pc, runtime·closechan);
|
||||
runtime·racerelease(c);
|
||||
}
|
||||
|
||||
c->closed = true;
|
||||
|
||||
// release all readers
|
||||
for(;;) {
|
||||
sg = dequeue(&c->recvq);
|
||||
if(sg == nil)
|
||||
break;
|
||||
gp = sg->g;
|
||||
gp->param = nil;
|
||||
if(sg->releasetime)
|
||||
sg->releasetime = runtime·cputicks();
|
||||
runtime·ready(gp);
|
||||
}
|
||||
|
||||
// release all writers
|
||||
for(;;) {
|
||||
sg = dequeue(&c->sendq);
|
||||
if(sg == nil)
|
||||
break;
|
||||
gp = sg->g;
|
||||
gp->param = nil;
|
||||
if(sg->releasetime)
|
||||
sg->releasetime = runtime·cputicks();
|
||||
runtime·ready(gp);
|
||||
}
|
||||
|
||||
runtime·unlock(&c->lock);
|
||||
}
|
||||
|
||||
func reflect·chanlen(c *Hchan) (len int) {
|
||||
if(c == nil)
|
||||
len = 0;
|
||||
else
|
||||
len = c->qcount;
|
||||
}
|
||||
|
||||
func reflect·chancap(c *Hchan) (cap int) {
|
||||
if(c == nil)
|
||||
cap = 0;
|
||||
else
|
||||
cap = c->dataqsiz;
|
||||
}
|
||||
|
||||
static SudoG*
|
||||
dequeue(WaitQ *q)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -52,3 +52,12 @@ TEXT bytes·Compare(SB),NOSPLIT,$0-0
|
|||
|
||||
TEXT runtime·reflectcall(SB), NOSPLIT, $0-0
|
||||
JMP reflect·call(SB)
|
||||
|
||||
TEXT reflect·chanclose(SB), NOSPLIT, $0-0
|
||||
JMP runtime·closechan(SB)
|
||||
|
||||
TEXT reflect·chanlen(SB), NOSPLIT, $0-0
|
||||
JMP runtime·reflect_chanlen(SB)
|
||||
|
||||
TEXT reflect·chancap(SB), NOSPLIT, $0-0
|
||||
JMP runtime·reflect_chancap(SB)
|
||||
|
|
|
|||
Loading…
Reference in New Issue