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.
|
|
|
|
|
|
|
|
#include "runtime.h"
|
2012-09-24 12:58:34 -06:00
|
|
|
#include "arch_GOARCH.h"
|
2009-09-08 14:46:54 -06:00
|
|
|
#include "type.h"
|
2012-10-07 12:05:32 -06:00
|
|
|
#include "race.h"
|
2012-09-24 12:58:34 -06:00
|
|
|
#include "malloc.h"
|
2008-07-13 15:29:46 -06:00
|
|
|
|
2011-03-22 19:41:17 -06:00
|
|
|
#define MAXALIGN 7
|
2011-07-20 12:28:55 -06:00
|
|
|
#define NOSELGEN 1
|
2011-03-22 19:41:17 -06:00
|
|
|
|
2008-07-14 15:33:39 -06:00
|
|
|
static int32 debug = 0;
|
2008-07-13 15:29:46 -06:00
|
|
|
|
2008-07-20 21:13:07 -06:00
|
|
|
typedef struct WaitQ WaitQ;
|
|
|
|
typedef struct SudoG SudoG;
|
2008-07-24 16:57:30 -06:00
|
|
|
typedef struct Select Select;
|
|
|
|
typedef struct Scase Scase;
|
2008-07-20 21:13:07 -06:00
|
|
|
|
|
|
|
struct SudoG
|
|
|
|
{
|
|
|
|
G* g; // g and selgen constitute
|
2009-12-18 13:25:53 -07:00
|
|
|
uint32 selgen; // a weak pointer to g
|
2008-07-20 21:13:07 -06:00
|
|
|
SudoG* link;
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 02:56:04 -06:00
|
|
|
int64 releasetime;
|
2011-07-20 09:51:25 -06:00
|
|
|
byte* elem; // data element
|
2008-07-20 21:13:07 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
struct WaitQ
|
|
|
|
{
|
|
|
|
SudoG* first;
|
|
|
|
SudoG* last;
|
|
|
|
};
|
2008-07-13 15:29:46 -06:00
|
|
|
|
|
|
|
struct Hchan
|
|
|
|
{
|
2012-09-24 12:58:34 -06:00
|
|
|
uintgo qcount; // total data in the q
|
|
|
|
uintgo dataqsiz; // size of the circular q
|
2009-03-12 18:55:11 -06:00
|
|
|
uint16 elemsize;
|
2011-03-11 12:47:26 -07:00
|
|
|
bool closed;
|
2009-09-08 14:46:54 -06:00
|
|
|
uint8 elemalign;
|
2008-07-14 15:33:39 -06:00
|
|
|
Alg* elemalg; // interface for element type
|
2012-09-24 12:58:34 -06:00
|
|
|
uintgo sendx; // send index
|
|
|
|
uintgo recvx; // receive index
|
2008-07-14 15:33:39 -06:00
|
|
|
WaitQ recvq; // list of recv waiters
|
|
|
|
WaitQ sendq; // list of send waiters
|
2009-12-04 11:57:01 -07:00
|
|
|
Lock;
|
2008-07-14 15:33:39 -06:00
|
|
|
};
|
|
|
|
|
2011-04-13 21:42:06 -06:00
|
|
|
// Buffer follows Hchan immediately in memory.
|
|
|
|
// chanbuf(c, i) is pointer to the i'th slot in the buffer.
|
|
|
|
#define chanbuf(c, i) ((byte*)((c)+1)+(uintptr)(c)->elemsize*(i))
|
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
// Scase.kind
|
|
|
|
CaseRecv,
|
|
|
|
CaseSend,
|
|
|
|
CaseDefault,
|
|
|
|
};
|
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
struct Scase
|
|
|
|
{
|
2011-07-21 11:57:13 -06:00
|
|
|
SudoG sg; // must be first member (cast to Scase)
|
2008-07-24 16:57:30 -06:00
|
|
|
Hchan* chan; // chan
|
|
|
|
byte* pc; // return pc
|
2011-03-11 12:47:26 -07:00
|
|
|
uint16 kind;
|
2008-07-24 16:57:30 -06:00
|
|
|
uint16 so; // vararg of selected bool
|
2011-07-21 11:57:13 -06:00
|
|
|
bool* receivedp; // pointer to received bool (recv2)
|
2008-07-24 16:57:30 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Select
|
|
|
|
{
|
|
|
|
uint16 tcase; // total count of scase[]
|
|
|
|
uint16 ncase; // currently filled scase[]
|
2011-07-21 11:57:13 -06:00
|
|
|
uint16* pollorder; // case poll order
|
|
|
|
Hchan** lockorder; // channel lock order
|
|
|
|
Scase scase[1]; // one per case (in order of appearance)
|
2008-07-24 16:57:30 -06:00
|
|
|
};
|
|
|
|
|
2011-07-21 11:57:13 -06:00
|
|
|
static void dequeueg(WaitQ*);
|
|
|
|
static SudoG* dequeue(WaitQ*);
|
2008-07-24 16:57:30 -06:00
|
|
|
static void enqueue(WaitQ*, SudoG*);
|
2010-02-08 22:41:54 -07:00
|
|
|
static void destroychan(Hchan*);
|
2012-10-07 12:05:32 -06:00
|
|
|
static void racesync(Hchan*, SudoG*);
|
2008-07-20 21:13:07 -06:00
|
|
|
|
2009-07-08 16:00:54 -06:00
|
|
|
Hchan*
|
2011-08-17 13:54:17 -06:00
|
|
|
runtime·makechan_c(ChanType *t, int64 hint)
|
2008-07-13 15:29:46 -06:00
|
|
|
{
|
|
|
|
Hchan *c;
|
2012-09-24 12:58:34 -06:00
|
|
|
uintptr n;
|
2011-08-17 13:54:17 -06:00
|
|
|
Type *elem;
|
2012-05-29 12:02:29 -06:00
|
|
|
|
2011-08-17 13:54:17 -06:00
|
|
|
elem = t->elem;
|
2008-07-13 15:29:46 -06:00
|
|
|
|
2012-09-24 12:58:34 -06:00
|
|
|
// compiler checks this but be safe.
|
|
|
|
if(elem->size >= (1<<16))
|
|
|
|
runtime·throw("makechan: invalid channel element type");
|
|
|
|
|
|
|
|
if(hint < 0 || (intgo)hint != hint || (elem->size > 0 && hint > MaxMem / elem->size))
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·panicstring("makechan: size out of range");
|
2010-05-01 14:15:42 -06:00
|
|
|
|
2011-04-13 21:42:06 -06:00
|
|
|
// calculate rounded size of Hchan
|
2011-03-22 19:41:17 -06:00
|
|
|
n = sizeof(*c);
|
|
|
|
while(n & MAXALIGN)
|
|
|
|
n++;
|
|
|
|
|
|
|
|
// allocate memory in one call
|
2011-08-04 06:31:03 -06:00
|
|
|
c = (Hchan*)runtime·mal(n + hint*elem->size);
|
2009-09-08 14:46:54 -06:00
|
|
|
c->elemsize = elem->size;
|
2011-12-05 07:40:22 -07:00
|
|
|
c->elemalg = elem->alg;
|
2009-09-08 14:46:54 -06:00
|
|
|
c->elemalign = elem->align;
|
2011-04-13 21:42:06 -06:00
|
|
|
c->dataqsiz = hint;
|
2008-07-13 15:29:46 -06:00
|
|
|
|
2010-04-01 12:56:18 -06:00
|
|
|
if(debug)
|
2012-09-24 12:58:34 -06:00
|
|
|
runtime·printf("makechan: chan=%p; elemsize=%D; elemalg=%p; elemalign=%d; dataqsiz=%D\n",
|
|
|
|
c, (int64)elem->size, elem->alg, elem->align, (int64)c->dataqsiz);
|
2009-07-08 16:00:54 -06:00
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
// For reflect
|
2012-09-24 12:58:34 -06:00
|
|
|
// func makechan(typ *ChanType, size uint64) (chan)
|
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
|
|
|
void
|
2012-09-24 12:58:34 -06:00
|
|
|
reflect·makechan(ChanType *t, uint64 size, Hchan *c)
|
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
|
|
|
{
|
2011-08-17 13:54:17 -06:00
|
|
|
c = runtime·makechan_c(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
|
|
|
FLUSH(&c);
|
|
|
|
}
|
|
|
|
|
2011-08-17 13:54:17 -06:00
|
|
|
// makechan(t *ChanType, hint int64) (hchan *chan any);
|
2009-07-08 16:00:54 -06:00
|
|
|
void
|
2011-08-17 13:54:17 -06:00
|
|
|
runtime·makechan(ChanType *t, int64 hint, Hchan *ret)
|
2009-07-08 16:00:54 -06:00
|
|
|
{
|
2011-08-17 13:54:17 -06:00
|
|
|
ret = runtime·makechan_c(t, hint);
|
2009-07-08 16:00:54 -06:00
|
|
|
FLUSH(&ret);
|
2008-07-13 15:29:46 -06:00
|
|
|
}
|
|
|
|
|
2008-07-26 15:21:21 -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
|
2010-04-01 12:56:18 -06:00
|
|
|
* 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.
|
2008-07-26 15:21:21 -06:00
|
|
|
*/
|
2008-07-13 15:29:46 -06:00
|
|
|
void
|
2012-10-07 12:05:32 -06:00
|
|
|
runtime·chansend(ChanType *t, Hchan *c, byte *ep, bool *pres, void *pc)
|
2008-07-13 15:29:46 -06:00
|
|
|
{
|
2008-07-26 15:21:21 -06:00
|
|
|
SudoG *sg;
|
2011-07-20 09:51:25 -06:00
|
|
|
SudoG mysg;
|
2008-07-26 15:21:21 -06:00
|
|
|
G* gp;
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 02:56:04 -06:00
|
|
|
int64 t0;
|
2008-07-13 15:29:46 -06:00
|
|
|
|
2011-08-17 13:54:17 -06:00
|
|
|
if(c == nil) {
|
|
|
|
USED(t);
|
|
|
|
if(pres != nil) {
|
|
|
|
*pres = false;
|
|
|
|
return;
|
|
|
|
}
|
2012-09-18 11:15:46 -06:00
|
|
|
runtime·park(nil, nil, "chan send (nil chan)");
|
2011-08-17 13:54:17 -06:00
|
|
|
return; // not reached
|
|
|
|
}
|
2010-07-13 18:27:26 -06:00
|
|
|
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
if(runtime·gcwaiting)
|
|
|
|
runtime·gosched();
|
2010-01-09 10:47:45 -07:00
|
|
|
|
2008-07-13 15:29:46 -06:00
|
|
|
if(debug) {
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·printf("chansend: chan=%p; elem=", c);
|
2008-07-26 15:21:21 -06:00
|
|
|
c->elemalg->print(c->elemsize, ep);
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·prints("\n");
|
2008-07-13 15:29:46 -06:00
|
|
|
}
|
2008-07-26 15:21:21 -06:00
|
|
|
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 02:56:04 -06:00
|
|
|
t0 = 0;
|
|
|
|
mysg.releasetime = 0;
|
|
|
|
if(runtime·blockprofilerate > 0) {
|
|
|
|
t0 = runtime·cputicks();
|
|
|
|
mysg.releasetime = -1;
|
|
|
|
}
|
|
|
|
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·lock(c);
|
2012-10-07 12:05:32 -06:00
|
|
|
// TODO(dvyukov): add similar instrumentation to select.
|
|
|
|
if(raceenabled)
|
2012-11-29 23:29:41 -07:00
|
|
|
runtime·racereadpc(c, pc, runtime·chansend);
|
2011-03-11 12:47:26 -07:00
|
|
|
if(c->closed)
|
2009-03-23 19:50:35 -06:00
|
|
|
goto closed;
|
2009-03-13 17:47:54 -06:00
|
|
|
|
2008-07-14 15:33:39 -06:00
|
|
|
if(c->dataqsiz > 0)
|
|
|
|
goto asynch;
|
|
|
|
|
2011-07-21 11:57:13 -06:00
|
|
|
sg = dequeue(&c->recvq);
|
2008-07-26 15:21:21 -06:00
|
|
|
if(sg != nil) {
|
2012-10-07 12:05:32 -06:00
|
|
|
if(raceenabled)
|
|
|
|
racesync(c, sg);
|
2011-07-20 09:51:25 -06:00
|
|
|
runtime·unlock(c);
|
2012-05-29 12:02:29 -06:00
|
|
|
|
2008-07-26 15:21:21 -06:00
|
|
|
gp = sg->g;
|
|
|
|
gp->param = sg;
|
2011-07-20 09:51:25 -06:00
|
|
|
if(sg->elem != nil)
|
|
|
|
c->elemalg->copy(c->elemsize, sg->elem, ep);
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 02:56:04 -06:00
|
|
|
if(sg->releasetime)
|
|
|
|
sg->releasetime = runtime·cputicks();
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·ready(gp);
|
2008-07-26 15:21:21 -06:00
|
|
|
|
|
|
|
if(pres != nil)
|
|
|
|
*pres = true;
|
2008-07-14 15:33:39 -06:00
|
|
|
return;
|
|
|
|
}
|
2008-07-20 21:13:07 -06:00
|
|
|
|
2008-07-26 15:21:21 -06:00
|
|
|
if(pres != nil) {
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·unlock(c);
|
2008-07-26 15:21:21 -06:00
|
|
|
*pres = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-07-20 09:51:25 -06:00
|
|
|
mysg.elem = ep;
|
|
|
|
mysg.g = g;
|
2011-07-20 12:28:55 -06:00
|
|
|
mysg.selgen = NOSELGEN;
|
2008-07-26 15:21:21 -06:00
|
|
|
g->param = nil;
|
2011-07-20 09:51:25 -06:00
|
|
|
enqueue(&c->sendq, &mysg);
|
2012-09-18 11:15:46 -06:00
|
|
|
runtime·park(runtime·unlock, c, "chan send");
|
2008-07-26 15:21:21 -06:00
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 02:56:04 -06:00
|
|
|
if(mysg.releasetime > 0)
|
|
|
|
runtime·blockevent(mysg.releasetime - t0, 2);
|
|
|
|
|
2008-07-14 15:33:39 -06:00
|
|
|
return;
|
|
|
|
|
|
|
|
asynch:
|
2011-03-11 12:47:26 -07:00
|
|
|
if(c->closed)
|
2009-03-13 17:47:54 -06:00
|
|
|
goto closed;
|
|
|
|
|
|
|
|
if(c->qcount >= c->dataqsiz) {
|
2008-09-26 12:47:04 -06:00
|
|
|
if(pres != nil) {
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·unlock(c);
|
2008-09-26 12:47:04 -06:00
|
|
|
*pres = false;
|
|
|
|
return;
|
|
|
|
}
|
2011-07-20 09:51:25 -06:00
|
|
|
mysg.g = g;
|
|
|
|
mysg.elem = nil;
|
2011-07-20 12:28:55 -06:00
|
|
|
mysg.selgen = NOSELGEN;
|
2011-07-20 09:51:25 -06:00
|
|
|
enqueue(&c->sendq, &mysg);
|
2012-09-18 11:15:46 -06:00
|
|
|
runtime·park(runtime·unlock, c, "chan send");
|
2008-09-19 21:43:30 -06:00
|
|
|
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·lock(c);
|
2009-03-13 17:47:54 -06:00
|
|
|
goto asynch;
|
2008-07-14 18:41:38 -06:00
|
|
|
}
|
2012-10-07 12:05:32 -06:00
|
|
|
|
|
|
|
if(raceenabled)
|
|
|
|
runtime·racerelease(chanbuf(c, c->sendx));
|
|
|
|
|
2011-07-20 09:51:25 -06:00
|
|
|
c->elemalg->copy(c->elemsize, chanbuf(c, c->sendx), ep);
|
2011-04-13 21:42:06 -06:00
|
|
|
if(++c->sendx == c->dataqsiz)
|
|
|
|
c->sendx = 0;
|
2008-07-14 18:41:38 -06:00
|
|
|
c->qcount++;
|
2008-07-26 15:21:21 -06:00
|
|
|
|
2011-07-21 11:57:13 -06:00
|
|
|
sg = dequeue(&c->recvq);
|
2008-07-26 15:21:21 -06:00
|
|
|
if(sg != nil) {
|
|
|
|
gp = sg->g;
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·unlock(c);
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 02:56:04 -06:00
|
|
|
if(sg->releasetime)
|
|
|
|
sg->releasetime = runtime·cputicks();
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·ready(gp);
|
2008-09-19 21:43:30 -06:00
|
|
|
} else
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·unlock(c);
|
2008-09-26 12:47:04 -06:00
|
|
|
if(pres != nil)
|
|
|
|
*pres = true;
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 02:56:04 -06:00
|
|
|
if(mysg.releasetime > 0)
|
|
|
|
runtime·blockevent(mysg.releasetime - t0, 2);
|
2009-03-13 17:47:54 -06:00
|
|
|
return;
|
|
|
|
|
|
|
|
closed:
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·unlock(c);
|
spec, runtime, tests: send on closed channel panics
Close of closed channel panics.
Receive from closed channel never panics,
even if done repeatedly.
Fixes #1349.
Fixes #1419.
R=gri, iant, ken2, r, gri1, r2, iant2, rog, albert.strasheim, niemeyer, ejsherry
CC=golang-dev
https://golang.org/cl/3989042
2011-01-21 13:07:13 -07:00
|
|
|
runtime·panicstring("send on closed channel");
|
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
|
|
|
|
2009-07-08 16:00:54 -06:00
|
|
|
void
|
2011-08-17 13:54:17 -06:00
|
|
|
runtime·chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *received)
|
2008-07-15 22:07:59 -06:00
|
|
|
{
|
2008-07-26 15:21:21 -06:00
|
|
|
SudoG *sg;
|
2011-07-20 09:51:25 -06:00
|
|
|
SudoG mysg;
|
2008-07-26 15:21:21 -06:00
|
|
|
G *gp;
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 02:56:04 -06:00
|
|
|
int64 t0;
|
2008-07-16 12:46:33 -06:00
|
|
|
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
if(runtime·gcwaiting)
|
|
|
|
runtime·gosched();
|
2010-01-09 10:47:45 -07:00
|
|
|
|
2010-04-01 12:56:18 -06:00
|
|
|
if(debug)
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·printf("chanrecv: chan=%p\n", c);
|
2008-07-26 15:21:21 -06:00
|
|
|
|
2011-08-17 13:54:17 -06:00
|
|
|
if(c == nil) {
|
|
|
|
USED(t);
|
|
|
|
if(selected != nil) {
|
|
|
|
*selected = false;
|
|
|
|
return;
|
|
|
|
}
|
2012-09-18 11:15:46 -06:00
|
|
|
runtime·park(nil, nil, "chan receive (nil chan)");
|
2011-08-17 13:54:17 -06:00
|
|
|
return; // not reached
|
|
|
|
}
|
|
|
|
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 02:56:04 -06:00
|
|
|
t0 = 0;
|
|
|
|
mysg.releasetime = 0;
|
|
|
|
if(runtime·blockprofilerate > 0) {
|
|
|
|
t0 = runtime·cputicks();
|
|
|
|
mysg.releasetime = -1;
|
|
|
|
}
|
|
|
|
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·lock(c);
|
2008-07-15 22:07:59 -06:00
|
|
|
if(c->dataqsiz > 0)
|
|
|
|
goto asynch;
|
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
if(c->closed)
|
2009-03-13 17:47:54 -06:00
|
|
|
goto closed;
|
|
|
|
|
2011-07-21 11:57:13 -06:00
|
|
|
sg = dequeue(&c->sendq);
|
2008-07-26 15:21:21 -06:00
|
|
|
if(sg != nil) {
|
2012-10-07 12:05:32 -06:00
|
|
|
if(raceenabled)
|
|
|
|
racesync(c, sg);
|
2011-07-20 09:51:25 -06:00
|
|
|
runtime·unlock(c);
|
|
|
|
|
2011-01-30 14:07:57 -07:00
|
|
|
if(ep != nil)
|
|
|
|
c->elemalg->copy(c->elemsize, ep, sg->elem);
|
2008-07-26 15:21:21 -06:00
|
|
|
gp = sg->g;
|
|
|
|
gp->param = sg;
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 02:56:04 -06:00
|
|
|
if(sg->releasetime)
|
|
|
|
sg->releasetime = runtime·cputicks();
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·ready(gp);
|
2008-07-15 22:07:59 -06:00
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
if(selected != nil)
|
|
|
|
*selected = true;
|
|
|
|
if(received != nil)
|
|
|
|
*received = true;
|
2008-07-15 22:07:59 -06:00
|
|
|
return;
|
|
|
|
}
|
2008-07-24 16:57:30 -06:00
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
if(selected != nil) {
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·unlock(c);
|
2011-03-11 12:47:26 -07:00
|
|
|
*selected = false;
|
2008-07-14 15:33:39 -06:00
|
|
|
return;
|
|
|
|
}
|
2008-08-05 15:21:42 -06:00
|
|
|
|
2011-07-20 09:51:25 -06:00
|
|
|
mysg.elem = ep;
|
|
|
|
mysg.g = g;
|
2011-07-20 12:28:55 -06:00
|
|
|
mysg.selgen = NOSELGEN;
|
2008-07-26 15:21:21 -06:00
|
|
|
g->param = nil;
|
2011-07-20 09:51:25 -06:00
|
|
|
enqueue(&c->recvq, &mysg);
|
2012-09-18 11:15:46 -06:00
|
|
|
runtime·park(runtime·unlock, c, "chan receive");
|
2008-07-26 15:21:21 -06:00
|
|
|
|
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;
|
|
|
|
}
|
2009-03-13 17:47:54 -06:00
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
if(received != nil)
|
|
|
|
*received = true;
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 02:56:04 -06:00
|
|
|
if(mysg.releasetime > 0)
|
|
|
|
runtime·blockevent(mysg.releasetime - t0, 2);
|
2008-07-14 15:33:39 -06:00
|
|
|
return;
|
|
|
|
|
|
|
|
asynch:
|
2009-03-13 17:47:54 -06:00
|
|
|
if(c->qcount <= 0) {
|
2011-03-11 12:47:26 -07:00
|
|
|
if(c->closed)
|
2009-03-13 17:47:54 -06:00
|
|
|
goto closed;
|
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
if(selected != nil) {
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·unlock(c);
|
2011-03-11 12:47:26 -07:00
|
|
|
*selected = false;
|
2011-03-25 11:36:22 -06:00
|
|
|
if(received != nil)
|
|
|
|
*received = false;
|
2008-09-26 12:47:04 -06:00
|
|
|
return;
|
|
|
|
}
|
2011-07-20 09:51:25 -06:00
|
|
|
mysg.g = g;
|
|
|
|
mysg.elem = nil;
|
2011-07-20 12:28:55 -06:00
|
|
|
mysg.selgen = NOSELGEN;
|
2011-07-20 09:51:25 -06:00
|
|
|
enqueue(&c->recvq, &mysg);
|
2012-09-18 11:15:46 -06:00
|
|
|
runtime·park(runtime·unlock, c, "chan receive");
|
2009-03-13 17:47:54 -06:00
|
|
|
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·lock(c);
|
2009-03-13 17:47:54 -06:00
|
|
|
goto asynch;
|
2008-07-14 18:41:38 -06:00
|
|
|
}
|
2012-10-07 12:05:32 -06:00
|
|
|
|
|
|
|
if(raceenabled)
|
|
|
|
runtime·raceacquire(chanbuf(c, c->recvx));
|
|
|
|
|
2011-01-30 14:07:57 -07:00
|
|
|
if(ep != nil)
|
2011-04-13 21:42:06 -06:00
|
|
|
c->elemalg->copy(c->elemsize, ep, chanbuf(c, c->recvx));
|
|
|
|
c->elemalg->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--;
|
2011-07-20 09:51:25 -06:00
|
|
|
|
2011-07-21 11:57:13 -06:00
|
|
|
sg = dequeue(&c->sendq);
|
2008-07-26 15:21:21 -06:00
|
|
|
if(sg != nil) {
|
|
|
|
gp = sg->g;
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·unlock(c);
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 02:56:04 -06:00
|
|
|
if(sg->releasetime)
|
|
|
|
sg->releasetime = runtime·cputicks();
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·ready(gp);
|
2011-03-11 12:47:26 -07:00
|
|
|
} else
|
|
|
|
runtime·unlock(c);
|
2009-03-13 17:47:54 -06:00
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
if(selected != nil)
|
|
|
|
*selected = true;
|
|
|
|
if(received != nil)
|
|
|
|
*received = true;
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 02:56:04 -06:00
|
|
|
if(mysg.releasetime > 0)
|
|
|
|
runtime·blockevent(mysg.releasetime - t0, 2);
|
2009-03-13 17:47:54 -06:00
|
|
|
return;
|
|
|
|
|
|
|
|
closed:
|
2011-01-30 14:07:57 -07:00
|
|
|
if(ep != nil)
|
|
|
|
c->elemalg->copy(c->elemsize, ep, nil);
|
2011-03-11 12:47:26 -07:00
|
|
|
if(selected != nil)
|
|
|
|
*selected = true;
|
|
|
|
if(received != nil)
|
|
|
|
*received = false;
|
2012-10-07 12:05:32 -06:00
|
|
|
if(raceenabled)
|
|
|
|
runtime·raceacquire(c);
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·unlock(c);
|
pprof: add goroutine blocking profiling
The profiler collects goroutine blocking information similar to Google Perf Tools.
You may see an example of the profile (converted to svg) attached to
http://code.google.com/p/go/issues/detail?id=3946
The public API changes are:
+pkg runtime, func BlockProfile([]BlockProfileRecord) (int, bool)
+pkg runtime, func SetBlockProfileRate(int)
+pkg runtime, method (*BlockProfileRecord) Stack() []uintptr
+pkg runtime, type BlockProfileRecord struct
+pkg runtime, type BlockProfileRecord struct, Count int64
+pkg runtime, type BlockProfileRecord struct, Cycles int64
+pkg runtime, type BlockProfileRecord struct, embedded StackRecord
R=rsc, dave, minux.ma, r
CC=gobot, golang-dev, r, remyoudompheng
https://golang.org/cl/6443115
2012-10-06 02:56:04 -06:00
|
|
|
if(mysg.releasetime > 0)
|
|
|
|
runtime·blockevent(mysg.releasetime - t0, 2);
|
2008-07-13 17:20:27 -06:00
|
|
|
}
|
|
|
|
|
2008-07-26 15:21:21 -06:00
|
|
|
// chansend1(hchan *chan any, elem any);
|
2010-03-04 16:34:25 -07:00
|
|
|
#pragma textflag 7
|
2008-07-13 17:20:27 -06:00
|
|
|
void
|
2011-08-17 13:54:17 -06:00
|
|
|
runtime·chansend1(ChanType *t, Hchan* c, ...)
|
2008-07-26 15:21:21 -06:00
|
|
|
{
|
2012-10-07 12:05:32 -06:00
|
|
|
runtime·chansend(t, c, (byte*)(&c+1), nil, runtime·getcallerpc(&t));
|
2008-07-26 15:21:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// chanrecv1(hchan *chan any) (elem any);
|
2010-03-04 16:34:25 -07:00
|
|
|
#pragma textflag 7
|
2008-07-26 15:21:21 -06:00
|
|
|
void
|
2011-08-17 13:54:17 -06:00
|
|
|
runtime·chanrecv1(ChanType *t, Hchan* c, ...)
|
2008-07-26 15:21:21 -06:00
|
|
|
{
|
2011-08-17 13:54:17 -06:00
|
|
|
runtime·chanrecv(t, c, (byte*)(&c+1), nil, nil);
|
2008-07-26 15:21:21 -06:00
|
|
|
}
|
2008-07-14 15:33:39 -06:00
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
// chanrecv2(hchan *chan any) (elem any, received bool);
|
2011-01-18 13:59:19 -07:00
|
|
|
#pragma textflag 7
|
|
|
|
void
|
2011-08-17 13:54:17 -06:00
|
|
|
runtime·chanrecv2(ChanType *t, Hchan* c, ...)
|
2011-01-18 13:59:19 -07:00
|
|
|
{
|
2011-08-17 13:54:17 -06:00
|
|
|
byte *ae, *ap;
|
2011-01-18 13:59:19 -07:00
|
|
|
|
2011-08-17 13:54:17 -06:00
|
|
|
ae = (byte*)(&c+1);
|
|
|
|
ap = ae + t->elem->size;
|
|
|
|
runtime·chanrecv(t, c, ae, nil, ap);
|
2008-07-26 15:21:21 -06:00
|
|
|
}
|
|
|
|
|
2011-01-30 14:07:57 -07:00
|
|
|
// func selectnbsend(c chan any, elem any) bool
|
|
|
|
//
|
|
|
|
// compiler implements
|
|
|
|
//
|
|
|
|
// select {
|
|
|
|
// case c <- v:
|
|
|
|
// ... foo
|
|
|
|
// default:
|
|
|
|
// ... bar
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// as
|
|
|
|
//
|
2011-08-17 13:54:17 -06:00
|
|
|
// if selectnbsend(c, v) {
|
2011-01-30 14:07:57 -07:00
|
|
|
// ... foo
|
|
|
|
// } else {
|
|
|
|
// ... bar
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
#pragma textflag 7
|
|
|
|
void
|
2011-08-17 13:54:17 -06:00
|
|
|
runtime·selectnbsend(ChanType *t, Hchan *c, ...)
|
2011-01-30 14:07:57 -07:00
|
|
|
{
|
|
|
|
byte *ae, *ap;
|
|
|
|
|
2011-08-17 13:54:17 -06:00
|
|
|
ae = (byte*)(&c + 1);
|
2012-05-29 12:02:29 -06:00
|
|
|
ap = ae + ROUND(t->elem->size, Structrnd);
|
2012-10-07 12:05:32 -06:00
|
|
|
runtime·chansend(t, c, ae, ap, runtime·getcallerpc(&t));
|
2011-01-30 14:07:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// func selectnbrecv(elem *any, c chan any) bool
|
|
|
|
//
|
|
|
|
// compiler implements
|
|
|
|
//
|
|
|
|
// select {
|
|
|
|
// case v = <-c:
|
|
|
|
// ... foo
|
|
|
|
// default:
|
|
|
|
// ... bar
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// as
|
|
|
|
//
|
2011-08-17 13:54:17 -06:00
|
|
|
// if selectnbrecv(&v, c) {
|
2011-01-30 14:07:57 -07:00
|
|
|
// ... foo
|
|
|
|
// } else {
|
|
|
|
// ... bar
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
#pragma textflag 7
|
|
|
|
void
|
2011-08-17 13:54:17 -06:00
|
|
|
runtime·selectnbrecv(ChanType *t, byte *v, Hchan *c, bool selected)
|
2011-01-30 14:07:57 -07:00
|
|
|
{
|
2011-08-17 13:54:17 -06:00
|
|
|
runtime·chanrecv(t, c, v, &selected, nil);
|
2012-05-29 12:02:29 -06:00
|
|
|
}
|
2011-03-11 12:47:26 -07:00
|
|
|
|
|
|
|
// func selectnbrecv2(elem *any, ok *bool, c chan any) bool
|
|
|
|
//
|
|
|
|
// compiler implements
|
|
|
|
//
|
|
|
|
// select {
|
2011-03-25 11:36:22 -06:00
|
|
|
// case v, ok = <-c:
|
2011-03-11 12:47:26 -07:00
|
|
|
// ... foo
|
|
|
|
// default:
|
|
|
|
// ... bar
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// as
|
|
|
|
//
|
2011-03-25 11:36:22 -06:00
|
|
|
// if c != nil && selectnbrecv2(&v, &ok, c) {
|
2011-03-11 12:47:26 -07:00
|
|
|
// ... foo
|
|
|
|
// } else {
|
|
|
|
// ... bar
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
#pragma textflag 7
|
|
|
|
void
|
2011-08-17 13:54:17 -06:00
|
|
|
runtime·selectnbrecv2(ChanType *t, byte *v, bool *received, Hchan *c, bool selected)
|
2011-03-11 12:47:26 -07:00
|
|
|
{
|
2011-08-17 13:54:17 -06:00
|
|
|
runtime·chanrecv(t, c, v, &selected, received);
|
2012-05-29 12:02:29 -06:00
|
|
|
}
|
2011-01-30 14:07:57 -07: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
|
|
|
// For reflect:
|
|
|
|
// func chansend(c chan, val iword, nb bool) (selected bool)
|
|
|
|
// where an iword is the same word an interface value would use:
|
|
|
|
// the actual data if it fits, or else a pointer to the data.
|
|
|
|
//
|
|
|
|
// The "uintptr selected" is really "bool selected" but saying
|
|
|
|
// uintptr gets us the right alignment for the output parameter block.
|
2012-10-07 12:05:32 -06:00
|
|
|
#pragma textflag 7
|
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
|
|
|
void
|
2011-08-17 13:54:17 -06:00
|
|
|
reflect·chansend(ChanType *t, Hchan *c, uintptr val, bool nb, uintptr selected)
|
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
|
|
|
{
|
|
|
|
bool *sp;
|
|
|
|
byte *vp;
|
2012-05-29 12:02:29 -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
|
|
|
if(nb) {
|
|
|
|
selected = false;
|
|
|
|
sp = (bool*)&selected;
|
|
|
|
} else {
|
|
|
|
*(bool*)&selected = true;
|
|
|
|
FLUSH(&selected);
|
|
|
|
sp = nil;
|
|
|
|
}
|
2011-08-17 13:54:17 -06:00
|
|
|
if(t->elem->size <= sizeof(val))
|
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
|
|
|
vp = (byte*)&val;
|
|
|
|
else
|
|
|
|
vp = (byte*)val;
|
2012-10-07 12:05:32 -06:00
|
|
|
runtime·chansend(t, c, vp, sp, 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
|
|
|
}
|
|
|
|
|
|
|
|
// For reflect:
|
|
|
|
// func chanrecv(c chan, nb bool) (val iword, selected, received bool)
|
|
|
|
// where an iword is the same word an interface value would use:
|
|
|
|
// the actual data if it fits, or else a pointer to the data.
|
|
|
|
void
|
2011-08-17 13:54:17 -06:00
|
|
|
reflect·chanrecv(ChanType *t, Hchan *c, bool nb, uintptr val, bool selected, bool 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
|
|
|
{
|
|
|
|
byte *vp;
|
|
|
|
bool *sp;
|
|
|
|
|
|
|
|
if(nb) {
|
|
|
|
selected = false;
|
|
|
|
sp = &selected;
|
|
|
|
} else {
|
|
|
|
selected = true;
|
|
|
|
FLUSH(&selected);
|
|
|
|
sp = nil;
|
|
|
|
}
|
|
|
|
received = false;
|
|
|
|
FLUSH(&received);
|
2011-08-17 13:54:17 -06:00
|
|
|
if(t->elem->size <= sizeof(val)) {
|
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
|
|
|
val = 0;
|
|
|
|
vp = (byte*)&val;
|
|
|
|
} else {
|
2011-08-17 13:54:17 -06:00
|
|
|
vp = runtime·mal(t->elem->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
|
|
|
val = (uintptr)vp;
|
|
|
|
FLUSH(&val);
|
|
|
|
}
|
2011-08-17 13:54:17 -06:00
|
|
|
runtime·chanrecv(t, c, vp, sp, &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
|
|
|
}
|
|
|
|
|
2011-02-22 15:40:40 -07:00
|
|
|
static void newselect(int32, Select**);
|
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
// newselect(size uint32) (sel *byte);
|
2010-03-04 16:34:25 -07:00
|
|
|
#pragma textflag 7
|
2008-07-24 16:57:30 -06:00
|
|
|
void
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·newselect(int32 size, ...)
|
2008-07-24 16:57:30 -06:00
|
|
|
{
|
2011-02-22 15:40:40 -07:00
|
|
|
int32 o;
|
2009-06-30 21:02:07 -06:00
|
|
|
Select **selp;
|
2008-07-24 16:57:30 -06:00
|
|
|
|
2012-05-29 12:02:29 -06:00
|
|
|
o = ROUND(sizeof(size), Structrnd);
|
2009-06-30 21:02:07 -06:00
|
|
|
selp = (Select**)((byte*)&size + o);
|
2011-02-22 15:40:40 -07:00
|
|
|
newselect(size, selp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
newselect(int32 size, Select **selp)
|
|
|
|
{
|
|
|
|
int32 n;
|
|
|
|
Select *sel;
|
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
n = 0;
|
|
|
|
if(size > 1)
|
|
|
|
n = size-1;
|
2008-07-26 15:21:21 -06:00
|
|
|
|
2012-02-10 22:24:14 -07:00
|
|
|
// 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
|
2011-07-21 11:57:13 -06:00
|
|
|
sel = runtime·mal(sizeof(*sel) +
|
|
|
|
n*sizeof(sel->scase[0]) +
|
|
|
|
size*sizeof(sel->lockorder[0]) +
|
|
|
|
size*sizeof(sel->pollorder[0]));
|
2008-07-26 15:21:21 -06:00
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
sel->tcase = size;
|
|
|
|
sel->ncase = 0;
|
2012-02-10 22:24:14 -07:00
|
|
|
sel->lockorder = (void*)(sel->scase + size);
|
|
|
|
sel->pollorder = (void*)(sel->lockorder + size);
|
2009-06-30 21:02:07 -06:00
|
|
|
*selp = sel;
|
2011-07-21 11:57:13 -06:00
|
|
|
|
2010-04-01 12:56:18 -06:00
|
|
|
if(debug)
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·printf("newselect s=%p size=%d\n", sel, size);
|
2008-07-24 16:57:30 -06:00
|
|
|
}
|
|
|
|
|
2011-03-23 09:28:24 -06:00
|
|
|
// cut in half to give stack a chance to split
|
2011-07-21 11:57:13 -06:00
|
|
|
static void selectsend(Select *sel, Hchan *c, void *pc, void *elem, int32 so);
|
2011-03-23 09:28:24 -06:00
|
|
|
|
2011-07-21 11:57:13 -06:00
|
|
|
// selectsend(sel *byte, hchan *chan any, elem *any) (selected bool);
|
2010-03-04 16:34:25 -07:00
|
|
|
#pragma textflag 7
|
2008-07-24 16:57:30 -06:00
|
|
|
void
|
2011-07-21 11:57:13 -06:00
|
|
|
runtime·selectsend(Select *sel, Hchan *c, void *elem, bool selected)
|
2008-07-24 16:57:30 -06:00
|
|
|
{
|
2011-07-21 12:10:39 -06:00
|
|
|
selected = false;
|
|
|
|
FLUSH(&selected);
|
|
|
|
|
2008-07-25 16:55:12 -06:00
|
|
|
// nil cases do not compete
|
2008-07-24 16:57:30 -06:00
|
|
|
if(c == nil)
|
|
|
|
return;
|
2012-05-29 12:02:29 -06:00
|
|
|
|
2011-07-21 11:57:13 -06:00
|
|
|
selectsend(sel, c, runtime·getcallerpc(&sel), elem, (byte*)&selected - (byte*)&sel);
|
2011-03-23 09:28:24 -06:00
|
|
|
}
|
2008-07-24 16:57:30 -06:00
|
|
|
|
2011-03-23 09:28:24 -06:00
|
|
|
static void
|
2011-07-21 11:57:13 -06:00
|
|
|
selectsend(Select *sel, Hchan *c, void *pc, void *elem, int32 so)
|
2011-03-23 09:28:24 -06:00
|
|
|
{
|
2011-07-21 11:57:13 -06:00
|
|
|
int32 i;
|
2011-03-23 09:28:24 -06:00
|
|
|
Scase *cas;
|
2012-05-29 12:02:29 -06:00
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
i = sel->ncase;
|
|
|
|
if(i >= sel->tcase)
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·throw("selectsend: too many cases");
|
2008-07-24 16:57:30 -06:00
|
|
|
sel->ncase = i+1;
|
2011-07-21 11:57:13 -06:00
|
|
|
cas = &sel->scase[i];
|
2008-07-24 16:57:30 -06:00
|
|
|
|
2011-03-23 09:28:24 -06:00
|
|
|
cas->pc = pc;
|
2008-07-24 16:57:30 -06:00
|
|
|
cas->chan = c;
|
2011-07-21 11:57:13 -06:00
|
|
|
cas->so = so;
|
2011-03-11 12:47:26 -07:00
|
|
|
cas->kind = CaseSend;
|
2011-07-21 11:57:13 -06:00
|
|
|
cas->sg.elem = elem;
|
2008-07-24 16:57:30 -06:00
|
|
|
|
2010-04-01 12:56:18 -06:00
|
|
|
if(debug)
|
2011-03-11 12:47:26 -07:00
|
|
|
runtime·printf("selectsend s=%p pc=%p chan=%p so=%d\n",
|
|
|
|
sel, cas->pc, cas->chan, cas->so);
|
2008-07-24 16:57:30 -06:00
|
|
|
}
|
|
|
|
|
2011-03-23 09:28:24 -06:00
|
|
|
// cut in half to give stack a chance to split
|
|
|
|
static void selectrecv(Select *sel, Hchan *c, void *pc, void *elem, bool*, int32 so);
|
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
|
2010-03-04 16:34:25 -07:00
|
|
|
#pragma textflag 7
|
2008-07-24 16:57:30 -06:00
|
|
|
void
|
2011-03-11 12:47:26 -07:00
|
|
|
runtime·selectrecv(Select *sel, Hchan *c, void *elem, bool selected)
|
2008-07-24 16:57:30 -06:00
|
|
|
{
|
2011-07-21 12:10:39 -06:00
|
|
|
selected = false;
|
|
|
|
FLUSH(&selected);
|
|
|
|
|
2008-07-25 16:55:12 -06:00
|
|
|
// nil cases do not compete
|
2008-07-25 12:58:26 -06:00
|
|
|
if(c == nil)
|
|
|
|
return;
|
|
|
|
|
2011-03-23 09:28:24 -06:00
|
|
|
selectrecv(sel, c, runtime·getcallerpc(&sel), elem, nil, (byte*)&selected - (byte*)&sel);
|
2011-03-11 12:47:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool);
|
|
|
|
#pragma textflag 7
|
|
|
|
void
|
|
|
|
runtime·selectrecv2(Select *sel, Hchan *c, void *elem, bool *received, bool selected)
|
|
|
|
{
|
2011-07-21 12:10:39 -06:00
|
|
|
selected = false;
|
|
|
|
FLUSH(&selected);
|
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
// nil cases do not compete
|
|
|
|
if(c == nil)
|
|
|
|
return;
|
|
|
|
|
2011-03-23 09:28:24 -06:00
|
|
|
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;
|
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
i = sel->ncase;
|
|
|
|
if(i >= sel->tcase)
|
|
|
|
runtime·throw("selectrecv: too many cases");
|
|
|
|
sel->ncase = i+1;
|
2011-07-21 11:57:13 -06:00
|
|
|
cas = &sel->scase[i];
|
2011-03-23 09:28:24 -06:00
|
|
|
cas->pc = pc;
|
2011-03-11 12:47:26 -07:00
|
|
|
cas->chan = c;
|
|
|
|
|
2011-03-23 09:28:24 -06:00
|
|
|
cas->so = so;
|
2011-03-11 12:47:26 -07:00
|
|
|
cas->kind = CaseRecv;
|
2011-07-21 11:57:13 -06:00
|
|
|
cas->sg.elem = elem;
|
|
|
|
cas->receivedp = received;
|
2008-07-25 12:58:26 -06:00
|
|
|
|
2010-04-01 12:56:18 -06:00
|
|
|
if(debug)
|
2011-03-23 09:28:24 -06:00
|
|
|
runtime·printf("selectrecv s=%p pc=%p chan=%p so=%d\n",
|
|
|
|
sel, cas->pc, cas->chan, cas->so);
|
2008-07-24 16:57:30 -06:00
|
|
|
}
|
|
|
|
|
2011-03-23 09:28:24 -06:00
|
|
|
// cut in half to give stack a chance to split
|
2011-03-11 12:47:26 -07:00
|
|
|
static void selectdefault(Select*, void*, int32);
|
2011-02-22 15:40:40 -07:00
|
|
|
|
|
|
|
// selectdefault(sel *byte) (selected bool);
|
2010-03-04 16:34:25 -07:00
|
|
|
#pragma textflag 7
|
2008-11-05 19:04:24 -07:00
|
|
|
void
|
2011-03-11 12:47:26 -07:00
|
|
|
runtime·selectdefault(Select *sel, bool selected)
|
2008-11-05 19:04:24 -07:00
|
|
|
{
|
2011-07-21 12:10:39 -06:00
|
|
|
selected = false;
|
|
|
|
FLUSH(&selected);
|
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
selectdefault(sel, runtime·getcallerpc(&sel), (byte*)&selected - (byte*)&sel);
|
2011-02-22 15:40:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-03-11 12:47:26 -07:00
|
|
|
selectdefault(Select *sel, void *callerpc, int32 so)
|
2011-02-22 15:40:40 -07:00
|
|
|
{
|
2008-11-05 22:50:28 -07:00
|
|
|
int32 i;
|
2008-11-05 19:04:24 -07:00
|
|
|
Scase *cas;
|
2008-12-09 17:16:07 -07:00
|
|
|
|
2008-11-05 19:04:24 -07:00
|
|
|
i = sel->ncase;
|
|
|
|
if(i >= sel->tcase)
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·throw("selectdefault: too many cases");
|
2008-11-05 19:04:24 -07:00
|
|
|
sel->ncase = i+1;
|
2011-07-21 11:57:13 -06:00
|
|
|
cas = &sel->scase[i];
|
2011-02-22 19:10:02 -07:00
|
|
|
cas->pc = callerpc;
|
2008-11-05 22:50:28 -07:00
|
|
|
cas->chan = nil;
|
2008-11-05 19:04:24 -07:00
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
cas->so = so;
|
|
|
|
cas->kind = CaseDefault;
|
2008-11-05 19:04:24 -07:00
|
|
|
|
2010-04-01 12:56:18 -06:00
|
|
|
if(debug)
|
2011-03-11 12:47:26 -07:00
|
|
|
runtime·printf("selectdefault s=%p pc=%p so=%d\n",
|
|
|
|
sel, cas->pc, cas->so);
|
2008-11-05 19:04:24 -07:00
|
|
|
}
|
|
|
|
|
2009-12-04 11:57:01 -07:00
|
|
|
static void
|
|
|
|
sellock(Select *sel)
|
|
|
|
{
|
|
|
|
uint32 i;
|
2011-07-21 11:57:13 -06:00
|
|
|
Hchan *c, *c0;
|
2009-12-04 11:57:01 -07:00
|
|
|
|
|
|
|
c = nil;
|
|
|
|
for(i=0; i<sel->ncase; i++) {
|
2011-07-21 11:57:13 -06:00
|
|
|
c0 = sel->lockorder[i];
|
|
|
|
if(c0 && c0 != c) {
|
|
|
|
c = sel->lockorder[i];
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·lock(c);
|
2009-12-04 11:57:01 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
selunlock(Select *sel)
|
|
|
|
{
|
|
|
|
uint32 i;
|
2011-07-21 11:57:13 -06:00
|
|
|
Hchan *c, *c0;
|
2009-12-04 11:57:01 -07:00
|
|
|
|
|
|
|
c = nil;
|
2011-07-21 11:57:13 -06:00
|
|
|
for(i=sel->ncase; i-->0;) {
|
|
|
|
c0 = sel->lockorder[i];
|
|
|
|
if(c0 && c0 != c) {
|
|
|
|
c = c0;
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·unlock(c);
|
2009-12-04 11:57:01 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-30 14:07:57 -07:00
|
|
|
void
|
|
|
|
runtime·block(void)
|
|
|
|
{
|
2012-09-18 11:15:46 -06:00
|
|
|
runtime·park(nil, nil, "select (no cases)"); // forever
|
2011-01-30 14:07:57 -07:00
|
|
|
}
|
|
|
|
|
2011-02-22 19:10:02 -07:00
|
|
|
static void* selectgo(Select**);
|
2011-02-22 15:40:40 -07:00
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
// selectgo(sel *byte);
|
2010-10-20 13:54:17 -06:00
|
|
|
//
|
|
|
|
// 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 7
|
2008-07-24 16:57:30 -06:00
|
|
|
void
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·selectgo(Select *sel)
|
2008-07-24 16:57:30 -06:00
|
|
|
{
|
2011-02-22 19:10:02 -07:00
|
|
|
runtime·setcallerpc(&sel, selectgo(&sel));
|
2011-02-22 15:40:40 -07:00
|
|
|
}
|
|
|
|
|
2011-02-22 19:10:02 -07:00
|
|
|
static void*
|
2011-02-22 15:40:40 -07:00
|
|
|
selectgo(Select **selp)
|
|
|
|
{
|
|
|
|
Select *sel;
|
2011-01-20 07:20:47 -07:00
|
|
|
uint32 o, i, j;
|
2008-11-05 18:57:18 -07:00
|
|
|
Scase *cas, *dfl;
|
2008-07-24 16:57:30 -06:00
|
|
|
Hchan *c;
|
2008-07-25 16:55:12 -06:00
|
|
|
SudoG *sg;
|
|
|
|
G *gp;
|
2008-08-05 15:18:47 -06:00
|
|
|
byte *as;
|
2011-02-22 19:10:02 -07:00
|
|
|
void *pc;
|
2008-07-24 16:57:30 -06:00
|
|
|
|
2011-02-22 15:40:40 -07:00
|
|
|
sel = *selp;
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
if(runtime·gcwaiting)
|
|
|
|
runtime·gosched();
|
2010-01-09 10:47:45 -07:00
|
|
|
|
2010-04-01 12:56:18 -06:00
|
|
|
if(debug)
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·printf("select: sel=%p\n", sel);
|
2008-07-25 12:58:26 -06:00
|
|
|
|
2011-01-30 14:07:57 -07:00
|
|
|
// 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).
|
2008-07-24 16:57:30 -06:00
|
|
|
|
2011-01-20 07:20:47 -07:00
|
|
|
// generate permuted order
|
|
|
|
for(i=0; i<sel->ncase; i++)
|
2011-07-21 11:57:13 -06:00
|
|
|
sel->pollorder[i] = i;
|
2011-01-20 07:20:47 -07:00
|
|
|
for(i=1; i<sel->ncase; i++) {
|
2011-07-21 11:57:13 -06:00
|
|
|
o = sel->pollorder[i];
|
2011-07-20 12:28:55 -06:00
|
|
|
j = runtime·fastrand1()%(i+1);
|
2011-07-21 11:57:13 -06:00
|
|
|
sel->pollorder[i] = sel->pollorder[j];
|
|
|
|
sel->pollorder[j] = o;
|
2008-07-24 16:57:30 -06:00
|
|
|
}
|
2008-07-25 16:55:12 -06:00
|
|
|
|
2009-12-04 11:57:01 -07:00
|
|
|
// sort the cases by Hchan address to get the locking order.
|
2011-07-21 11:57:13 -06:00
|
|
|
for(i=0; i<sel->ncase; i++) {
|
|
|
|
c = sel->scase[i].chan;
|
|
|
|
for(j=i; j>0 && sel->lockorder[j-1] >= c; j--)
|
|
|
|
sel->lockorder[j] = sel->lockorder[j-1];
|
|
|
|
sel->lockorder[j] = c;
|
2009-12-04 11:57:01 -07:00
|
|
|
}
|
|
|
|
sellock(sel);
|
2008-09-09 12:50:14 -06:00
|
|
|
|
2009-01-24 16:58:44 -07:00
|
|
|
loop:
|
2008-07-25 16:55:12 -06:00
|
|
|
// pass 1 - look for something already waiting
|
2008-11-05 18:57:18 -07:00
|
|
|
dfl = nil;
|
2008-07-24 16:57:30 -06:00
|
|
|
for(i=0; i<sel->ncase; i++) {
|
2011-07-21 11:57:13 -06:00
|
|
|
o = sel->pollorder[i];
|
|
|
|
cas = &sel->scase[o];
|
2008-07-24 16:57:30 -06:00
|
|
|
c = cas->chan;
|
2010-04-01 12:56:18 -06:00
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
switch(cas->kind) {
|
|
|
|
case CaseRecv:
|
2010-04-01 12:56:18 -06:00
|
|
|
if(c->dataqsiz > 0) {
|
|
|
|
if(c->qcount > 0)
|
|
|
|
goto asyncrecv;
|
|
|
|
} else {
|
2011-07-21 11:57:13 -06:00
|
|
|
sg = dequeue(&c->sendq);
|
2010-04-01 12:56:18 -06:00
|
|
|
if(sg != nil)
|
|
|
|
goto syncrecv;
|
2008-07-26 15:21:21 -06:00
|
|
|
}
|
2011-03-11 12:47:26 -07:00
|
|
|
if(c->closed)
|
2009-03-23 19:50:35 -06:00
|
|
|
goto rclose;
|
2010-04-01 12:56:18 -06:00
|
|
|
break;
|
2008-07-25 12:58:26 -06:00
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
case CaseSend:
|
|
|
|
if(c->closed)
|
2009-03-23 19:50:35 -06:00
|
|
|
goto sclose;
|
2010-04-01 12:56:18 -06:00
|
|
|
if(c->dataqsiz > 0) {
|
|
|
|
if(c->qcount < c->dataqsiz)
|
|
|
|
goto asyncsend;
|
|
|
|
} else {
|
2011-07-21 11:57:13 -06:00
|
|
|
sg = dequeue(&c->recvq);
|
2010-04-01 12:56:18 -06:00
|
|
|
if(sg != nil)
|
|
|
|
goto syncsend;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
case CaseDefault:
|
2010-04-01 12:56:18 -06:00
|
|
|
dfl = cas;
|
|
|
|
break;
|
2008-07-25 16:55:12 -06:00
|
|
|
}
|
|
|
|
}
|
2008-12-09 17:16:07 -07:00
|
|
|
|
2008-11-05 18:57:18 -07:00
|
|
|
if(dfl != nil) {
|
2011-07-20 09:51:25 -06:00
|
|
|
selunlock(sel);
|
2008-11-05 18:57:18 -07:00
|
|
|
cas = dfl;
|
|
|
|
goto retc;
|
|
|
|
}
|
2008-12-09 17:16:07 -07:00
|
|
|
|
2008-07-25 12:58:26 -06:00
|
|
|
|
2008-07-25 16:55:12 -06:00
|
|
|
// pass 2 - enqueue on all chans
|
|
|
|
for(i=0; i<sel->ncase; i++) {
|
2011-08-15 00:51:51 -06:00
|
|
|
o = sel->pollorder[i];
|
|
|
|
cas = &sel->scase[o];
|
2008-07-25 16:55:12 -06:00
|
|
|
c = cas->chan;
|
2011-07-21 11:57:13 -06:00
|
|
|
sg = &cas->sg;
|
|
|
|
sg->g = g;
|
|
|
|
sg->selgen = g->selgen;
|
2008-07-26 15:21:21 -06:00
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
switch(cas->kind) {
|
|
|
|
case CaseRecv:
|
2008-11-06 18:50:28 -07:00
|
|
|
enqueue(&c->recvq, sg);
|
2010-04-01 12:56:18 -06:00
|
|
|
break;
|
2012-05-29 12:02:29 -06:00
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
case CaseSend:
|
2008-07-25 16:55:12 -06:00
|
|
|
enqueue(&c->sendq, sg);
|
2010-04-01 12:56:18 -06:00
|
|
|
break;
|
2008-11-06 18:50:28 -07:00
|
|
|
}
|
2008-07-24 16:57:30 -06:00
|
|
|
}
|
|
|
|
|
2009-01-24 16:58:44 -07:00
|
|
|
g->param = nil;
|
2012-09-18 11:15:46 -06:00
|
|
|
runtime·park((void(*)(Lock*))selunlock, (Lock*)sel, "select");
|
2008-07-25 16:55:12 -06:00
|
|
|
|
2009-12-04 11:57:01 -07:00
|
|
|
sellock(sel);
|
2008-07-25 16:55:12 -06:00
|
|
|
sg = g->param;
|
2010-04-01 12:56:18 -06:00
|
|
|
|
|
|
|
// pass 3 - dequeue from unsuccessful chans
|
|
|
|
// otherwise they stack up on quiet channels
|
|
|
|
for(i=0; i<sel->ncase; i++) {
|
2011-07-21 11:57:13 -06:00
|
|
|
cas = &sel->scase[i];
|
|
|
|
if(cas != (Scase*)sg) {
|
2010-04-01 12:56:18 -06:00
|
|
|
c = cas->chan;
|
2011-03-11 12:47:26 -07:00
|
|
|
if(cas->kind == CaseSend)
|
2011-07-21 11:57:13 -06:00
|
|
|
dequeueg(&c->sendq);
|
2010-04-01 12:56:18 -06:00
|
|
|
else
|
2011-07-21 11:57:13 -06:00
|
|
|
dequeueg(&c->recvq);
|
2010-04-01 12:56:18 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-24 16:58:44 -07:00
|
|
|
if(sg == nil)
|
|
|
|
goto loop;
|
|
|
|
|
2011-07-21 11:57:13 -06:00
|
|
|
cas = (Scase*)sg;
|
2008-07-25 16:55:12 -06:00
|
|
|
c = cas->chan;
|
|
|
|
|
2011-07-20 09:51:25 -06:00
|
|
|
if(c->dataqsiz > 0)
|
|
|
|
runtime·throw("selectgo: shouldnt happen");
|
2009-01-24 16:58:44 -07:00
|
|
|
|
2010-04-01 12:56:18 -06:00
|
|
|
if(debug)
|
2011-07-21 11:57:13 -06:00
|
|
|
runtime·printf("wait-return: sel=%p c=%p cas=%p kind=%d\n",
|
|
|
|
sel, c, cas, cas->kind);
|
2011-03-11 12:47:26 -07:00
|
|
|
|
|
|
|
if(cas->kind == CaseRecv) {
|
2011-07-21 11:57:13 -06:00
|
|
|
if(cas->receivedp != nil)
|
|
|
|
*cas->receivedp = true;
|
2008-07-26 15:21:21 -06:00
|
|
|
}
|
|
|
|
|
2011-07-20 09:51:25 -06:00
|
|
|
selunlock(sel);
|
2008-07-26 15:21:21 -06:00
|
|
|
goto retc;
|
|
|
|
|
2010-04-01 12:56:18 -06:00
|
|
|
asyncrecv:
|
|
|
|
// can receive from buffer
|
2012-10-07 12:05:32 -06:00
|
|
|
if(raceenabled)
|
|
|
|
runtime·raceacquire(chanbuf(c, c->recvx));
|
2011-07-21 11:57:13 -06:00
|
|
|
if(cas->receivedp != nil)
|
|
|
|
*cas->receivedp = true;
|
|
|
|
if(cas->sg.elem != nil)
|
|
|
|
c->elemalg->copy(c->elemsize, cas->sg.elem, chanbuf(c, c->recvx));
|
2011-04-13 21:42:06 -06:00
|
|
|
c->elemalg->copy(c->elemsize, chanbuf(c, c->recvx), nil);
|
|
|
|
if(++c->recvx == c->dataqsiz)
|
|
|
|
c->recvx = 0;
|
2008-09-19 21:43:30 -06:00
|
|
|
c->qcount--;
|
2011-07-21 11:57:13 -06:00
|
|
|
sg = dequeue(&c->sendq);
|
2008-09-19 21:43:30 -06:00
|
|
|
if(sg != nil) {
|
|
|
|
gp = sg->g;
|
2011-07-20 09:51:25 -06:00
|
|
|
selunlock(sel);
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·ready(gp);
|
2011-07-20 09:51:25 -06:00
|
|
|
} else {
|
|
|
|
selunlock(sel);
|
2008-09-19 21:43:30 -06:00
|
|
|
}
|
|
|
|
goto retc;
|
|
|
|
|
2010-04-01 12:56:18 -06:00
|
|
|
asyncsend:
|
|
|
|
// can send to buffer
|
2012-10-07 12:05:32 -06:00
|
|
|
if(raceenabled)
|
|
|
|
runtime·racerelease(chanbuf(c, c->sendx));
|
2011-07-21 11:57:13 -06:00
|
|
|
c->elemalg->copy(c->elemsize, chanbuf(c, c->sendx), cas->sg.elem);
|
2011-04-13 21:42:06 -06:00
|
|
|
if(++c->sendx == c->dataqsiz)
|
|
|
|
c->sendx = 0;
|
2008-09-19 21:43:30 -06:00
|
|
|
c->qcount++;
|
2011-07-21 11:57:13 -06:00
|
|
|
sg = dequeue(&c->recvq);
|
2008-09-19 21:43:30 -06:00
|
|
|
if(sg != nil) {
|
|
|
|
gp = sg->g;
|
2011-07-20 09:51:25 -06:00
|
|
|
selunlock(sel);
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·ready(gp);
|
2011-07-20 09:51:25 -06:00
|
|
|
} else {
|
|
|
|
selunlock(sel);
|
2008-09-19 21:43:30 -06:00
|
|
|
}
|
|
|
|
goto retc;
|
2008-08-05 15:18:47 -06:00
|
|
|
|
2010-04-01 12:56:18 -06:00
|
|
|
syncrecv:
|
|
|
|
// can receive from sleeping sender (sg)
|
2012-10-07 12:05:32 -06:00
|
|
|
if(raceenabled)
|
|
|
|
racesync(c, sg);
|
2011-07-20 09:51:25 -06:00
|
|
|
selunlock(sel);
|
2010-04-01 12:56:18 -06:00
|
|
|
if(debug)
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·printf("syncrecv: sel=%p c=%p o=%d\n", sel, c, o);
|
2011-07-21 11:57:13 -06:00
|
|
|
if(cas->receivedp != nil)
|
|
|
|
*cas->receivedp = true;
|
|
|
|
if(cas->sg.elem != nil)
|
|
|
|
c->elemalg->copy(c->elemsize, cas->sg.elem, sg->elem);
|
2008-07-25 16:55:12 -06:00
|
|
|
gp = sg->g;
|
|
|
|
gp->param = sg;
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·ready(gp);
|
2008-07-25 16:55:12 -06:00
|
|
|
goto retc;
|
|
|
|
|
2009-03-23 19:50:35 -06:00
|
|
|
rclose:
|
2010-04-01 12:56:18 -06:00
|
|
|
// read at end of closed channel
|
2011-07-20 09:51:25 -06:00
|
|
|
selunlock(sel);
|
2011-07-21 11:57:13 -06:00
|
|
|
if(cas->receivedp != nil)
|
|
|
|
*cas->receivedp = false;
|
|
|
|
if(cas->sg.elem != nil)
|
|
|
|
c->elemalg->copy(c->elemsize, cas->sg.elem, nil);
|
2012-10-07 12:05:32 -06:00
|
|
|
if(raceenabled)
|
|
|
|
runtime·raceacquire(c);
|
2009-03-23 19:50:35 -06:00
|
|
|
goto retc;
|
|
|
|
|
2010-04-01 12:56:18 -06:00
|
|
|
syncsend:
|
|
|
|
// can send to sleeping receiver (sg)
|
2012-10-07 12:05:32 -06:00
|
|
|
if(raceenabled)
|
|
|
|
racesync(c, sg);
|
2011-07-20 09:51:25 -06:00
|
|
|
selunlock(sel);
|
2010-04-01 12:56:18 -06:00
|
|
|
if(debug)
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o);
|
2011-09-26 21:46:37 -06:00
|
|
|
if(sg->elem != nil)
|
|
|
|
c->elemalg->copy(c->elemsize, sg->elem, cas->sg.elem);
|
2008-07-25 16:55:12 -06:00
|
|
|
gp = sg->g;
|
|
|
|
gp->param = sg;
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·ready(gp);
|
2008-07-24 16:57:30 -06:00
|
|
|
|
|
|
|
retc:
|
2012-09-18 12:22:41 -06:00
|
|
|
// 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.
|
2011-02-22 19:10:02 -07:00
|
|
|
pc = cas->pc;
|
2012-09-18 12:22:41 -06:00
|
|
|
if(cas->so > 0) {
|
|
|
|
as = (byte*)selp + cas->so;
|
|
|
|
*as = true;
|
|
|
|
}
|
2011-07-21 11:57:13 -06:00
|
|
|
runtime·free(sel);
|
2011-02-22 19:10:02 -07:00
|
|
|
return pc;
|
spec, runtime, tests: send on closed channel panics
Close of closed channel panics.
Receive from closed channel never panics,
even if done repeatedly.
Fixes #1349.
Fixes #1419.
R=gri, iant, ken2, r, gri1, r2, iant2, rog, albert.strasheim, niemeyer, ejsherry
CC=golang-dev
https://golang.org/cl/3989042
2011-01-21 13:07:13 -07:00
|
|
|
|
|
|
|
sclose:
|
|
|
|
// send on closed channel
|
|
|
|
selunlock(sel);
|
|
|
|
runtime·panicstring("send on closed channel");
|
2011-02-22 19:10:02 -07:00
|
|
|
return nil; // not reached
|
2008-07-24 16:57:30 -06:00
|
|
|
}
|
|
|
|
|
2012-09-18 12:22:41 -06:00
|
|
|
// This struct must match ../reflect/value.go:/runtimeSelect.
|
|
|
|
typedef struct runtimeSelect runtimeSelect;
|
|
|
|
struct runtimeSelect
|
|
|
|
{
|
|
|
|
uintptr dir;
|
|
|
|
ChanType *typ;
|
|
|
|
Hchan *ch;
|
|
|
|
uintptr val;
|
|
|
|
};
|
|
|
|
|
|
|
|
// This enum must match ../reflect/value.go:/SelectDir.
|
|
|
|
enum SelectDir {
|
|
|
|
SelectSend = 1,
|
|
|
|
SelectRecv,
|
|
|
|
SelectDefault,
|
|
|
|
};
|
|
|
|
|
|
|
|
// func rselect(cases []runtimeSelect) (chosen int, word uintptr, recvOK bool)
|
|
|
|
void
|
2012-09-24 12:58:34 -06:00
|
|
|
reflect·rselect(Slice cases, intgo chosen, uintptr word, bool recvOK)
|
2012-09-18 12:22:41 -06:00
|
|
|
{
|
|
|
|
int32 i;
|
|
|
|
Select *sel;
|
|
|
|
runtimeSelect* rcase, *rc;
|
|
|
|
void *elem;
|
|
|
|
void *recvptr;
|
|
|
|
uintptr maxsize;
|
|
|
|
|
|
|
|
chosen = -1;
|
|
|
|
word = 0;
|
|
|
|
recvOK = false;
|
|
|
|
|
|
|
|
maxsize = 0;
|
|
|
|
rcase = (runtimeSelect*)cases.array;
|
|
|
|
for(i=0; i<cases.len; i++) {
|
|
|
|
rc = &rcase[i];
|
|
|
|
if(rc->dir == SelectRecv && rc->ch != nil && maxsize < rc->typ->elem->size)
|
|
|
|
maxsize = rc->typ->elem->size;
|
|
|
|
}
|
|
|
|
|
|
|
|
recvptr = nil;
|
|
|
|
if(maxsize > sizeof(void*))
|
|
|
|
recvptr = runtime·mal(maxsize);
|
|
|
|
|
|
|
|
newselect(cases.len, &sel);
|
|
|
|
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;
|
|
|
|
if(rc->typ->elem->size > sizeof(void*))
|
|
|
|
elem = (void*)rc->val;
|
|
|
|
else
|
|
|
|
elem = (void*)&rc->val;
|
|
|
|
selectsend(sel, rc->ch, (void*)i, elem, 0);
|
|
|
|
break;
|
|
|
|
case SelectRecv:
|
|
|
|
if(rc->ch == nil)
|
|
|
|
break;
|
|
|
|
if(rc->typ->elem->size > sizeof(void*))
|
|
|
|
elem = recvptr;
|
|
|
|
else
|
|
|
|
elem = &word;
|
|
|
|
selectrecv(sel, rc->ch, (void*)i, elem, &recvOK, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-24 12:58:34 -06:00
|
|
|
chosen = (intgo)(uintptr)selectgo(&sel);
|
2012-09-18 12:22:41 -06:00
|
|
|
if(rcase[chosen].dir == SelectRecv && rcase[chosen].typ->elem->size > sizeof(void*))
|
|
|
|
word = (uintptr)recvptr;
|
|
|
|
|
|
|
|
FLUSH(&chosen);
|
|
|
|
FLUSH(&word);
|
|
|
|
FLUSH(&recvOK);
|
|
|
|
}
|
|
|
|
|
2009-03-12 18:55:11 -06:00
|
|
|
// closechan(sel *byte);
|
2012-10-07 12:05:32 -06:00
|
|
|
#pragma textflag 7
|
2009-03-12 18:55:11 -06:00
|
|
|
void
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·closechan(Hchan *c)
|
2009-03-12 18:55:11 -06:00
|
|
|
{
|
2009-03-13 17:47:54 -06:00
|
|
|
SudoG *sg;
|
|
|
|
G* gp;
|
2009-03-12 18:55:11 -06:00
|
|
|
|
2011-10-13 14:58:04 -06:00
|
|
|
if(c == nil)
|
|
|
|
runtime·panicstring("close of nil channel");
|
|
|
|
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
if(runtime·gcwaiting)
|
|
|
|
runtime·gosched();
|
2010-01-09 10:47:45 -07:00
|
|
|
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·lock(c);
|
2011-03-11 12:47:26 -07:00
|
|
|
if(c->closed) {
|
spec, runtime, tests: send on closed channel panics
Close of closed channel panics.
Receive from closed channel never panics,
even if done repeatedly.
Fixes #1349.
Fixes #1419.
R=gri, iant, ken2, r, gri1, r2, iant2, rog, albert.strasheim, niemeyer, ejsherry
CC=golang-dev
https://golang.org/cl/3989042
2011-01-21 13:07:13 -07:00
|
|
|
runtime·unlock(c);
|
|
|
|
runtime·panicstring("close of closed channel");
|
|
|
|
}
|
|
|
|
|
2012-10-07 12:05:32 -06:00
|
|
|
if(raceenabled) {
|
2012-11-29 23:29:41 -07:00
|
|
|
runtime·racewritepc(c, runtime·getcallerpc(&c), runtime·closechan);
|
2012-10-07 12:05:32 -06:00
|
|
|
runtime·racerelease(c);
|
|
|
|
}
|
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
c->closed = true;
|
2009-03-13 17:47:54 -06:00
|
|
|
|
|
|
|
// release all readers
|
|
|
|
for(;;) {
|
2011-07-21 11:57:13 -06:00
|
|
|
sg = dequeue(&c->recvq);
|
2009-03-13 17:47:54 -06:00
|
|
|
if(sg == nil)
|
|
|
|
break;
|
|
|
|
gp = sg->g;
|
|
|
|
gp->param = nil;
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·ready(gp);
|
2009-03-13 17:47:54 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// release all writers
|
|
|
|
for(;;) {
|
2011-07-21 11:57:13 -06:00
|
|
|
sg = dequeue(&c->sendq);
|
2009-03-13 17:47:54 -06:00
|
|
|
if(sg == nil)
|
|
|
|
break;
|
|
|
|
gp = sg->g;
|
|
|
|
gp->param = nil;
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·ready(gp);
|
2009-03-13 17:47:54 -06:00
|
|
|
}
|
|
|
|
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·unlock(c);
|
2009-03-12 18:55:11 -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
|
|
|
// For reflect
|
|
|
|
// func chanclose(c chan)
|
2009-08-26 11:47:18 -06:00
|
|
|
void
|
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
|
|
|
reflect·chanclose(Hchan *c)
|
2009-08-26 11:47:18 -06:00
|
|
|
{
|
runtime: ,s/[a-zA-Z0-9_]+/runtime·&/g, almost
Prefix all external symbols in runtime by runtime·,
to avoid conflicts with possible symbols of the same
name in linked-in C libraries. The obvious conflicts
are printf, malloc, and free, but hide everything to
avoid future pain.
The symbols left alone are:
** known to cgo **
_cgo_free
_cgo_malloc
libcgo_thread_start
initcgo
ncgocall
** known to linker **
_rt0_$GOARCH
_rt0_$GOARCH_$GOOS
text
etext
data
end
pclntab
epclntab
symtab
esymtab
** known to C compiler **
_divv
_modv
_div64by32
etc (arch specific)
Tested on darwin/386, darwin/amd64, linux/386, linux/amd64.
Built (but not tested) for freebsd/386, freebsd/amd64, linux/arm, windows/386.
R=r, PeterGo
CC=golang-dev
https://golang.org/cl/2899041
2010-11-04 12:00:19 -06:00
|
|
|
runtime·closechan(c);
|
2009-08-26 11:47:18 -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
|
|
|
// For reflect
|
2012-09-24 12:58:34 -06:00
|
|
|
// func chanlen(c chan) (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
|
|
|
void
|
2012-09-24 12:58:34 -06:00
|
|
|
reflect·chanlen(Hchan *c, intgo len)
|
2009-08-26 13:42:22 -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
|
|
|
if(c == nil)
|
|
|
|
len = 0;
|
|
|
|
else
|
|
|
|
len = c->qcount;
|
|
|
|
FLUSH(&len);
|
2009-08-26 13:42:22 -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
|
|
|
// For reflect
|
2012-09-24 12:58:34 -06:00
|
|
|
// func chancap(c chan) 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
|
|
|
void
|
2012-09-24 12:58:34 -06:00
|
|
|
reflect·chancap(Hchan *c, intgo cap)
|
2009-08-26 13:42:22 -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
|
|
|
if(c == nil)
|
|
|
|
cap = 0;
|
|
|
|
else
|
|
|
|
cap = c->dataqsiz;
|
|
|
|
FLUSH(&cap);
|
2009-08-26 13:42:22 -06:00
|
|
|
}
|
|
|
|
|
2008-07-20 21:13:07 -06:00
|
|
|
static SudoG*
|
2011-07-21 11:57:13 -06:00
|
|
|
dequeue(WaitQ *q)
|
2008-07-20 21:13:07 -06:00
|
|
|
{
|
|
|
|
SudoG *sgp;
|
|
|
|
|
|
|
|
loop:
|
|
|
|
sgp = q->first;
|
|
|
|
if(sgp == nil)
|
|
|
|
return nil;
|
|
|
|
q->first = sgp->link;
|
|
|
|
|
|
|
|
// if sgp is stale, ignore it
|
2011-07-20 12:28:55 -06:00
|
|
|
if(sgp->selgen != NOSELGEN &&
|
|
|
|
(sgp->selgen != sgp->g->selgen ||
|
|
|
|
!runtime·cas(&sgp->g->selgen, sgp->selgen, sgp->selgen + 2))) {
|
2008-07-25 16:55:12 -06:00
|
|
|
//prints("INVALID PSEUDOG POINTER\n");
|
2008-07-20 21:13:07 -06:00
|
|
|
goto loop;
|
|
|
|
}
|
|
|
|
|
|
|
|
return sgp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-07-21 11:57:13 -06:00
|
|
|
dequeueg(WaitQ *q)
|
2010-04-01 12:56:18 -06:00
|
|
|
{
|
2011-07-18 14:15:01 -06:00
|
|
|
SudoG **l, *sgp, *prevsgp;
|
|
|
|
|
|
|
|
prevsgp = nil;
|
|
|
|
for(l=&q->first; (sgp=*l) != nil; l=&sgp->link, prevsgp=sgp) {
|
2010-04-01 12:56:18 -06:00
|
|
|
if(sgp->g == g) {
|
|
|
|
*l = sgp->link;
|
2011-07-18 14:15:01 -06:00
|
|
|
if(q->last == sgp)
|
|
|
|
q->last = prevsgp;
|
2010-04-01 12:56:18 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2008-07-20 21:13:07 -06:00
|
|
|
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;
|
|
|
|
}
|
2012-10-07 12:05:32 -06:00
|
|
|
|
|
|
|
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));
|
|
|
|
}
|