]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: eliminate false sharing on random number generators
authorDmitriy Vyukov <dvyukov@google.com>
Tue, 12 Jul 2011 05:23:58 +0000 (01:23 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 12 Jul 2011 05:23:58 +0000 (01:23 -0400)
Use machine-local random number generator instead of
racy global ones.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/4674049

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

index f94c3ef40a36b78c7c869afcd2fc3d7bf2c1409a..78f67b817c0002439046653ca82ee7932c4aa6e4 100644 (file)
@@ -1221,17 +1221,6 @@ freesg(Hchan *c, SudoG *sg)
        }
 }
 
-static uint32
-fastrand1(void)
-{
-       static uint32 x = 0x49f6428aUL;
-
-       x += x;
-       if(x & 0x80000000L)
-               x ^= 0x88888eefUL;
-       return x;
-}
-
 static uint32
 fastrandn(uint32 n)
 {
@@ -1240,12 +1229,12 @@ fastrandn(uint32 n)
        if(n <= 1)
                return 0;
 
-       r = fastrand1();
+       r = runtime·fastrand1();
        if(r < (1ULL<<31)-n)  // avoid computing max in common case
                return r%n;
 
        max = (1ULL<<31)/n * n;
        while(r >= max)
-               r = fastrand1();
+               r = runtime·fastrand1();
        return r%n;
 }
index 49ab24df86eabd896b2cbe9b0f047153d492b7bf..696a99827624de4c151dce083d276d4325fa315b 100644 (file)
@@ -18,21 +18,6 @@ extern MStats mstats;        // defined in extern.go
 
 extern volatile int32 runtime·MemProfileRate;
 
-// Same algorithm from chan.c, but a different
-// instance of the static uint32 x.
-// Not protected by a lock - let the threads use
-// the same random number if they like.
-static uint32
-fastrand1(void)
-{
-       static uint32 x = 0x49f6428aUL;
-
-       x += x;
-       if(x & 0x80000000L)
-               x ^= 0x88888eefUL;
-       return x;
-}
-
 // Allocate an object of at least size bytes.
 // Small objects are allocated from the per-thread cache's free lists.
 // Large objects (> 32 kB) are allocated straight from the heap.
@@ -97,7 +82,7 @@ runtime·mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
                        // pick next profile time
                        if(rate > 0x3fffffff)   // make 2*rate not overflow
                                rate = 0x3fffffff;
-                       m->mcache->next_sample = fastrand1() % (2*rate);
+                       m->mcache->next_sample = runtime·fastrand1() % (2*rate);
                profile:
                        runtime·setblockspecial(v);
                        runtime·MProf_Malloc(v, size);
index a8f3a796acb3cffdc83a2850ce2367223f7a7b1f..814a68e2ec6dff0cfae235caf34332a1c0121f79 100644 (file)
@@ -117,6 +117,7 @@ runtime·schedinit(void)
 
        runtime·allm = m;
        m->nomemprof++;
+       m->fastrand = 0x49f6428aUL + m->id;
 
        runtime·mallocinit();
        runtime·goargs();
@@ -495,6 +496,7 @@ matchmg(void)
                        m->alllink = runtime·allm;
                        runtime·allm = m;
                        m->id = runtime·sched.mcount++;
+                       m->fastrand = 0x49f6428aUL + m->id;
 
                        if(runtime·iscgo) {
                                CgoThreadStart ts;
index 1a3653f108c457dbac460f1f88339e92fbd3ab3f..83af8dc5e2f680a4a10c2d473c654b54be9a02b4 100644 (file)
@@ -588,3 +588,16 @@ runtime·FuncForPC(uintptr pc, void *retf)
        retf = runtime·findfunc(pc);
        FLUSH(&retf);
 }
+
+uint32
+runtime·fastrand1(void)
+{
+       uint32 x;
+
+       x = m->fastrand;
+       x += x;
+       if(x & 0x80000000L)
+               x ^= 0x88888eefUL;
+       m->fastrand = x;
+       return x;
+}
index ad5da0a96269f0364bfa2ce7b982cb2472f76994..48cd482dd9012e46793a5b616cf44f4b1cf0c951 100644 (file)
@@ -229,6 +229,7 @@ struct      M
        int32   waitnextg;
        int32   dying;
        int32   profilehz;
+       uint32  fastrand;
        Note    havenextg;
        G*      nextg;
        M*      alllink;        // on allm
@@ -454,6 +455,7 @@ void        runtime·runpanic(Panic*);
 void*  runtime·getcallersp(void*);
 int32  runtime·mcount(void);
 void   runtime·mcall(void(*)(G*));
+uint32 runtime·fastrand1(void);
 
 void   runtime·exit(int32);
 void   runtime·breakpoint(void);