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"
|
2013-08-12 14:47:18 -06:00
|
|
|
#include "../../cmd/ld/textflag.h"
|
2008-07-13 15:29:46 -06:00
|
|
|
|
2013-06-06 13:06:12 -06:00
|
|
|
#define MAXALIGN 8
|
2011-07-20 12:28:55 -06:00
|
|
|
#define NOSELGEN 1
|
2011-03-22 19:41:17 -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
|
|
|
|
2013-02-25 13:58:23 -07:00
|
|
|
// The garbage collector is assuming that Hchan can only contain pointers into the stack
|
|
|
|
// and cannot contain pointers into the heap.
|
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;
|
2013-06-06 13:06:12 -06:00
|
|
|
uint16 pad; // ensures proper alignment of the buffer that follows Hchan in memory
|
2011-03-11 12:47:26 -07:00
|
|
|
bool closed;
|
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
|
|
|
};
|
|
|
|
|
2013-02-25 13:58:23 -07:00
|
|
|
uint32 runtime·Hchansize = sizeof(Hchan);
|
|
|
|
|
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
|
|
|
|
{
|
2013-05-15 01:10:26 -06:00
|
|
|
debug = 0,
|
|
|
|
|
2011-03-11 12:47:26 -07:00
|
|
|
// 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;
|
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");
|
2013-06-06 13:06:12 -06:00
|
|
|
if((sizeof(*c)%MAXALIGN) != 0 || elem->align > MAXALIGN)
|
|
|
|
runtime·throw("makechan: bad alignment");
|
2012-09-24 12:58:34 -06:00
|
|
|
|
|
|
|
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-03-22 19:41:17 -06:00
|
|
|
// allocate memory in one call
|
runtime: refactor mallocgc
Make it accept type, combine flags.
Several reasons for the change:
1. mallocgc and settype must be atomic wrt GC
2. settype is called from only one place now
3. it will help performance (eventually settype
functionality must be combined with markallocated)
4. flags are easier to read now (no mallocgc(sz, 0, 1, 0) anymore)
R=golang-dev, iant, nightlyone, rsc, dave, khr, bradfitz, r
CC=golang-dev
https://golang.org/cl/10136043
2013-07-26 11:17:24 -06:00
|
|
|
c = (Hchan*)runtime·mallocgc(sizeof(*c) + hint*elem->size, (uintptr)t | TypeInfo_Chan, 0);
|
2009-09-08 14:46:54 -06:00
|
|
|
c->elemsize = elem->size;
|
2011-12-05 07:40:22 -07:00
|
|
|
c->elemalg = elem->alg;
|
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)
|
2013-06-06 13:06:12 -06:00
|
|
|
runtime·printf("makechan: chan=%p; elemsize=%D; elemalg=%p; dataqsiz=%D\n",
|
|
|
|
c, (int64)elem->size, elem->alg, (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
|
|
|
|
2014-01-21 00:17:44 -07:00
|
|
|
if(raceenabled)
|
|
|
|
runtime·racereadobjectpc(ep, t->elem, runtime·getcallerpc(&t), runtime·chansend);
|
|
|
|
|
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
|
|
|
|
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
|
|
|
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
|
|
|
|
2014-01-21 00:17:44 -07:00
|
|
|
// raceenabled: don't need to check ep, as it is always on the stack.
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2014-01-17 15:48:45 -07:00
|
|
|
// chansend1(hchan *chan any, elem *any);
|
2013-08-12 14:47:18 -06:00
|
|
|
#pragma textflag NOSPLIT
|
2008-07-13 17:20:27 -06:00
|
|
|
void
|
2014-01-17 15:48:45 -07:00
|
|
|
runtime·chansend1(ChanType *t, Hchan* c, byte *v)
|
2008-07-26 15:21:21 -06:00
|
|
|
{
|
2014-01-17 15:48:45 -07:00
|
|
|
runtime·chansend(t, c, v, nil, runtime·getcallerpc(&t));
|
2008-07-26 15:21:21 -06:00
|
|
|
}
|
|
|
|
|
2014-01-17 15:48:45 -07:00
|
|
|
// chanrecv1(hchan *chan any, elem *any);
|
2013-08-12 14:47:18 -06:00
|
|
|
#pragma textflag NOSPLIT
|
2008-07-26 15:21:21 -06:00
|
|
|
void
|
2014-01-17 15:48:45 -07:00
|
|
|
runtime·chanrecv1(ChanType *t, Hchan* c, byte *v)
|
2008-07-26 15:21:21 -06:00
|
|
|
{
|
2014-01-17 15:48:45 -07:00
|
|
|
runtime·chanrecv(t, c, v, nil, nil);
|
2008-07-26 15:21:21 -06:00
|
|
|
}
|
2008-07-14 15:33:39 -06:00
|
|
|
|
2014-01-17 15:48:45 -07:00
|
|
|
// chanrecv2(hchan *chan any, elem *any) (received bool);
|
2013-08-12 14:47:18 -06:00
|
|
|
#pragma textflag NOSPLIT
|
2011-01-18 13:59:19 -07:00
|
|
|
void
|
2014-01-17 15:48:45 -07:00
|
|
|
runtime·chanrecv2(ChanType *t, Hchan* c, byte *v, bool received)
|
2011-01-18 13:59:19 -07:00
|
|
|
{
|
2014-01-17 15:48:45 -07:00
|
|
|
runtime·chanrecv(t, c, v, nil, &received);
|
2008-07-26 15:21:21 -06:00
|
|
|
}
|
|
|
|
|
2014-01-17 15:48:45 -07:00
|
|
|
// func selectnbsend(c chan any, elem *any) bool
|
2011-01-30 14:07:57 -07:00
|
|
|
//
|
|
|
|
// 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
|
|
|
|
// }
|
|
|
|
//
|
2013-08-12 14:47:18 -06:00
|
|
|
#pragma textflag NOSPLIT
|
2011-01-30 14:07:57 -07:00
|
|
|
void
|
2014-01-17 15:48:45 -07:00
|
|
|
runtime·selectnbsend(ChanType *t, Hchan *c, byte *val, bool pres)
|
2011-01-30 14:07:57 -07:00
|
|
|
{
|
2014-01-17 15:48:45 -07:00
|
|
|
runtime·chansend(t, c, val, &pres, 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
|
|
|
|
// }
|
|
|
|
//
|
2013-08-12 14:47:18 -06:00
|
|
|
#pragma textflag NOSPLIT
|
2011-01-30 14:07:57 -07:00
|
|
|
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
|
|
|
|
// }
|
|
|
|
//
|
2013-08-12 14:47:18 -06:00
|
|
|
#pragma textflag NOSPLIT
|
2011-03-11 12:47:26 -07:00
|
|
|
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:
|
2014-01-16 14:35:29 -07:00
|
|
|
// func chansend(c chan, val *any, nb bool) (selected bool)
|
|
|
|
// where val points to the data to be sent.
|
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
|
|
|
//
|
|
|
|
// The "uintptr selected" is really "bool selected" but saying
|
|
|
|
// uintptr gets us the right alignment for the output parameter block.
|
2013-08-12 14:47:18 -06:00
|
|
|
#pragma textflag NOSPLIT
|
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
|
2014-01-16 14:35:29 -07:00
|
|
|
reflect·chansend(ChanType *t, Hchan *c, byte *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;
|
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;
|
|
|
|
}
|
2014-01-16 14:35:29 -07:00
|
|
|
runtime·chansend(t, c, val, 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:
|
2014-01-16 14:35:29 -07:00
|
|
|
// func chanrecv(c chan, nb bool, val *any) (selected, received bool)
|
|
|
|
// where val points to a data area that will be filled in with the
|
|
|
|
// received value. val must have the size and type of the channel element type.
|
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
|
2014-01-16 14:35:29 -07:00
|
|
|
reflect·chanrecv(ChanType *t, Hchan *c, bool nb, byte *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
|
|
|
{
|
|
|
|
bool *sp;
|
|
|
|
|
|
|
|
if(nb) {
|
|
|
|
selected = false;
|
|
|
|
sp = &selected;
|
|
|
|
} else {
|
|
|
|
selected = true;
|
|
|
|
FLUSH(&selected);
|
|
|
|
sp = nil;
|
|
|
|
}
|
|
|
|
received = false;
|
|
|
|
FLUSH(&received);
|
2014-01-16 14:35:29 -07:00
|
|
|
runtime·chanrecv(t, c, val, 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
|
|
|
}
|
|
|
|
|
2014-01-17 15:48:45 -07:00
|
|
|
static Select* newselect(int32);
|
2011-02-22 15:40:40 -07:00
|
|
|
|
2008-07-24 16:57:30 -06:00
|
|
|
// newselect(size uint32) (sel *byte);
|
2013-08-12 14:47:18 -06:00
|
|
|
#pragma textflag NOSPLIT
|
2008-07-24 16:57:30 -06:00
|
|
|
void
|
2014-01-17 15:48:45 -07:00
|
|
|
runtime·newselect(int32 size, byte *sel)
|
2008-07-24 16:57:30 -06:00
|
|
|
{
|
2014-01-17 15:48:45 -07:00
|
|
|
sel = (byte*)newselect(size);
|
|
|
|
FLUSH(&sel);
|
2011-02-22 15:40:40 -07:00
|
|
|
}
|
|
|
|
|
2014-01-17 15:48:45 -07:00
|
|
|
static Select*
|
|
|
|
newselect(int32 size)
|
2011-02-22 15:40:40 -07:00
|
|
|
{
|
|
|
|
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);
|
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);
|
2014-01-17 15:48:45 -07:00
|
|
|
return sel;
|
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);
|
2013-08-12 14:47:18 -06:00
|
|
|
#pragma textflag NOSPLIT
|
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);
|
2013-08-12 14:47:18 -06:00
|
|
|
#pragma textflag NOSPLIT
|
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);
|
2013-08-12 14:47:18 -06:00
|
|
|
#pragma textflag NOSPLIT
|
2011-03-11 12:47:26 -07:00
|
|
|
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);
|
2013-08-12 14:47:18 -06:00
|
|
|
#pragma textflag NOSPLIT
|
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)
|
|
|
|
{
|
2013-05-08 15:58:34 -06:00
|
|
|
int32 i, n, r;
|
|
|
|
Hchan *c;
|
2009-12-04 11:57:01 -07:00
|
|
|
|
2013-05-08 15:58:34 -06:00
|
|
|
// We must be very careful here to not touch sel after we have unlocked
|
|
|
|
// the last lock, because sel can be freed right after the last unlock.
|
|
|
|
// Consider the following situation.
|
|
|
|
// First M calls runtime·park() in runtime·selectgo() passing the sel.
|
|
|
|
// Once runtime·park() has unlocked the last lock, another M makes
|
|
|
|
// the G that calls select runnable again and schedules it for execution.
|
|
|
|
// When the G runs on another M, it locks all the locks and frees sel.
|
|
|
|
// Now if the first M touches sel, it will access freed memory.
|
|
|
|
n = (int32)sel->ncase;
|
|
|
|
r = 0;
|
|
|
|
// skip the default case
|
|
|
|
if(n>0 && sel->lockorder[0] == nil)
|
|
|
|
r = 1;
|
|
|
|
for(i = n-1; i >= r; i--) {
|
|
|
|
c = sel->lockorder[i];
|
|
|
|
if(i>0 && sel->lockorder[i-1] == c)
|
|
|
|
continue; // will unlock it on the next iteration
|
|
|
|
runtime·unlock(c);
|
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.
|
2013-08-12 14:47:18 -06:00
|
|
|
#pragma textflag NOSPLIT
|
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;
|
2013-02-19 08:15:13 -07:00
|
|
|
uint32 o, i, j, k;
|
2013-08-14 03:56:01 -06:00
|
|
|
int64 t0;
|
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;
|
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
|
|
|
|
2013-08-14 03:56:01 -06:00
|
|
|
t0 = 0;
|
|
|
|
if(runtime·blockprofilerate > 0) {
|
|
|
|
t0 = runtime·cputicks();
|
|
|
|
for(i=0; i<sel->ncase; i++)
|
|
|
|
sel->scase[i].sg.releasetime = -1;
|
|
|
|
}
|
|
|
|
|
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.
|
2013-02-19 08:15:13 -07:00
|
|
|
// simple heap sort, to guarantee n log n time and constant stack footprint.
|
2011-07-21 11:57:13 -06:00
|
|
|
for(i=0; i<sel->ncase; i++) {
|
2013-02-19 08:15:13 -07:00
|
|
|
j = i;
|
|
|
|
c = sel->scase[j].chan;
|
|
|
|
while(j > 0 && sel->lockorder[k=(j-1)/2] < c) {
|
|
|
|
sel->lockorder[j] = sel->lockorder[k];
|
|
|
|
j = k;
|
|
|
|
}
|
2011-07-21 11:57:13 -06:00
|
|
|
sel->lockorder[j] = c;
|
2009-12-04 11:57:01 -07:00
|
|
|
}
|
2013-02-19 08:15:13 -07:00
|
|
|
for(i=sel->ncase; i-->0; ) {
|
|
|
|
c = sel->lockorder[i];
|
|
|
|
sel->lockorder[i] = sel->lockorder[0];
|
|
|
|
j = 0;
|
|
|
|
for(;;) {
|
|
|
|
k = j*2+1;
|
|
|
|
if(k >= i)
|
|
|
|
break;
|
|
|
|
if(k+1 < i && sel->lockorder[k] < sel->lockorder[k+1])
|
|
|
|
k++;
|
|
|
|
if(c < sel->lockorder[k]) {
|
|
|
|
sel->lockorder[j] = sel->lockorder[k];
|
|
|
|
j = k;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
sel->lockorder[j] = c;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
for(i=0; i+1<sel->ncase; i++)
|
|
|
|
if(sel->lockorder[i] > sel->lockorder[i+1]) {
|
|
|
|
runtime·printf("i=%d %p %p\n", i, sel->lockorder[i], sel->lockorder[i+1]);
|
|
|
|
runtime·throw("select: broken sort");
|
|
|
|
}
|
|
|
|
*/
|
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:
|
2013-06-10 12:58:04 -06:00
|
|
|
if(raceenabled)
|
|
|
|
runtime·racereadpc(c, cas->pc, runtime·chansend);
|
2011-03-11 12:47:26 -07:00
|
|
|
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)
|
2013-04-23 14:46:14 -06:00
|
|
|
runtime·throw("selectgo: shouldn't 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);
|
2013-08-14 03:56:01 -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-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);
|
2013-08-14 03:56:01 -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-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;
|
2013-08-14 03:56:01 -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-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;
|
2013-08-14 03:56:01 -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-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;
|
|
|
|
}
|
2013-08-14 03:56:01 -06:00
|
|
|
if(cas->sg.releasetime > 0)
|
|
|
|
runtime·blockevent(cas->sg.releasetime - t0, 2);
|
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;
|
2014-01-16 14:35:29 -07:00
|
|
|
byte *val;
|
2012-09-18 12:22:41 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
// This enum must match ../reflect/value.go:/SelectDir.
|
|
|
|
enum SelectDir {
|
|
|
|
SelectSend = 1,
|
|
|
|
SelectRecv,
|
|
|
|
SelectDefault,
|
|
|
|
};
|
|
|
|
|
2014-01-16 14:35:29 -07:00
|
|
|
// func rselect(cases []runtimeSelect) (chosen int, recvOK bool)
|
2012-09-18 12:22:41 -06:00
|
|
|
void
|
2014-01-16 14:35:29 -07:00
|
|
|
reflect·rselect(Slice cases, intgo chosen, bool recvOK)
|
2012-09-18 12:22:41 -06:00
|
|
|
{
|
|
|
|
int32 i;
|
|
|
|
Select *sel;
|
|
|
|
runtimeSelect* rcase, *rc;
|
|
|
|
|
|
|
|
chosen = -1;
|
|
|
|
recvOK = false;
|
|
|
|
|
|
|
|
rcase = (runtimeSelect*)cases.array;
|
|
|
|
|
2014-01-17 15:48:45 -07:00
|
|
|
sel = newselect(cases.len);
|
2012-09-18 12:22:41 -06:00
|
|
|
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;
|
2014-01-16 14:35:29 -07:00
|
|
|
selectsend(sel, rc->ch, (void*)i, rc->val, 0);
|
2012-09-18 12:22:41 -06:00
|
|
|
break;
|
|
|
|
case SelectRecv:
|
|
|
|
if(rc->ch == nil)
|
|
|
|
break;
|
2014-01-16 14:35:29 -07:00
|
|
|
selectrecv(sel, rc->ch, (void*)i, rc->val, &recvOK, 0);
|
2012-09-18 12:22:41 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-24 12:58:34 -06:00
|
|
|
chosen = (intgo)(uintptr)selectgo(&sel);
|
2012-09-18 12:22:41 -06:00
|
|
|
|
|
|
|
FLUSH(&chosen);
|
|
|
|
FLUSH(&recvOK);
|
|
|
|
}
|
|
|
|
|
2013-07-22 10:47:39 -06:00
|
|
|
static void closechan(Hchan *c, void *pc);
|
|
|
|
|
2009-03-12 18:55:11 -06:00
|
|
|
// closechan(sel *byte);
|
2013-08-12 14:47:18 -06:00
|
|
|
#pragma textflag NOSPLIT
|
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)
|
2013-07-22 10:47:39 -06:00
|
|
|
{
|
|
|
|
closechan(c, runtime·getcallerpc(&c));
|
|
|
|
}
|
|
|
|
|
|
|
|
// For reflect
|
|
|
|
// func chanclose(c chan)
|
2013-08-12 14:47:18 -06:00
|
|
|
#pragma textflag NOSPLIT
|
2013-07-22 10:47:39 -06:00
|
|
|
void
|
|
|
|
reflect·chanclose(Hchan *c)
|
|
|
|
{
|
|
|
|
closechan(c, runtime·getcallerpc(&c));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
closechan(Hchan *c, void *pc)
|
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
|
|
|
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) {
|
2013-07-22 10:47:39 -06:00
|
|
|
runtime·racewritepc(c, pc, 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;
|
2013-08-14 03:56:01 -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);
|
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;
|
2013-08-14 03:56:01 -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);
|
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
|
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));
|
|
|
|
}
|