Commit 909f3187 authored by Dmitriy Vyukov's avatar Dmitriy Vyukov Committed by Russ Cox

runtime: eliminate false sharing on random number generators

Use machine-local random number generator instead of
racy global ones.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/4674049
parent f9f21aa1
...@@ -1221,17 +1221,6 @@ freesg(Hchan *c, SudoG *sg) ...@@ -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 static uint32
fastrandn(uint32 n) fastrandn(uint32 n)
{ {
...@@ -1240,12 +1229,12 @@ fastrandn(uint32 n) ...@@ -1240,12 +1229,12 @@ fastrandn(uint32 n)
if(n <= 1) if(n <= 1)
return 0; return 0;
r = fastrand1(); r = runtime·fastrand1();
if(r < (1ULL<<31)-n) // avoid computing max in common case if(r < (1ULL<<31)-n) // avoid computing max in common case
return r%n; return r%n;
max = (1ULL<<31)/n * n; max = (1ULL<<31)/n * n;
while(r >= max) while(r >= max)
r = fastrand1(); r = runtime·fastrand1();
return r%n; return r%n;
} }
...@@ -18,21 +18,6 @@ extern MStats mstats; // defined in extern.go ...@@ -18,21 +18,6 @@ extern MStats mstats; // defined in extern.go
extern volatile int32 runtime·MemProfileRate; 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. // Allocate an object of at least size bytes.
// Small objects are allocated from the per-thread cache's free lists. // Small objects are allocated from the per-thread cache's free lists.
// Large objects (> 32 kB) are allocated straight from the heap. // Large objects (> 32 kB) are allocated straight from the heap.
...@@ -97,7 +82,7 @@ runtime·mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed) ...@@ -97,7 +82,7 @@ runtime·mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
// pick next profile time // pick next profile time
if(rate > 0x3fffffff) // make 2*rate not overflow if(rate > 0x3fffffff) // make 2*rate not overflow
rate = 0x3fffffff; rate = 0x3fffffff;
m->mcache->next_sample = fastrand1() % (2*rate); m->mcache->next_sample = runtime·fastrand1() % (2*rate);
profile: profile:
runtime·setblockspecial(v); runtime·setblockspecial(v);
runtime·MProf_Malloc(v, size); runtime·MProf_Malloc(v, size);
......
...@@ -117,6 +117,7 @@ runtime·schedinit(void) ...@@ -117,6 +117,7 @@ runtime·schedinit(void)
runtime·allm = m; runtime·allm = m;
m->nomemprof++; m->nomemprof++;
m->fastrand = 0x49f6428aUL + m->id;
runtime·mallocinit(); runtime·mallocinit();
runtime·goargs(); runtime·goargs();
...@@ -495,6 +496,7 @@ matchmg(void) ...@@ -495,6 +496,7 @@ matchmg(void)
m->alllink = runtime·allm; m->alllink = runtime·allm;
runtime·allm = m; runtime·allm = m;
m->id = runtime·sched.mcount++; m->id = runtime·sched.mcount++;
m->fastrand = 0x49f6428aUL + m->id;
if(runtime·iscgo) { if(runtime·iscgo) {
CgoThreadStart ts; CgoThreadStart ts;
......
...@@ -588,3 +588,16 @@ runtime·FuncForPC(uintptr pc, void *retf) ...@@ -588,3 +588,16 @@ runtime·FuncForPC(uintptr pc, void *retf)
retf = runtime·findfunc(pc); retf = runtime·findfunc(pc);
FLUSH(&retf); FLUSH(&retf);
} }
uint32
runtime·fastrand1(void)
{
uint32 x;
x = m->fastrand;
x += x;
if(x & 0x80000000L)
x ^= 0x88888eefUL;
m->fastrand = x;
return x;
}
...@@ -229,6 +229,7 @@ struct M ...@@ -229,6 +229,7 @@ struct M
int32 waitnextg; int32 waitnextg;
int32 dying; int32 dying;
int32 profilehz; int32 profilehz;
uint32 fastrand;
Note havenextg; Note havenextg;
G* nextg; G* nextg;
M* alllink; // on allm M* alllink; // on allm
...@@ -454,6 +455,7 @@ void runtime·runpanic(Panic*); ...@@ -454,6 +455,7 @@ void runtime·runpanic(Panic*);
void* runtime·getcallersp(void*); void* runtime·getcallersp(void*);
int32 runtime·mcount(void); int32 runtime·mcount(void);
void runtime·mcall(void(*)(G*)); void runtime·mcall(void(*)(G*));
uint32 runtime·fastrand1(void);
void runtime·exit(int32); void runtime·exit(int32);
void runtime·breakpoint(void); void runtime·breakpoint(void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment