1
0
mirror of https://github.com/golang/go synced 2024-10-04 16:31:22 -06:00
go/src/pkg/runtime/chan.goc

1160 lines
24 KiB
Plaintext
Raw Normal View History

2008-07-13 15:29:46 -06:00
// 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.
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
package runtime
2008-07-13 15:29:46 -06:00
#include "runtime.h"
#include "arch_GOARCH.h"
#include "type.h"
#include "race.h"
#include "malloc.h"
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
#include "chan.h"
#include "../../cmd/ld/textflag.h"
2008-07-13 15:29:46 -06:00
uint32 runtime·Hchansize = sizeof(Hchan);
static void dequeueg(WaitQ*);
static SudoG* dequeue(WaitQ*);
static void enqueue(WaitQ*, SudoG*);
static void destroychan(Hchan*);
static void racesync(Hchan*, SudoG*);
static Hchan*
makechan(ChanType *t, int64 hint)
2008-07-13 15:29:46 -06:00
{
Hchan *c;
Type *elem;
elem = t->elem;
2008-07-13 15:29:46 -06:00
// compiler checks this but be safe.
if(elem->size >= (1<<16))
runtime·throw("makechan: invalid channel element type");
if((sizeof(*c)%MAXALIGN) != 0 || elem->align > MAXALIGN)
runtime·throw("makechan: bad alignment");
if(hint < 0 || (intgo)hint != hint || (elem->size > 0 && hint > (MaxMem - sizeof(*c)) / elem->size))
runtime·panicstring("makechan: size out of range");
// allocate memory in one call
c = (Hchan*)runtime·mallocgc(sizeof(*c) + hint*elem->size, (uintptr)t | TypeInfo_Chan, 0);
c->elemsize = elem->size;
c->elemtype = elem;
c->dataqsiz = hint;
2008-07-13 15:29:46 -06:00
if(debug)
runtime·printf("makechan: chan=%p; elemsize=%D; elemalg=%p; dataqsiz=%D\n",
c, (int64)elem->size, elem->alg, (int64)c->dataqsiz);
return c;
}
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func reflect·makechan(t *ChanType, size uint64) (c *Hchan) {
c = makechan(t, size);
reflect: more efficient; cannot Set result of NewValue anymore * Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5. The current reflect uses Set to mean two subtly different things. (1) If you have a reflect.Value v, it might just represent itself (as in v = reflect.NewValue(42)), in which case calling v.Set only changed v, not any other data in the program. (2) If you have a reflect Value v derived from a pointer or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)), v represents the value held there. Changing x[0] affects the value returned by v.Int(), and calling v.Set affects x[0]. This was not really by design; it just happened that way. The motivation for the new reflect implementation was to remove mallocs. The use case (1) has an implicit malloc inside it. If you can do: v := reflect.NewValue(0) v.Set(42) i := v.Int() // i = 42 then that implies that v is referring to some underlying chunk of memory in order to remember the 42; that is, NewValue must have allocated some memory. Almost all the time you are using reflect the goal is to inspect or to change other data, not to manipulate data stored solely inside a reflect.Value. This CL removes use case (1), so that an assignable reflect.Value must always refer to some other piece of data in the program. Put another way, removing this case would make v := reflect.NewValue(0) v.Set(42) as illegal as 0 = 42. It would also make this illegal: x := 0 v := reflect.NewValue(x) v.Set(42) for the same reason. (Note that right now, v.Set(42) "succeeds" but does not change the value of x.) If you really wanted to make v refer to x, you'd start with &x and dereference it: x := 0 v := reflect.NewValue(&x).Elem() // v = *&x v.Set(42) It's pretty rare, except in tests, to want to use NewValue and then call Set to change the Value itself instead of some other piece of data in the program. I haven't seen it happen once yet while making the tree build with this change. For the same reasons, reflect.Zero (formerly reflect.MakeZero) would also return an unassignable, unaddressable value. This invalidates the (awkward) idiom: pv := ... some Ptr Value we have ... v := reflect.Zero(pv.Type().Elem()) pv.PointTo(v) which, when the API changed, turned into: pv := ... some Ptr Value we have ... v := reflect.Zero(pv.Type().Elem()) pv.Set(v.Addr()) In both, it is far from clear what the code is trying to do. Now that it is possible, this CL adds reflect.New(Type) Value that does the obvious thing (same as Go's new), so this code would be replaced by: pv := ... some Ptr Value we have ... pv.Set(reflect.New(pv.Type().Elem())) The changes just described can be confusing to think about, but I believe it is because the old API was confusing - it was conflating two different kinds of Values - and that the new API by itself is pretty simple: you can only Set (or call Addr on) a Value if it actually addresses some real piece of data; that is, only if it is the result of dereferencing a Ptr or indexing a Slice. If you really want the old behavior, you'd get it by translating: v := reflect.NewValue(x) into v := reflect.New(reflect.Typeof(x)).Elem() v.Set(reflect.NewValue(x)) Gofix will not be able to help with this, because whether and how to change the code depends on whether the original code meant use (1) or use (2), so the developer has to read and think about the code. You can see the effect on packages in the tree in https://golang.org/cl/4423043/. R=r CC=golang-dev https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
}
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func makechan(t *ChanType, size int64) (c *Hchan) {
c = makechan(t, size);
2008-07-13 15:29:46 -06:00
}
/*
* generic single channel send/recv
* if the bool pointer is nil,
* then the full exchange will
* occur. if pres is not nil,
* then the protocol will not
* sleep but return if it could
* not complete.
*
* sleep can wake up with g->param == nil
* when a channel involved in the sleep has
* been closed. it is easiest to loop and re-run
* the operation; we'll see that it's now closed.
*/
static bool
chansend(ChanType *t, Hchan *c, byte *ep, bool block, void *pc)
2008-07-13 15:29:46 -06:00
{
SudoG *sg;
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
SudoG mysg;
G* gp;
int64 t0;
2008-07-13 15:29:46 -06:00
if(raceenabled)
runtime·racereadobjectpc(ep, t->elem, runtime·getcallerpc(&t), chansend);
if(c == nil) {
USED(t);
if(!block)
return false;
runtime·park(nil, nil, "chan send (nil chan)");
return false; // not reached
}
2008-07-13 15:29:46 -06:00
if(debug) {
runtime·printf("chansend: chan=%p; elem=", c);
c->elemtype->alg->print(c->elemsize, ep);
runtime·prints("\n");
2008-07-13 15:29:46 -06:00
}
t0 = 0;
mysg.releasetime = 0;
if(runtime·blockprofilerate > 0) {
t0 = runtime·cputicks();
mysg.releasetime = -1;
}
runtime·lock(c);
if(raceenabled)
runtime·racereadpc(c, pc, chansend);
if(c->closed)
goto closed;
2008-07-14 15:33:39 -06:00
if(c->dataqsiz > 0)
goto asynch;
sg = dequeue(&c->recvq);
if(sg != nil) {
if(raceenabled)
racesync(c, sg);
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
runtime·unlock(c);
gp = sg->g;
gp->param = sg;
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
if(sg->elem != nil)
c->elemtype->alg->copy(c->elemsize, sg->elem, ep);
if(sg->releasetime)
sg->releasetime = runtime·cputicks();
runtime·ready(gp);
return true;
2008-07-14 15:33:39 -06:00
}
if(!block) {
runtime·unlock(c);
return false;
}
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
mysg.elem = ep;
mysg.g = g;
mysg.selectdone = nil;
g->param = nil;
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
enqueue(&c->sendq, &mysg);
runtime·parkunlock(c, "chan send");
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
if(g->param == nil) {
runtime·lock(c);
if(!c->closed)
runtime·throw("chansend: spurious wakeup");
goto closed;
}
if(mysg.releasetime > 0)
runtime·blockevent(mysg.releasetime - t0, 2);
return true;
2008-07-14 15:33:39 -06:00
asynch:
if(c->closed)
goto closed;
if(c->qcount >= c->dataqsiz) {
if(!block) {
runtime·unlock(c);
return false;
}
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
mysg.g = g;
mysg.elem = nil;
mysg.selectdone = nil;
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
enqueue(&c->sendq, &mysg);
runtime·parkunlock(c, "chan send");
runtime·lock(c);
goto asynch;
2008-07-14 18:41:38 -06:00
}
if(raceenabled) {
if(c->dataqsiz == 1)
runtime·raceacquire(chanbuf(c, c->sendx));
runtime·racerelease(chanbuf(c, c->sendx));
}
c->elemtype->alg->copy(c->elemsize, chanbuf(c, c->sendx), ep);
if(++c->sendx == c->dataqsiz)
c->sendx = 0;
2008-07-14 18:41:38 -06:00
c->qcount++;
sg = dequeue(&c->recvq);
if(sg != nil) {
gp = sg->g;
runtime·unlock(c);
if(sg->releasetime)
sg->releasetime = runtime·cputicks();
runtime·ready(gp);
} else
runtime·unlock(c);
if(mysg.releasetime > 0)
runtime·blockevent(mysg.releasetime - t0, 2);
return true;
closed:
runtime·unlock(c);
runtime·panicstring("send on closed channel");
return false; // not reached
2008-07-13 15:29:46 -06:00
}
2008-07-13 17:20:27 -06:00
reflect: more efficient; cannot Set result of NewValue anymore * Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5. The current reflect uses Set to mean two subtly different things. (1) If you have a reflect.Value v, it might just represent itself (as in v = reflect.NewValue(42)), in which case calling v.Set only changed v, not any other data in the program. (2) If you have a reflect Value v derived from a pointer or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)), v represents the value held there. Changing x[0] affects the value returned by v.Int(), and calling v.Set affects x[0]. This was not really by design; it just happened that way. The motivation for the new reflect implementation was to remove mallocs. The use case (1) has an implicit malloc inside it. If you can do: v := reflect.NewValue(0) v.Set(42) i := v.Int() // i = 42 then that implies that v is referring to some underlying chunk of memory in order to remember the 42; that is, NewValue must have allocated some memory. Almost all the time you are using reflect the goal is to inspect or to change other data, not to manipulate data stored solely inside a reflect.Value. This CL removes use case (1), so that an assignable reflect.Value must always refer to some other piece of data in the program. Put another way, removing this case would make v := reflect.NewValue(0) v.Set(42) as illegal as 0 = 42. It would also make this illegal: x := 0 v := reflect.NewValue(x) v.Set(42) for the same reason. (Note that right now, v.Set(42) "succeeds" but does not change the value of x.) If you really wanted to make v refer to x, you'd start with &x and dereference it: x := 0 v := reflect.NewValue(&x).Elem() // v = *&x v.Set(42) It's pretty rare, except in tests, to want to use NewValue and then call Set to change the Value itself instead of some other piece of data in the program. I haven't seen it happen once yet while making the tree build with this change. For the same reasons, reflect.Zero (formerly reflect.MakeZero) would also return an unassignable, unaddressable value. This invalidates the (awkward) idiom: pv := ... some Ptr Value we have ... v := reflect.Zero(pv.Type().Elem()) pv.PointTo(v) which, when the API changed, turned into: pv := ... some Ptr Value we have ... v := reflect.Zero(pv.Type().Elem()) pv.Set(v.Addr()) In both, it is far from clear what the code is trying to do. Now that it is possible, this CL adds reflect.New(Type) Value that does the obvious thing (same as Go's new), so this code would be replaced by: pv := ... some Ptr Value we have ... pv.Set(reflect.New(pv.Type().Elem())) The changes just described can be confusing to think about, but I believe it is because the old API was confusing - it was conflating two different kinds of Values - and that the new API by itself is pretty simple: you can only Set (or call Addr on) a Value if it actually addresses some real piece of data; that is, only if it is the result of dereferencing a Ptr or indexing a Slice. If you really want the old behavior, you'd get it by translating: v := reflect.NewValue(x) into v := reflect.New(reflect.Typeof(x)).Elem() v.Set(reflect.NewValue(x)) Gofix will not be able to help with this, because whether and how to change the code depends on whether the original code meant use (1) or use (2), so the developer has to read and think about the code. You can see the effect on packages in the tree in https://golang.org/cl/4423043/. R=r CC=golang-dev https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
static bool
chanrecv(ChanType *t, Hchan* c, byte *ep, bool block, bool *received)
2008-07-15 22:07:59 -06:00
{
SudoG *sg;
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
SudoG mysg;
G *gp;
int64 t0;
2008-07-16 12:46:33 -06:00
// raceenabled: don't need to check ep, as it is always on the stack.
if(debug)
runtime·printf("chanrecv: chan=%p\n", c);
if(c == nil) {
USED(t);
if(!block)
return false;
runtime·park(nil, nil, "chan receive (nil chan)");
return false; // not reached
}
t0 = 0;
mysg.releasetime = 0;
if(runtime·blockprofilerate > 0) {
t0 = runtime·cputicks();
mysg.releasetime = -1;
}
runtime·lock(c);
2008-07-15 22:07:59 -06:00
if(c->dataqsiz > 0)
goto asynch;
if(c->closed)
goto closed;
sg = dequeue(&c->sendq);
if(sg != nil) {
if(raceenabled)
racesync(c, sg);
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
runtime·unlock(c);
if(ep != nil)
c->elemtype->alg->copy(c->elemsize, ep, sg->elem);
gp = sg->g;
gp->param = sg;
if(sg->releasetime)
sg->releasetime = runtime·cputicks();
runtime·ready(gp);
2008-07-15 22:07:59 -06:00
if(received != nil)
*received = true;
return true;
2008-07-15 22:07:59 -06:00
}
if(!block) {
runtime·unlock(c);
return false;
2008-07-14 15:33:39 -06:00
}
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
mysg.elem = ep;
mysg.g = g;
mysg.selectdone = nil;
g->param = nil;
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
enqueue(&c->recvq, &mysg);
runtime·parkunlock(c, "chan receive");
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
if(g->param == nil) {
runtime·lock(c);
if(!c->closed)
runtime·throw("chanrecv: spurious wakeup");
goto closed;
}
if(received != nil)
*received = true;
if(mysg.releasetime > 0)
runtime·blockevent(mysg.releasetime - t0, 2);
return true;
2008-07-14 15:33:39 -06:00
asynch:
if(c->qcount <= 0) {
if(c->closed)
goto closed;
if(!block) {
runtime·unlock(c);
if(received != nil)
*received = false;
return false;
}
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
mysg.g = g;
mysg.elem = nil;
mysg.selectdone = nil;
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
enqueue(&c->recvq, &mysg);
runtime·parkunlock(c, "chan receive");
runtime·lock(c);
goto asynch;
2008-07-14 18:41:38 -06:00
}
if(raceenabled) {
runtime·raceacquire(chanbuf(c, c->recvx));
if(c->dataqsiz == 1)
runtime·racerelease(chanbuf(c, c->recvx));
}
if(ep != nil)
c->elemtype->alg->copy(c->elemsize, ep, chanbuf(c, c->recvx));
c->elemtype->alg->copy(c->elemsize, chanbuf(c, c->recvx), nil);
if(++c->recvx == c->dataqsiz)
c->recvx = 0;
2008-07-14 18:41:38 -06:00
c->qcount--;
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
sg = dequeue(&c->sendq);
if(sg != nil) {
gp = sg->g;
runtime·unlock(c);
if(sg->releasetime)
sg->releasetime = runtime·cputicks();
runtime·ready(gp);
} else
runtime·unlock(c);
if(received != nil)
*received = true;
if(mysg.releasetime > 0)
runtime·blockevent(mysg.releasetime - t0, 2);
return true;
closed:
if(ep != nil)
c->elemtype->alg->copy(c->elemsize, ep, nil);
if(received != nil)
*received = false;
if(raceenabled)
runtime·raceacquire(c);
runtime·unlock(c);
if(mysg.releasetime > 0)
runtime·blockevent(mysg.releasetime - t0, 2);
return true;
2008-07-13 17:20:27 -06:00
}
#pragma textflag NOSPLIT
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func chansend1(t *ChanType, c *Hchan, elem *byte) {
chansend(t, c, elem, true, runtime·getcallerpc(&t));
}
#pragma textflag NOSPLIT
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func chanrecv1(t *ChanType, c *Hchan, elem *byte) {
chanrecv(t, c, elem, true, nil);
}
2008-07-14 15:33:39 -06:00
// chanrecv2(hchan *chan any, elem *any) (received bool);
#pragma textflag NOSPLIT
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func chanrecv2(t *ChanType, c *Hchan, elem *byte) (received bool) {
chanrecv(t, c, elem, true, &received);
}
// compiler implements
//
// select {
// case c <- v:
// ... foo
// default:
// ... bar
// }
//
// as
//
// if selectnbsend(c, v) {
// ... foo
// } else {
// ... bar
// }
//
#pragma textflag NOSPLIT
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func selectnbsend(t *ChanType, c *Hchan, elem *byte) (selected bool) {
selected = chansend(t, c, elem, false, runtime·getcallerpc(&t));
}
// compiler implements
//
// select {
// case v = <-c:
// ... foo
// default:
// ... bar
// }
//
// as
//
// if selectnbrecv(&v, c) {
// ... foo
// } else {
// ... bar
// }
//
#pragma textflag NOSPLIT
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func selectnbrecv(t *ChanType, elem *byte, c *Hchan) (selected bool) {
selected = chanrecv(t, c, elem, false, nil);
}
// compiler implements
//
// select {
// case v, ok = <-c:
// ... foo
// default:
// ... bar
// }
//
// as
//
// if c != nil && selectnbrecv2(&v, &ok, c) {
// ... foo
// } else {
// ... bar
// }
//
#pragma textflag NOSPLIT
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func selectnbrecv2(t *ChanType, elem *byte, received *bool, c *Hchan) (selected bool) {
selected = chanrecv(t, c, elem, false, received);
}
#pragma textflag NOSPLIT
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func reflect·chansend(t *ChanType, c *Hchan, elem *byte, nb bool) (selected bool) {
selected = chansend(t, c, elem, !nb, runtime·getcallerpc(&t));
reflect: more efficient; cannot Set result of NewValue anymore * Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5. The current reflect uses Set to mean two subtly different things. (1) If you have a reflect.Value v, it might just represent itself (as in v = reflect.NewValue(42)), in which case calling v.Set only changed v, not any other data in the program. (2) If you have a reflect Value v derived from a pointer or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)), v represents the value held there. Changing x[0] affects the value returned by v.Int(), and calling v.Set affects x[0]. This was not really by design; it just happened that way. The motivation for the new reflect implementation was to remove mallocs. The use case (1) has an implicit malloc inside it. If you can do: v := reflect.NewValue(0) v.Set(42) i := v.Int() // i = 42 then that implies that v is referring to some underlying chunk of memory in order to remember the 42; that is, NewValue must have allocated some memory. Almost all the time you are using reflect the goal is to inspect or to change other data, not to manipulate data stored solely inside a reflect.Value. This CL removes use case (1), so that an assignable reflect.Value must always refer to some other piece of data in the program. Put another way, removing this case would make v := reflect.NewValue(0) v.Set(42) as illegal as 0 = 42. It would also make this illegal: x := 0 v := reflect.NewValue(x) v.Set(42) for the same reason. (Note that right now, v.Set(42) "succeeds" but does not change the value of x.) If you really wanted to make v refer to x, you'd start with &x and dereference it: x := 0 v := reflect.NewValue(&x).Elem() // v = *&x v.Set(42) It's pretty rare, except in tests, to want to use NewValue and then call Set to change the Value itself instead of some other piece of data in the program. I haven't seen it happen once yet while making the tree build with this change. For the same reasons, reflect.Zero (formerly reflect.MakeZero) would also return an unassignable, unaddressable value. This invalidates the (awkward) idiom: pv := ... some Ptr Value we have ... v := reflect.Zero(pv.Type().Elem()) pv.PointTo(v) which, when the API changed, turned into: pv := ... some Ptr Value we have ... v := reflect.Zero(pv.Type().Elem()) pv.Set(v.Addr()) In both, it is far from clear what the code is trying to do. Now that it is possible, this CL adds reflect.New(Type) Value that does the obvious thing (same as Go's new), so this code would be replaced by: pv := ... some Ptr Value we have ... pv.Set(reflect.New(pv.Type().Elem())) The changes just described can be confusing to think about, but I believe it is because the old API was confusing - it was conflating two different kinds of Values - and that the new API by itself is pretty simple: you can only Set (or call Addr on) a Value if it actually addresses some real piece of data; that is, only if it is the result of dereferencing a Ptr or indexing a Slice. If you really want the old behavior, you'd get it by translating: v := reflect.NewValue(x) into v := reflect.New(reflect.Typeof(x)).Elem() v.Set(reflect.NewValue(x)) Gofix will not be able to help with this, because whether and how to change the code depends on whether the original code meant use (1) or use (2), so the developer has to read and think about the code. You can see the effect on packages in the tree in https://golang.org/cl/4423043/. R=r CC=golang-dev https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
}
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func reflect·chanrecv(t *ChanType, c *Hchan, nb bool, elem *byte) (selected bool, received bool) {
reflect: more efficient; cannot Set result of NewValue anymore * Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5. The current reflect uses Set to mean two subtly different things. (1) If you have a reflect.Value v, it might just represent itself (as in v = reflect.NewValue(42)), in which case calling v.Set only changed v, not any other data in the program. (2) If you have a reflect Value v derived from a pointer or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)), v represents the value held there. Changing x[0] affects the value returned by v.Int(), and calling v.Set affects x[0]. This was not really by design; it just happened that way. The motivation for the new reflect implementation was to remove mallocs. The use case (1) has an implicit malloc inside it. If you can do: v := reflect.NewValue(0) v.Set(42) i := v.Int() // i = 42 then that implies that v is referring to some underlying chunk of memory in order to remember the 42; that is, NewValue must have allocated some memory. Almost all the time you are using reflect the goal is to inspect or to change other data, not to manipulate data stored solely inside a reflect.Value. This CL removes use case (1), so that an assignable reflect.Value must always refer to some other piece of data in the program. Put another way, removing this case would make v := reflect.NewValue(0) v.Set(42) as illegal as 0 = 42. It would also make this illegal: x := 0 v := reflect.NewValue(x) v.Set(42) for the same reason. (Note that right now, v.Set(42) "succeeds" but does not change the value of x.) If you really wanted to make v refer to x, you'd start with &x and dereference it: x := 0 v := reflect.NewValue(&x).Elem() // v = *&x v.Set(42) It's pretty rare, except in tests, to want to use NewValue and then call Set to change the Value itself instead of some other piece of data in the program. I haven't seen it happen once yet while making the tree build with this change. For the same reasons, reflect.Zero (formerly reflect.MakeZero) would also return an unassignable, unaddressable value. This invalidates the (awkward) idiom: pv := ... some Ptr Value we have ... v := reflect.Zero(pv.Type().Elem()) pv.PointTo(v) which, when the API changed, turned into: pv := ... some Ptr Value we have ... v := reflect.Zero(pv.Type().Elem()) pv.Set(v.Addr()) In both, it is far from clear what the code is trying to do. Now that it is possible, this CL adds reflect.New(Type) Value that does the obvious thing (same as Go's new), so this code would be replaced by: pv := ... some Ptr Value we have ... pv.Set(reflect.New(pv.Type().Elem())) The changes just described can be confusing to think about, but I believe it is because the old API was confusing - it was conflating two different kinds of Values - and that the new API by itself is pretty simple: you can only Set (or call Addr on) a Value if it actually addresses some real piece of data; that is, only if it is the result of dereferencing a Ptr or indexing a Slice. If you really want the old behavior, you'd get it by translating: v := reflect.NewValue(x) into v := reflect.New(reflect.Typeof(x)).Elem() v.Set(reflect.NewValue(x)) Gofix will not be able to help with this, because whether and how to change the code depends on whether the original code meant use (1) or use (2), so the developer has to read and think about the code. You can see the effect on packages in the tree in https://golang.org/cl/4423043/. R=r CC=golang-dev https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
received = false;
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
selected = chanrecv(t, c, elem, !nb, &received);
reflect: more efficient; cannot Set result of NewValue anymore * Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5. The current reflect uses Set to mean two subtly different things. (1) If you have a reflect.Value v, it might just represent itself (as in v = reflect.NewValue(42)), in which case calling v.Set only changed v, not any other data in the program. (2) If you have a reflect Value v derived from a pointer or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)), v represents the value held there. Changing x[0] affects the value returned by v.Int(), and calling v.Set affects x[0]. This was not really by design; it just happened that way. The motivation for the new reflect implementation was to remove mallocs. The use case (1) has an implicit malloc inside it. If you can do: v := reflect.NewValue(0) v.Set(42) i := v.Int() // i = 42 then that implies that v is referring to some underlying chunk of memory in order to remember the 42; that is, NewValue must have allocated some memory. Almost all the time you are using reflect the goal is to inspect or to change other data, not to manipulate data stored solely inside a reflect.Value. This CL removes use case (1), so that an assignable reflect.Value must always refer to some other piece of data in the program. Put another way, removing this case would make v := reflect.NewValue(0) v.Set(42) as illegal as 0 = 42. It would also make this illegal: x := 0 v := reflect.NewValue(x) v.Set(42) for the same reason. (Note that right now, v.Set(42) "succeeds" but does not change the value of x.) If you really wanted to make v refer to x, you'd start with &x and dereference it: x := 0 v := reflect.NewValue(&x).Elem() // v = *&x v.Set(42) It's pretty rare, except in tests, to want to use NewValue and then call Set to change the Value itself instead of some other piece of data in the program. I haven't seen it happen once yet while making the tree build with this change. For the same reasons, reflect.Zero (formerly reflect.MakeZero) would also return an unassignable, unaddressable value. This invalidates the (awkward) idiom: pv := ... some Ptr Value we have ... v := reflect.Zero(pv.Type().Elem()) pv.PointTo(v) which, when the API changed, turned into: pv := ... some Ptr Value we have ... v := reflect.Zero(pv.Type().Elem()) pv.Set(v.Addr()) In both, it is far from clear what the code is trying to do. Now that it is possible, this CL adds reflect.New(Type) Value that does the obvious thing (same as Go's new), so this code would be replaced by: pv := ... some Ptr Value we have ... pv.Set(reflect.New(pv.Type().Elem())) The changes just described can be confusing to think about, but I believe it is because the old API was confusing - it was conflating two different kinds of Values - and that the new API by itself is pretty simple: you can only Set (or call Addr on) a Value if it actually addresses some real piece of data; that is, only if it is the result of dereferencing a Ptr or indexing a Slice. If you really want the old behavior, you'd get it by translating: v := reflect.NewValue(x) into v := reflect.New(reflect.Typeof(x)).Elem() v.Set(reflect.NewValue(x)) Gofix will not be able to help with this, because whether and how to change the code depends on whether the original code meant use (1) or use (2), so the developer has to read and think about the code. You can see the effect on packages in the tree in https://golang.org/cl/4423043/. R=r CC=golang-dev https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
}
static Select* newselect(int32);
ld: detect stack overflow due to NOSPLIT Fix problems found. On amd64, various library routines had bigger stack frames than expected, because large function calls had been added. runtime.assertI2T: nosplit stack overflow 120 assumed on entry to runtime.assertI2T 8 after runtime.assertI2T uses 112 0 on entry to runtime.newTypeAssertionError -8 on entry to runtime.morestack01 runtime.assertE2E: nosplit stack overflow 120 assumed on entry to runtime.assertE2E 16 after runtime.assertE2E uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.assertE2T: nosplit stack overflow 120 assumed on entry to runtime.assertE2T 16 after runtime.assertE2T uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.newselect: nosplit stack overflow 120 assumed on entry to runtime.newselect 56 after runtime.newselect uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectdefault: nosplit stack overflow 120 assumed on entry to runtime.selectdefault 56 after runtime.selectdefault uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectgo: nosplit stack overflow 120 assumed on entry to runtime.selectgo 0 after runtime.selectgo uses 120 -8 on entry to runtime.gosched On arm, 5c was tagging functions NOSPLIT that should not have been, like the recursive function printpanics: printpanics: nosplit stack overflow 124 assumed on entry to printpanics 112 after printpanics uses 12 108 on entry to printpanics 96 after printpanics uses 12 92 on entry to printpanics 80 after printpanics uses 12 76 on entry to printpanics 64 after printpanics uses 12 60 on entry to printpanics 48 after printpanics uses 12 44 on entry to printpanics 32 after printpanics uses 12 28 on entry to printpanics 16 after printpanics uses 12 12 on entry to printpanics 0 after printpanics uses 12 -4 on entry to printpanics R=r, r2 CC=golang-dev https://golang.org/cl/4188061
2011-02-22 15:40:40 -07:00
#pragma textflag NOSPLIT
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func newselect(size int32) (sel *byte) {
sel = (byte*)newselect(size);
ld: detect stack overflow due to NOSPLIT Fix problems found. On amd64, various library routines had bigger stack frames than expected, because large function calls had been added. runtime.assertI2T: nosplit stack overflow 120 assumed on entry to runtime.assertI2T 8 after runtime.assertI2T uses 112 0 on entry to runtime.newTypeAssertionError -8 on entry to runtime.morestack01 runtime.assertE2E: nosplit stack overflow 120 assumed on entry to runtime.assertE2E 16 after runtime.assertE2E uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.assertE2T: nosplit stack overflow 120 assumed on entry to runtime.assertE2T 16 after runtime.assertE2T uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.newselect: nosplit stack overflow 120 assumed on entry to runtime.newselect 56 after runtime.newselect uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectdefault: nosplit stack overflow 120 assumed on entry to runtime.selectdefault 56 after runtime.selectdefault uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectgo: nosplit stack overflow 120 assumed on entry to runtime.selectgo 0 after runtime.selectgo uses 120 -8 on entry to runtime.gosched On arm, 5c was tagging functions NOSPLIT that should not have been, like the recursive function printpanics: printpanics: nosplit stack overflow 124 assumed on entry to printpanics 112 after printpanics uses 12 108 on entry to printpanics 96 after printpanics uses 12 92 on entry to printpanics 80 after printpanics uses 12 76 on entry to printpanics 64 after printpanics uses 12 60 on entry to printpanics 48 after printpanics uses 12 44 on entry to printpanics 32 after printpanics uses 12 28 on entry to printpanics 16 after printpanics uses 12 12 on entry to printpanics 0 after printpanics uses 12 -4 on entry to printpanics R=r, r2 CC=golang-dev https://golang.org/cl/4188061
2011-02-22 15:40:40 -07:00
}
static Select*
newselect(int32 size)
ld: detect stack overflow due to NOSPLIT Fix problems found. On amd64, various library routines had bigger stack frames than expected, because large function calls had been added. runtime.assertI2T: nosplit stack overflow 120 assumed on entry to runtime.assertI2T 8 after runtime.assertI2T uses 112 0 on entry to runtime.newTypeAssertionError -8 on entry to runtime.morestack01 runtime.assertE2E: nosplit stack overflow 120 assumed on entry to runtime.assertE2E 16 after runtime.assertE2E uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.assertE2T: nosplit stack overflow 120 assumed on entry to runtime.assertE2T 16 after runtime.assertE2T uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.newselect: nosplit stack overflow 120 assumed on entry to runtime.newselect 56 after runtime.newselect uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectdefault: nosplit stack overflow 120 assumed on entry to runtime.selectdefault 56 after runtime.selectdefault uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectgo: nosplit stack overflow 120 assumed on entry to runtime.selectgo 0 after runtime.selectgo uses 120 -8 on entry to runtime.gosched On arm, 5c was tagging functions NOSPLIT that should not have been, like the recursive function printpanics: printpanics: nosplit stack overflow 124 assumed on entry to printpanics 112 after printpanics uses 12 108 on entry to printpanics 96 after printpanics uses 12 92 on entry to printpanics 80 after printpanics uses 12 76 on entry to printpanics 64 after printpanics uses 12 60 on entry to printpanics 48 after printpanics uses 12 44 on entry to printpanics 32 after printpanics uses 12 28 on entry to printpanics 16 after printpanics uses 12 12 on entry to printpanics 0 after printpanics uses 12 -4 on entry to printpanics R=r, r2 CC=golang-dev https://golang.org/cl/4188061
2011-02-22 15:40:40 -07:00
{
int32 n;
Select *sel;
n = 0;
if(size > 1)
n = size-1;
// allocate all the memory we need in a single allocation
// start with Select with size cases
// then lockorder with size entries
// then pollorder with size entries
sel = runtime·mal(sizeof(*sel) +
n*sizeof(sel->scase[0]) +
size*sizeof(sel->lockorder[0]) +
size*sizeof(sel->pollorder[0]));
sel->tcase = size;
sel->ncase = 0;
sel->lockorder = (void*)(sel->scase + size);
sel->pollorder = (void*)(sel->lockorder + size);
if(debug)
runtime·printf("newselect s=%p size=%d\n", sel, size);
return sel;
}
// cut in half to give stack a chance to split
static void selectsend(Select *sel, Hchan *c, void *pc, void *elem, int32 so);
#pragma textflag NOSPLIT
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func selectsend(sel *Select, c *Hchan, elem *byte) (selected bool) {
selected = false;
// nil cases do not compete
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
if(c != nil)
selectsend(sel, c, runtime·getcallerpc(&sel), elem, (byte*)&selected - (byte*)&sel);
}
static void
selectsend(Select *sel, Hchan *c, void *pc, void *elem, int32 so)
{
int32 i;
Scase *cas;
i = sel->ncase;
if(i >= sel->tcase)
runtime·throw("selectsend: too many cases");
sel->ncase = i+1;
cas = &sel->scase[i];
cas->pc = pc;
cas->chan = c;
cas->so = so;
cas->kind = CaseSend;
cas->sg.elem = elem;
if(debug)
runtime·printf("selectsend s=%p pc=%p chan=%p so=%d\n",
sel, cas->pc, cas->chan, cas->so);
}
// cut in half to give stack a chance to split
static void selectrecv(Select *sel, Hchan *c, void *pc, void *elem, bool*, int32 so);
#pragma textflag NOSPLIT
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func selectrecv(sel *Select, c *Hchan, elem *byte) (selected bool) {
selected = false;
// nil cases do not compete
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
if(c != nil)
selectrecv(sel, c, runtime·getcallerpc(&sel), elem, nil, (byte*)&selected - (byte*)&sel);
}
#pragma textflag NOSPLIT
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func selectrecv2(sel *Select, c *Hchan, elem *byte, received *bool) (selected bool) {
selected = false;
// nil cases do not compete
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
if(c != nil)
selectrecv(sel, c, runtime·getcallerpc(&sel), elem, received, (byte*)&selected - (byte*)&sel);
}
static void
selectrecv(Select *sel, Hchan *c, void *pc, void *elem, bool *received, int32 so)
{
int32 i;
Scase *cas;
i = sel->ncase;
if(i >= sel->tcase)
runtime·throw("selectrecv: too many cases");
sel->ncase = i+1;
cas = &sel->scase[i];
cas->pc = pc;
cas->chan = c;
cas->so = so;
cas->kind = CaseRecv;
cas->sg.elem = elem;
cas->receivedp = received;
if(debug)
runtime·printf("selectrecv s=%p pc=%p chan=%p so=%d\n",
sel, cas->pc, cas->chan, cas->so);
}
// cut in half to give stack a chance to split
static void selectdefault(Select*, void*, int32);
ld: detect stack overflow due to NOSPLIT Fix problems found. On amd64, various library routines had bigger stack frames than expected, because large function calls had been added. runtime.assertI2T: nosplit stack overflow 120 assumed on entry to runtime.assertI2T 8 after runtime.assertI2T uses 112 0 on entry to runtime.newTypeAssertionError -8 on entry to runtime.morestack01 runtime.assertE2E: nosplit stack overflow 120 assumed on entry to runtime.assertE2E 16 after runtime.assertE2E uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.assertE2T: nosplit stack overflow 120 assumed on entry to runtime.assertE2T 16 after runtime.assertE2T uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.newselect: nosplit stack overflow 120 assumed on entry to runtime.newselect 56 after runtime.newselect uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectdefault: nosplit stack overflow 120 assumed on entry to runtime.selectdefault 56 after runtime.selectdefault uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectgo: nosplit stack overflow 120 assumed on entry to runtime.selectgo 0 after runtime.selectgo uses 120 -8 on entry to runtime.gosched On arm, 5c was tagging functions NOSPLIT that should not have been, like the recursive function printpanics: printpanics: nosplit stack overflow 124 assumed on entry to printpanics 112 after printpanics uses 12 108 on entry to printpanics 96 after printpanics uses 12 92 on entry to printpanics 80 after printpanics uses 12 76 on entry to printpanics 64 after printpanics uses 12 60 on entry to printpanics 48 after printpanics uses 12 44 on entry to printpanics 32 after printpanics uses 12 28 on entry to printpanics 16 after printpanics uses 12 12 on entry to printpanics 0 after printpanics uses 12 -4 on entry to printpanics R=r, r2 CC=golang-dev https://golang.org/cl/4188061
2011-02-22 15:40:40 -07:00
#pragma textflag NOSPLIT
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func selectdefault(sel *Select) (selected bool) {
selected = false;
selectdefault(sel, runtime·getcallerpc(&sel), (byte*)&selected - (byte*)&sel);
ld: detect stack overflow due to NOSPLIT Fix problems found. On amd64, various library routines had bigger stack frames than expected, because large function calls had been added. runtime.assertI2T: nosplit stack overflow 120 assumed on entry to runtime.assertI2T 8 after runtime.assertI2T uses 112 0 on entry to runtime.newTypeAssertionError -8 on entry to runtime.morestack01 runtime.assertE2E: nosplit stack overflow 120 assumed on entry to runtime.assertE2E 16 after runtime.assertE2E uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.assertE2T: nosplit stack overflow 120 assumed on entry to runtime.assertE2T 16 after runtime.assertE2T uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.newselect: nosplit stack overflow 120 assumed on entry to runtime.newselect 56 after runtime.newselect uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectdefault: nosplit stack overflow 120 assumed on entry to runtime.selectdefault 56 after runtime.selectdefault uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectgo: nosplit stack overflow 120 assumed on entry to runtime.selectgo 0 after runtime.selectgo uses 120 -8 on entry to runtime.gosched On arm, 5c was tagging functions NOSPLIT that should not have been, like the recursive function printpanics: printpanics: nosplit stack overflow 124 assumed on entry to printpanics 112 after printpanics uses 12 108 on entry to printpanics 96 after printpanics uses 12 92 on entry to printpanics 80 after printpanics uses 12 76 on entry to printpanics 64 after printpanics uses 12 60 on entry to printpanics 48 after printpanics uses 12 44 on entry to printpanics 32 after printpanics uses 12 28 on entry to printpanics 16 after printpanics uses 12 12 on entry to printpanics 0 after printpanics uses 12 -4 on entry to printpanics R=r, r2 CC=golang-dev https://golang.org/cl/4188061
2011-02-22 15:40:40 -07:00
}
static void
selectdefault(Select *sel, void *callerpc, int32 so)
ld: detect stack overflow due to NOSPLIT Fix problems found. On amd64, various library routines had bigger stack frames than expected, because large function calls had been added. runtime.assertI2T: nosplit stack overflow 120 assumed on entry to runtime.assertI2T 8 after runtime.assertI2T uses 112 0 on entry to runtime.newTypeAssertionError -8 on entry to runtime.morestack01 runtime.assertE2E: nosplit stack overflow 120 assumed on entry to runtime.assertE2E 16 after runtime.assertE2E uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.assertE2T: nosplit stack overflow 120 assumed on entry to runtime.assertE2T 16 after runtime.assertE2T uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.newselect: nosplit stack overflow 120 assumed on entry to runtime.newselect 56 after runtime.newselect uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectdefault: nosplit stack overflow 120 assumed on entry to runtime.selectdefault 56 after runtime.selectdefault uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectgo: nosplit stack overflow 120 assumed on entry to runtime.selectgo 0 after runtime.selectgo uses 120 -8 on entry to runtime.gosched On arm, 5c was tagging functions NOSPLIT that should not have been, like the recursive function printpanics: printpanics: nosplit stack overflow 124 assumed on entry to printpanics 112 after printpanics uses 12 108 on entry to printpanics 96 after printpanics uses 12 92 on entry to printpanics 80 after printpanics uses 12 76 on entry to printpanics 64 after printpanics uses 12 60 on entry to printpanics 48 after printpanics uses 12 44 on entry to printpanics 32 after printpanics uses 12 28 on entry to printpanics 16 after printpanics uses 12 12 on entry to printpanics 0 after printpanics uses 12 -4 on entry to printpanics R=r, r2 CC=golang-dev https://golang.org/cl/4188061
2011-02-22 15:40:40 -07:00
{
2008-11-05 22:50:28 -07:00
int32 i;
Scase *cas;
i = sel->ncase;
if(i >= sel->tcase)
runtime·throw("selectdefault: too many cases");
sel->ncase = i+1;
cas = &sel->scase[i];
cas->pc = callerpc;
2008-11-05 22:50:28 -07:00
cas->chan = nil;
cas->so = so;
cas->kind = CaseDefault;
if(debug)
runtime·printf("selectdefault s=%p pc=%p so=%d\n",
sel, cas->pc, cas->so);
}
static void
sellock(Select *sel)
{
uint32 i;
Hchan *c, *c0;
c = nil;
for(i=0; i<sel->ncase; i++) {
c0 = sel->lockorder[i];
if(c0 && c0 != c) {
c = sel->lockorder[i];
runtime·lock(c);
}
}
}
static void
selunlock(Select *sel)
{
int32 i, n, r;
Hchan *c;
// 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.
// Consider the following situation.
// First M calls runtime·park() in runtime·selectgo() passing the sel.
// Once runtime·park() has unlocked the last lock, another M makes
// the G that calls select runnable again and schedules it for execution.
// When the G runs on another M, it locks all the locks and frees sel.
// Now if the first M touches sel, it will access freed memory.
n = (int32)sel->ncase;
r = 0;
// skip the default case
if(n>0 && sel->lockorder[0] == nil)
r = 1;
for(i = n-1; i >= r; i--) {
c = sel->lockorder[i];
if(i>0 && sel->lockorder[i-1] == c)
continue; // will unlock it on the next iteration
runtime·unlock(c);
}
}
static bool
selparkcommit(G *gp, void *sel)
{
USED(gp);
selunlock(sel);
return true;
}
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func block() {
runtime·park(nil, nil, "select (no cases)"); // forever
}
static void* selectgo(Select**);
ld: detect stack overflow due to NOSPLIT Fix problems found. On amd64, various library routines had bigger stack frames than expected, because large function calls had been added. runtime.assertI2T: nosplit stack overflow 120 assumed on entry to runtime.assertI2T 8 after runtime.assertI2T uses 112 0 on entry to runtime.newTypeAssertionError -8 on entry to runtime.morestack01 runtime.assertE2E: nosplit stack overflow 120 assumed on entry to runtime.assertE2E 16 after runtime.assertE2E uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.assertE2T: nosplit stack overflow 120 assumed on entry to runtime.assertE2T 16 after runtime.assertE2T uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.newselect: nosplit stack overflow 120 assumed on entry to runtime.newselect 56 after runtime.newselect uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectdefault: nosplit stack overflow 120 assumed on entry to runtime.selectdefault 56 after runtime.selectdefault uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectgo: nosplit stack overflow 120 assumed on entry to runtime.selectgo 0 after runtime.selectgo uses 120 -8 on entry to runtime.gosched On arm, 5c was tagging functions NOSPLIT that should not have been, like the recursive function printpanics: printpanics: nosplit stack overflow 124 assumed on entry to printpanics 112 after printpanics uses 12 108 on entry to printpanics 96 after printpanics uses 12 92 on entry to printpanics 80 after printpanics uses 12 76 on entry to printpanics 64 after printpanics uses 12 60 on entry to printpanics 48 after printpanics uses 12 44 on entry to printpanics 32 after printpanics uses 12 28 on entry to printpanics 16 after printpanics uses 12 12 on entry to printpanics 0 after printpanics uses 12 -4 on entry to printpanics R=r, r2 CC=golang-dev https://golang.org/cl/4188061
2011-02-22 15:40:40 -07:00
// selectgo(sel *byte);
//
// overwrites return pc on stack to signal which case of the select
// to run, so cannot appear at the top of a split stack.
#pragma textflag NOSPLIT
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func selectgo(sel *Select) {
runtime·setcallerpc(&sel, selectgo(&sel));
ld: detect stack overflow due to NOSPLIT Fix problems found. On amd64, various library routines had bigger stack frames than expected, because large function calls had been added. runtime.assertI2T: nosplit stack overflow 120 assumed on entry to runtime.assertI2T 8 after runtime.assertI2T uses 112 0 on entry to runtime.newTypeAssertionError -8 on entry to runtime.morestack01 runtime.assertE2E: nosplit stack overflow 120 assumed on entry to runtime.assertE2E 16 after runtime.assertE2E uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.assertE2T: nosplit stack overflow 120 assumed on entry to runtime.assertE2T 16 after runtime.assertE2T uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.newselect: nosplit stack overflow 120 assumed on entry to runtime.newselect 56 after runtime.newselect uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectdefault: nosplit stack overflow 120 assumed on entry to runtime.selectdefault 56 after runtime.selectdefault uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectgo: nosplit stack overflow 120 assumed on entry to runtime.selectgo 0 after runtime.selectgo uses 120 -8 on entry to runtime.gosched On arm, 5c was tagging functions NOSPLIT that should not have been, like the recursive function printpanics: printpanics: nosplit stack overflow 124 assumed on entry to printpanics 112 after printpanics uses 12 108 on entry to printpanics 96 after printpanics uses 12 92 on entry to printpanics 80 after printpanics uses 12 76 on entry to printpanics 64 after printpanics uses 12 60 on entry to printpanics 48 after printpanics uses 12 44 on entry to printpanics 32 after printpanics uses 12 28 on entry to printpanics 16 after printpanics uses 12 12 on entry to printpanics 0 after printpanics uses 12 -4 on entry to printpanics R=r, r2 CC=golang-dev https://golang.org/cl/4188061
2011-02-22 15:40:40 -07:00
}
static void*
ld: detect stack overflow due to NOSPLIT Fix problems found. On amd64, various library routines had bigger stack frames than expected, because large function calls had been added. runtime.assertI2T: nosplit stack overflow 120 assumed on entry to runtime.assertI2T 8 after runtime.assertI2T uses 112 0 on entry to runtime.newTypeAssertionError -8 on entry to runtime.morestack01 runtime.assertE2E: nosplit stack overflow 120 assumed on entry to runtime.assertE2E 16 after runtime.assertE2E uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.assertE2T: nosplit stack overflow 120 assumed on entry to runtime.assertE2T 16 after runtime.assertE2T uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.newselect: nosplit stack overflow 120 assumed on entry to runtime.newselect 56 after runtime.newselect uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectdefault: nosplit stack overflow 120 assumed on entry to runtime.selectdefault 56 after runtime.selectdefault uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectgo: nosplit stack overflow 120 assumed on entry to runtime.selectgo 0 after runtime.selectgo uses 120 -8 on entry to runtime.gosched On arm, 5c was tagging functions NOSPLIT that should not have been, like the recursive function printpanics: printpanics: nosplit stack overflow 124 assumed on entry to printpanics 112 after printpanics uses 12 108 on entry to printpanics 96 after printpanics uses 12 92 on entry to printpanics 80 after printpanics uses 12 76 on entry to printpanics 64 after printpanics uses 12 60 on entry to printpanics 48 after printpanics uses 12 44 on entry to printpanics 32 after printpanics uses 12 28 on entry to printpanics 16 after printpanics uses 12 12 on entry to printpanics 0 after printpanics uses 12 -4 on entry to printpanics R=r, r2 CC=golang-dev https://golang.org/cl/4188061
2011-02-22 15:40:40 -07:00
selectgo(Select **selp)
{
Select *sel;
uint32 o, i, j, k, done;
int64 t0;
Scase *cas, *dfl;
Hchan *c;
SudoG *sg;
G *gp;
byte *as;
void *pc;
ld: detect stack overflow due to NOSPLIT Fix problems found. On amd64, various library routines had bigger stack frames than expected, because large function calls had been added. runtime.assertI2T: nosplit stack overflow 120 assumed on entry to runtime.assertI2T 8 after runtime.assertI2T uses 112 0 on entry to runtime.newTypeAssertionError -8 on entry to runtime.morestack01 runtime.assertE2E: nosplit stack overflow 120 assumed on entry to runtime.assertE2E 16 after runtime.assertE2E uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.assertE2T: nosplit stack overflow 120 assumed on entry to runtime.assertE2T 16 after runtime.assertE2T uses 104 8 on entry to runtime.panic 0 on entry to runtime.morestack16 -8 after runtime.morestack16 uses 8 runtime.newselect: nosplit stack overflow 120 assumed on entry to runtime.newselect 56 after runtime.newselect uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectdefault: nosplit stack overflow 120 assumed on entry to runtime.selectdefault 56 after runtime.selectdefault uses 64 48 on entry to runtime.printf 8 after runtime.printf uses 40 0 on entry to vprintf -8 on entry to runtime.morestack16 runtime.selectgo: nosplit stack overflow 120 assumed on entry to runtime.selectgo 0 after runtime.selectgo uses 120 -8 on entry to runtime.gosched On arm, 5c was tagging functions NOSPLIT that should not have been, like the recursive function printpanics: printpanics: nosplit stack overflow 124 assumed on entry to printpanics 112 after printpanics uses 12 108 on entry to printpanics 96 after printpanics uses 12 92 on entry to printpanics 80 after printpanics uses 12 76 on entry to printpanics 64 after printpanics uses 12 60 on entry to printpanics 48 after printpanics uses 12 44 on entry to printpanics 32 after printpanics uses 12 28 on entry to printpanics 16 after printpanics uses 12 12 on entry to printpanics 0 after printpanics uses 12 -4 on entry to printpanics R=r, r2 CC=golang-dev https://golang.org/cl/4188061
2011-02-22 15:40:40 -07:00
sel = *selp;
if(debug)
runtime·printf("select: sel=%p\n", sel);
t0 = 0;
if(runtime·blockprofilerate > 0) {
t0 = runtime·cputicks();
for(i=0; i<sel->ncase; i++)
sel->scase[i].sg.releasetime = -1;
}
// The compiler rewrites selects that statically have
// only 0 or 1 cases plus default into simpler constructs.
// The only way we can end up with such small sel->ncase
// values here is for a larger select in which most channels
// have been nilled out. The general code handles those
// cases correctly, and they are rare enough not to bother
// optimizing (and needing to test).
// generate permuted order
for(i=0; i<sel->ncase; i++)
sel->pollorder[i] = i;
for(i=1; i<sel->ncase; i++) {
o = sel->pollorder[i];
j = runtime·fastrand1()%(i+1);
sel->pollorder[i] = sel->pollorder[j];
sel->pollorder[j] = o;
}
// sort the cases by Hchan address to get the locking order.
// simple heap sort, to guarantee n log n time and constant stack footprint.
for(i=0; i<sel->ncase; i++) {
j = i;
c = sel->scase[j].chan;
while(j > 0 && sel->lockorder[k=(j-1)/2] < c) {
sel->lockorder[j] = sel->lockorder[k];
j = k;
}
sel->lockorder[j] = c;
}
for(i=sel->ncase; i-->0; ) {
c = sel->lockorder[i];
sel->lockorder[i] = sel->lockorder[0];
j = 0;
for(;;) {
k = j*2+1;
if(k >= i)
break;
if(k+1 < i && sel->lockorder[k] < sel->lockorder[k+1])
k++;
if(c < sel->lockorder[k]) {
sel->lockorder[j] = sel->lockorder[k];
j = k;
continue;
}
break;
}
sel->lockorder[j] = c;
}
/*
for(i=0; i+1<sel->ncase; i++)
if(sel->lockorder[i] > sel->lockorder[i+1]) {
runtime·printf("i=%d %p %p\n", i, sel->lockorder[i], sel->lockorder[i+1]);
runtime·throw("select: broken sort");
}
*/
sellock(sel);
loop:
// pass 1 - look for something already waiting
dfl = nil;
for(i=0; i<sel->ncase; i++) {
o = sel->pollorder[i];
cas = &sel->scase[o];
c = cas->chan;
switch(cas->kind) {
case CaseRecv:
if(c->dataqsiz > 0) {
if(c->qcount > 0)
goto asyncrecv;
} else {
sg = dequeue(&c->sendq);
if(sg != nil)
goto syncrecv;
}
if(c->closed)
goto rclose;
break;
case CaseSend:
if(raceenabled)
runtime·racereadpc(c, cas->pc, chansend);
if(c->closed)
goto sclose;
if(c->dataqsiz > 0) {
if(c->qcount < c->dataqsiz)
goto asyncsend;
} else {
sg = dequeue(&c->recvq);
if(sg != nil)
goto syncsend;
}
break;
case CaseDefault:
dfl = cas;
break;
}
}
if(dfl != nil) {
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
selunlock(sel);
cas = dfl;
goto retc;
}
// pass 2 - enqueue on all chans
done = 0;
for(i=0; i<sel->ncase; i++) {
o = sel->pollorder[i];
cas = &sel->scase[o];
c = cas->chan;
sg = &cas->sg;
sg->g = g;
sg->selectdone = &done;
switch(cas->kind) {
case CaseRecv:
enqueue(&c->recvq, sg);
break;
case CaseSend:
enqueue(&c->sendq, sg);
break;
}
}
g->param = nil;
runtime·park(selparkcommit, sel, "select");
sellock(sel);
sg = g->param;
// pass 3 - dequeue from unsuccessful chans
// otherwise they stack up on quiet channels
for(i=0; i<sel->ncase; i++) {
cas = &sel->scase[i];
if(cas != (Scase*)sg) {
c = cas->chan;
if(cas->kind == CaseSend)
dequeueg(&c->sendq);
else
dequeueg(&c->recvq);
}
}
if(sg == nil)
goto loop;
cas = (Scase*)sg;
c = cas->chan;
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
if(c->dataqsiz > 0)
runtime·throw("selectgo: shouldn't happen");
if(debug)
runtime·printf("wait-return: sel=%p c=%p cas=%p kind=%d\n",
sel, c, cas, cas->kind);
if(cas->kind == CaseRecv) {
if(cas->receivedp != nil)
*cas->receivedp = true;
}
if(raceenabled) {
if(cas->kind == CaseRecv && cas->sg.elem != nil)
runtime·racewriteobjectpc(cas->sg.elem, c->elemtype, cas->pc, chanrecv);
else if(cas->kind == CaseSend)
runtime·racereadobjectpc(cas->sg.elem, c->elemtype, cas->pc, chansend);
}
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
selunlock(sel);
goto retc;
asyncrecv:
// can receive from buffer
if(raceenabled) {
if(cas->sg.elem != nil)
runtime·racewriteobjectpc(cas->sg.elem, c->elemtype, cas->pc, chanrecv);
runtime·raceacquire(chanbuf(c, c->recvx));
if(c->dataqsiz == 1)
runtime·racerelease(chanbuf(c, c->recvx));
}
if(cas->receivedp != nil)
*cas->receivedp = true;
if(cas->sg.elem != nil)
c->elemtype->alg->copy(c->elemsize, cas->sg.elem, chanbuf(c, c->recvx));
c->elemtype->alg->copy(c->elemsize, chanbuf(c, c->recvx), nil);
if(++c->recvx == c->dataqsiz)
c->recvx = 0;
c->qcount--;
sg = dequeue(&c->sendq);
if(sg != nil) {
gp = sg->g;
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
selunlock(sel);
if(sg->releasetime)
sg->releasetime = runtime·cputicks();
runtime·ready(gp);
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
} else {
selunlock(sel);
}
goto retc;
asyncsend:
// can send to buffer
if(raceenabled) {
if(c->dataqsiz == 1)
runtime·raceacquire(chanbuf(c, c->sendx));
runtime·racerelease(chanbuf(c, c->sendx));
runtime·racereadobjectpc(cas->sg.elem, c->elemtype, cas->pc, chansend);
}
c->elemtype->alg->copy(c->elemsize, chanbuf(c, c->sendx), cas->sg.elem);
if(++c->sendx == c->dataqsiz)
c->sendx = 0;
c->qcount++;
sg = dequeue(&c->recvq);
if(sg != nil) {
gp = sg->g;
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
selunlock(sel);
if(sg->releasetime)
sg->releasetime = runtime·cputicks();
runtime·ready(gp);
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
} else {
selunlock(sel);
}
goto retc;
syncrecv:
// can receive from sleeping sender (sg)
if(raceenabled) {
if(cas->sg.elem != nil)
runtime·racewriteobjectpc(cas->sg.elem, c->elemtype, cas->pc, chanrecv);
racesync(c, sg);
}
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
selunlock(sel);
if(debug)
runtime·printf("syncrecv: sel=%p c=%p o=%d\n", sel, c, o);
if(cas->receivedp != nil)
*cas->receivedp = true;
if(cas->sg.elem != nil)
c->elemtype->alg->copy(c->elemsize, cas->sg.elem, sg->elem);
gp = sg->g;
gp->param = sg;
if(sg->releasetime)
sg->releasetime = runtime·cputicks();
runtime·ready(gp);
goto retc;
rclose:
// read at end of closed channel
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
selunlock(sel);
if(cas->receivedp != nil)
*cas->receivedp = false;
if(cas->sg.elem != nil)
c->elemtype->alg->copy(c->elemsize, cas->sg.elem, nil);
if(raceenabled)
runtime·raceacquire(c);
goto retc;
syncsend:
// can send to sleeping receiver (sg)
if(raceenabled) {
runtime·racereadobjectpc(cas->sg.elem, c->elemtype, cas->pc, chansend);
racesync(c, sg);
}
runtime: improve performance of sync channels 1. SudoG always contains a pointer to the element (thus no variable size, and less copying). 2. chansend/chanrecv allocate SudoG on the stack. 3. Copying of elements and gorotuine notifications are moved out of critical sections. benchmark old ns/op new ns/op delta BenchmarkSelectUncontended 515.00 514.00 -0.19% BenchmarkSelectUncontended-2 291.00 281.00 -3.44% BenchmarkSelectUncontended-4 213.00 189.00 -11.27% BenchmarkSelectUncontended-8 78.30 79.00 +0.89% BenchmarkSelectContended 518.00 514.00 -0.77% BenchmarkSelectContended-2 655.00 631.00 -3.66% BenchmarkSelectContended-4 1026.00 1051.00 +2.44% BenchmarkSelectContended-8 2026.00 2128.00 +5.03% BenchmarkSelectNonblock 175.00 173.00 -1.14% BenchmarkSelectNonblock-2 85.10 87.70 +3.06% BenchmarkSelectNonblock-4 60.10 43.30 -27.95% BenchmarkSelectNonblock-8 37.60 25.50 -32.18% BenchmarkChanUncontended 109.00 114.00 +4.59% BenchmarkChanUncontended-2 54.60 57.20 +4.76% BenchmarkChanUncontended-4 27.40 28.70 +4.74% BenchmarkChanUncontended-8 14.60 15.10 +3.42% BenchmarkChanContended 108.00 114.00 +5.56% BenchmarkChanContended-2 621.00 617.00 -0.64% BenchmarkChanContended-4 759.00 677.00 -10.80% BenchmarkChanContended-8 1635.00 1517.00 -7.22% BenchmarkChanSync 299.00 256.00 -14.38% BenchmarkChanSync-2 5055.00 4624.00 -8.53% BenchmarkChanSync-4 4998.00 4680.00 -6.36% BenchmarkChanSync-8 5019.00 4760.00 -5.16% BenchmarkChanProdCons0 316.00 274.00 -13.29% BenchmarkChanProdCons0-2 1280.00 617.00 -51.80% BenchmarkChanProdCons0-4 2433.00 1332.00 -45.25% BenchmarkChanProdCons0-8 3651.00 1934.00 -47.03% BenchmarkChanProdCons10 153.00 152.00 -0.65% BenchmarkChanProdCons10-2 626.00 581.00 -7.19% BenchmarkChanProdCons10-4 1440.00 1323.00 -8.12% BenchmarkChanProdCons10-8 2036.00 2017.00 -0.93% R=rsc, ken CC=golang-dev https://golang.org/cl/4790042
2011-07-20 09:51:25 -06:00
selunlock(sel);
if(debug)
runtime·printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o);
if(sg->elem != nil)
c->elemtype->alg->copy(c->elemsize, sg->elem, cas->sg.elem);
gp = sg->g;
gp->param = sg;
if(sg->releasetime)
sg->releasetime = runtime·cputicks();
runtime·ready(gp);
retc:
// return pc corresponding to chosen case.
// Set boolean passed during select creation
// (at offset selp + cas->so) to true.
// If cas->so == 0, this is a reflect-driven select and we
// don't need to update the boolean.
pc = cas->pc;
if(cas->so > 0) {
as = (byte*)selp + cas->so;
*as = true;
}
if(cas->sg.releasetime > 0)
runtime·blockevent(cas->sg.releasetime - t0, 2);
runtime·free(sel);
return pc;
sclose:
// send on closed channel
selunlock(sel);
runtime·panicstring("send on closed channel");
return nil; // not reached
}
// This struct must match ../reflect/value.go:/runtimeSelect.
typedef struct runtimeSelect runtimeSelect;
struct runtimeSelect
{
uintptr dir;
ChanType *typ;
Hchan *ch;
byte *val;
};
// This enum must match ../reflect/value.go:/SelectDir.
enum SelectDir {
SelectSend = 1,
SelectRecv,
SelectDefault,
};
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func reflect·rselect(cases Slice) (chosen int, recvOK bool) {
int32 i;
Select *sel;
runtimeSelect* rcase, *rc;
chosen = -1;
recvOK = false;
rcase = (runtimeSelect*)cases.array;
sel = newselect(cases.len);
for(i=0; i<cases.len; i++) {
rc = &rcase[i];
switch(rc->dir) {
case SelectDefault:
selectdefault(sel, (void*)i, 0);
break;
case SelectSend:
if(rc->ch == nil)
break;
selectsend(sel, rc->ch, (void*)i, rc->val, 0);
break;
case SelectRecv:
if(rc->ch == nil)
break;
selectrecv(sel, rc->ch, (void*)i, rc->val, &recvOK, 0);
break;
}
}
chosen = (intgo)(uintptr)selectgo(&sel);
}
static void closechan(Hchan *c, void *pc);
#pragma textflag NOSPLIT
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func closechan(c *Hchan) {
closechan(c, runtime·getcallerpc(&c));
}
#pragma textflag NOSPLIT
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
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);
if(c->closed) {
runtime·unlock(c);
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);
}
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func reflect·chanlen(c *Hchan) (len int) {
reflect: more efficient; cannot Set result of NewValue anymore * Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5. The current reflect uses Set to mean two subtly different things. (1) If you have a reflect.Value v, it might just represent itself (as in v = reflect.NewValue(42)), in which case calling v.Set only changed v, not any other data in the program. (2) If you have a reflect Value v derived from a pointer or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)), v represents the value held there. Changing x[0] affects the value returned by v.Int(), and calling v.Set affects x[0]. This was not really by design; it just happened that way. The motivation for the new reflect implementation was to remove mallocs. The use case (1) has an implicit malloc inside it. If you can do: v := reflect.NewValue(0) v.Set(42) i := v.Int() // i = 42 then that implies that v is referring to some underlying chunk of memory in order to remember the 42; that is, NewValue must have allocated some memory. Almost all the time you are using reflect the goal is to inspect or to change other data, not to manipulate data stored solely inside a reflect.Value. This CL removes use case (1), so that an assignable reflect.Value must always refer to some other piece of data in the program. Put another way, removing this case would make v := reflect.NewValue(0) v.Set(42) as illegal as 0 = 42. It would also make this illegal: x := 0 v := reflect.NewValue(x) v.Set(42) for the same reason. (Note that right now, v.Set(42) "succeeds" but does not change the value of x.) If you really wanted to make v refer to x, you'd start with &x and dereference it: x := 0 v := reflect.NewValue(&x).Elem() // v = *&x v.Set(42) It's pretty rare, except in tests, to want to use NewValue and then call Set to change the Value itself instead of some other piece of data in the program. I haven't seen it happen once yet while making the tree build with this change. For the same reasons, reflect.Zero (formerly reflect.MakeZero) would also return an unassignable, unaddressable value. This invalidates the (awkward) idiom: pv := ... some Ptr Value we have ... v := reflect.Zero(pv.Type().Elem()) pv.PointTo(v) which, when the API changed, turned into: pv := ... some Ptr Value we have ... v := reflect.Zero(pv.Type().Elem()) pv.Set(v.Addr()) In both, it is far from clear what the code is trying to do. Now that it is possible, this CL adds reflect.New(Type) Value that does the obvious thing (same as Go's new), so this code would be replaced by: pv := ... some Ptr Value we have ... pv.Set(reflect.New(pv.Type().Elem())) The changes just described can be confusing to think about, but I believe it is because the old API was confusing - it was conflating two different kinds of Values - and that the new API by itself is pretty simple: you can only Set (or call Addr on) a Value if it actually addresses some real piece of data; that is, only if it is the result of dereferencing a Ptr or indexing a Slice. If you really want the old behavior, you'd get it by translating: v := reflect.NewValue(x) into v := reflect.New(reflect.Typeof(x)).Elem() v.Set(reflect.NewValue(x)) Gofix will not be able to help with this, because whether and how to change the code depends on whether the original code meant use (1) or use (2), so the developer has to read and think about the code. You can see the effect on packages in the tree in https://golang.org/cl/4423043/. R=r CC=golang-dev https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
if(c == nil)
len = 0;
else
len = c->qcount;
}
runtime: use goc2c as much as possible Package runtime's C functions written to be called from Go started out written in C using carefully constructed argument lists and the FLUSH macro to write a result back to memory. For some functions, the appropriate parameter list ended up being architecture-dependent due to differences in alignment, so we added 'goc2c', which takes a .goc file containing Go func declarations but C bodies, rewrites the Go func declaration to equivalent C declarations for the target architecture, adds the needed FLUSH statements, and writes out an equivalent C file. That C file is compiled as part of package runtime. Native Client's x86-64 support introduces the most complex alignment rules yet, breaking many functions that could until now be portably written in C. Using goc2c for those avoids the breakage. Separately, Keith's work on emitting stack information from the C compiler would require the hand-written functions to add #pragmas specifying how many arguments are result parameters. Using goc2c for those avoids maintaining #pragmas. For both reasons, use goc2c for as many Go-called C functions as possible. This CL is a replay of the bulk of CL 15400047 and CL 15790043, both of which were reviewed as part of the NaCl port and are checked in to the NaCl branch. This CL is part of bringing the NaCl code into the main tree. No new code here, just reformatting and occasional movement into .h files. LGTM=r R=dave, alex.brainman, r CC=golang-codereviews https://golang.org/cl/65220044
2014-02-20 13:58:47 -07:00
func reflect·chancap(c *Hchan) (cap int) {
reflect: more efficient; cannot Set result of NewValue anymore * Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5. The current reflect uses Set to mean two subtly different things. (1) If you have a reflect.Value v, it might just represent itself (as in v = reflect.NewValue(42)), in which case calling v.Set only changed v, not any other data in the program. (2) If you have a reflect Value v derived from a pointer or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)), v represents the value held there. Changing x[0] affects the value returned by v.Int(), and calling v.Set affects x[0]. This was not really by design; it just happened that way. The motivation for the new reflect implementation was to remove mallocs. The use case (1) has an implicit malloc inside it. If you can do: v := reflect.NewValue(0) v.Set(42) i := v.Int() // i = 42 then that implies that v is referring to some underlying chunk of memory in order to remember the 42; that is, NewValue must have allocated some memory. Almost all the time you are using reflect the goal is to inspect or to change other data, not to manipulate data stored solely inside a reflect.Value. This CL removes use case (1), so that an assignable reflect.Value must always refer to some other piece of data in the program. Put another way, removing this case would make v := reflect.NewValue(0) v.Set(42) as illegal as 0 = 42. It would also make this illegal: x := 0 v := reflect.NewValue(x) v.Set(42) for the same reason. (Note that right now, v.Set(42) "succeeds" but does not change the value of x.) If you really wanted to make v refer to x, you'd start with &x and dereference it: x := 0 v := reflect.NewValue(&x).Elem() // v = *&x v.Set(42) It's pretty rare, except in tests, to want to use NewValue and then call Set to change the Value itself instead of some other piece of data in the program. I haven't seen it happen once yet while making the tree build with this change. For the same reasons, reflect.Zero (formerly reflect.MakeZero) would also return an unassignable, unaddressable value. This invalidates the (awkward) idiom: pv := ... some Ptr Value we have ... v := reflect.Zero(pv.Type().Elem()) pv.PointTo(v) which, when the API changed, turned into: pv := ... some Ptr Value we have ... v := reflect.Zero(pv.Type().Elem()) pv.Set(v.Addr()) In both, it is far from clear what the code is trying to do. Now that it is possible, this CL adds reflect.New(Type) Value that does the obvious thing (same as Go's new), so this code would be replaced by: pv := ... some Ptr Value we have ... pv.Set(reflect.New(pv.Type().Elem())) The changes just described can be confusing to think about, but I believe it is because the old API was confusing - it was conflating two different kinds of Values - and that the new API by itself is pretty simple: you can only Set (or call Addr on) a Value if it actually addresses some real piece of data; that is, only if it is the result of dereferencing a Ptr or indexing a Slice. If you really want the old behavior, you'd get it by translating: v := reflect.NewValue(x) into v := reflect.New(reflect.Typeof(x)).Elem() v.Set(reflect.NewValue(x)) Gofix will not be able to help with this, because whether and how to change the code depends on whether the original code meant use (1) or use (2), so the developer has to read and think about the code. You can see the effect on packages in the tree in https://golang.org/cl/4423043/. R=r CC=golang-dev https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
if(c == nil)
cap = 0;
else
cap = c->dataqsiz;
}
static SudoG*
dequeue(WaitQ *q)
{
SudoG *sgp;
loop:
sgp = q->first;
if(sgp == nil)
return nil;
q->first = sgp->link;
// if sgp participates in a select and is already signaled, ignore it
if(sgp->selectdone != nil) {
// claim the right to signal
if(*sgp->selectdone != 0 || !runtime·cas(sgp->selectdone, 0, 1))
goto loop;
}
return sgp;
}
static void
dequeueg(WaitQ *q)
{
SudoG **l, *sgp, *prevsgp;
prevsgp = nil;
for(l=&q->first; (sgp=*l) != nil; l=&sgp->link, prevsgp=sgp) {
if(sgp->g == g) {
*l = sgp->link;
if(q->last == sgp)
q->last = prevsgp;
break;
}
}
}
static void
enqueue(WaitQ *q, SudoG *sgp)
{
sgp->link = nil;
if(q->first == nil) {
q->first = sgp;
q->last = sgp;
return;
}
q->last->link = sgp;
q->last = sgp;
}
static void
racesync(Hchan *c, SudoG *sg)
{
runtime·racerelease(chanbuf(c, 0));
runtime·raceacquireg(sg->g, chanbuf(c, 0));
runtime·racereleaseg(sg->g, chanbuf(c, 0));
runtime·raceacquire(chanbuf(c, 0));
}