]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: generate type info for chans
authorDmitriy Vyukov <dvyukov@google.com>
Tue, 29 Jul 2014 18:06:47 +0000 (22:06 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Tue, 29 Jul 2014 18:06:47 +0000 (22:06 +0400)
LGTM=khr
R=golang-codereviews, khr
CC=golang-codereviews, khr
https://golang.org/cl/115280043

src/pkg/runtime/chan.goc
src/pkg/runtime/chan.h
src/pkg/runtime/proc.c
src/pkg/runtime/runtime.h

index 39d53aa16ee370382473de79a477b17158e9e1e2..b3520b60fca2224fc266aadcd4e019d6feee07e2 100644 (file)
@@ -9,16 +9,40 @@ package runtime
 #include "race.h"
 #include "malloc.h"
 #include "chan.h"
+#include "mgc0.h"
+#include "typekind.h"
 #include "../../cmd/ld/textflag.h"
 
-uint32 runtime·Hchansize = sizeof(Hchan);
-
 static void    dequeueg(WaitQ*);
 static SudoG*  dequeue(WaitQ*);
 static void    enqueue(WaitQ*, SudoG*);
-static void    destroychan(Hchan*);
 static void    racesync(Hchan*, SudoG*);
 
+static Type    hchanType;
+static String  hchanStr;
+
+void
+runtime·chaninit(void)
+{
+       int32 i, off;
+       byte *mask;
+
+       // Generate (bare minimum) type descriptor for Hchan.
+       hchanType.size = sizeof(Hchan);
+       hchanStr = runtime·gostringnocopy((byte*)"chan");
+       hchanType.string = &hchanStr;
+       // Hchan has only one interesting pointer -- buf.
+       off = offsetof(Hchan, buf)/PtrSize*gcBits;
+       if(off%8)
+               runtime·throw("makechan: unaligned buffer");
+       if(off+8 >= sizeof(hchanType.gc)*8)
+               runtime·throw("makechan: gc mask does not fit");
+       mask = (byte*)hchanType.gc;
+       for(i = 0; i < off/8; i++)
+               mask[i] = (BitsScalar<<2) | (BitsScalar<<6);
+       mask[off/8] = (BitsPointer<<2) | (BitsDead<<6);
+}
+
 static Hchan*
 makechan(ChanType *t, int64 hint)
 {
@@ -36,8 +60,17 @@ makechan(ChanType *t, int64 hint)
        if(hint < 0 || (intgo)hint != hint || (elem->size > 0 && hint > (MaxMem - sizeof(*c)) / elem->size))
                runtime·panicstring("makechan: size out of range");
 
-       // allocate memory in one call
-       c = (Hchan*)runtime·mallocgc(sizeof(*c) + hint*elem->size, nil, 0);
+       if((elem->kind&KindNoPointers) || hint == 0) {
+               // allocate memory in one call
+               c = (Hchan*)runtime·mallocgc(sizeof(*c) + hint*elem->size, nil, FlagNoScan);
+               if(hint > 0 && elem->size != 0)
+                       c->buf = (byte*)(c+1);
+               else
+                       c->buf = (byte*)c;  // race detector uses this location for synchronization
+       } else {
+               c = (Hchan*)runtime·cnew(&hchanType);
+               c->buf = runtime·cnewarray(elem, hint);
+       }
        c->elemsize = elem->size;
        c->elemtype = elem;
        c->dataqsiz = hint;
index b23b3417fedd098ba9198f2637efc71969c6dc35..043ef7d21c8aef96628bfb2ee959ddcdcec2d018 100644 (file)
@@ -26,14 +26,12 @@ struct      WaitQ
        SudoG*  last;
 };
 
-// The garbage collector is assuming that Hchan can only contain pointers into the stack
-// and cannot contain pointers into the heap.
 struct Hchan
 {
        uintgo  qcount;                 // total data in the q
        uintgo  dataqsiz;               // size of the circular q
+       byte*   buf;
        uint16  elemsize;
-       uint16  pad;                    // ensures proper alignment of the buffer that follows Hchan in memory
        bool    closed;
        Type*   elemtype;               // element type
        uintgo  sendx;                  // send index
@@ -45,7 +43,7 @@ struct        Hchan
 
 // 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))
+#define chanbuf(c, i) ((byte*)((c)->buf)+(uintptr)(c)->elemsize*(i))
 
 enum
 {
index 9ccb1751e4fc934af5c8ae1d77f7e6fc57f7d67b..1e7fdd421ec94a5066385a07ac5bdfb70ea26dea 100644 (file)
@@ -158,6 +158,7 @@ runtime·schedinit(void)
        runtime·symtabinit();
        runtime·stackinit();
        runtime·mallocinit();
+       runtime·chaninit();
        mcommoninit(g->m);
        
        // Initialize the itable value for newErrorCString,
index ecff3f3b792ce2e43572f913c936978cfa0c772b..d21112de5a042eafec269cdc42ad43a63fe6ef71 100644 (file)
@@ -862,6 +862,7 @@ void        runtime·shrinkstack(G*);
 MCache*        runtime·allocmcache(void);
 void   runtime·freemcache(MCache*);
 void   runtime·mallocinit(void);
+void   runtime·chaninit(void);
 bool   runtime·ifaceeq_c(Iface, Iface);
 bool   runtime·efaceeq_c(Eface, Eface);
 uintptr        runtime·ifacehash(Iface, uintptr);