Fixes #284: LJ_PRNG_BITS() is too weak for multi-threaded applications

Replace LGC used by LJ_PRNG_BITS() with SplitMix64. Also, see it in
lua_newstate() with rand() to generated different sequence in multiple
concurrent threads.
This commit is contained in:
Alexey Kopytov 2017-02-25 17:27:32 +03:00
parent a25c0b99b8
commit 7d0a1f7699
2 changed files with 7 additions and 5 deletions

View File

@ -450,7 +450,7 @@ typedef struct jit_State {
HotPenalty penalty[PENALTY_SLOTS]; /* Penalty slots. */ HotPenalty penalty[PENALTY_SLOTS]; /* Penalty slots. */
uint32_t penaltyslot; /* Round-robin index into penalty slots. */ uint32_t penaltyslot; /* Round-robin index into penalty slots. */
uint32_t prngstate; /* PRNG state. */ uint64_t prngstate; /* PRNG state. */
#ifdef LUAJIT_ENABLE_TABLE_BUMP #ifdef LUAJIT_ENABLE_TABLE_BUMP
RBCHashEntry rbchash[RBCHASH_SLOTS]; /* Reverse bytecode map. */ RBCHashEntry rbchash[RBCHASH_SLOTS]; /* Reverse bytecode map. */
@ -488,12 +488,13 @@ LJ_ALIGN(16) /* For DISPATCH-relative addresses in assembler part. */
#endif #endif
jit_State; jit_State;
/* Trivial PRNG e.g. used for penalty randomization. */ /* SplitMix64 PRNG based on http://xoroshiro.di.unimi.it/splitmix64.c */
static LJ_AINLINE uint32_t LJ_PRNG_BITS(jit_State *J, int bits) static LJ_AINLINE uint32_t LJ_PRNG_BITS(jit_State *J, int bits)
{ {
/* Yes, this LCG is very weak, but that doesn't matter for our use case. */ uint64_t z = (J->prngstate += UINT64_C(0x9E3779B97F4A7C15));
J->prngstate = J->prngstate * 1103515245 + 12345; z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9);
return J->prngstate >> (32-bits); z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB);
return z >> (64-bits);
} }
#endif #endif

View File

@ -225,6 +225,7 @@ LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud)
return NULL; return NULL;
} }
L->status = 0; L->status = 0;
G2J(g)->prngstate = rand();
return L; return L;
} }