]> granicus.if.org Git - php/commitdiff
Make rand.c thread-safe.
authorSascha Schumann <sas@php.net>
Mon, 13 Dec 1999 18:31:29 +0000 (18:31 +0000)
committerSascha Schumann <sas@php.net>
Mon, 13 Dec 1999 18:31:29 +0000 (18:31 +0000)
ext/standard/basic_functions.c
ext/standard/basic_functions.h
ext/standard/rand.c

index 5f143a840fa358086260f9fca52fecd6fbaf3a73..f45678452983d986d57057b2ad72f76805866729 100644 (file)
@@ -363,11 +363,19 @@ static int _php3_putenv_destructor(putenv_entry *pe)
 
 void test_class_startup(void);
 
+static void basic_globals_ctor(BLS_D)
+{
+       BG(next) = NULL;
+       BG(left) = -1;
+}
+
 PHP_MINIT_FUNCTION(basic)
 {
        ELS_FETCH();
 #ifdef ZTS
-       basic_globals_id = ts_allocate_id(sizeof(php_basic_globals), NULL, NULL);
+       basic_globals_id = ts_allocate_id(sizeof(php_basic_globals), (ts_allocate_ctor) basic_globals_ctor, NULL);
+#else
+       basic_globals_ctor(BLS_C);
 #endif
        
        REGISTER_DOUBLE_CONSTANT("M_PI", M_PI, CONST_CS | CONST_PERSISTENT);
index d5e52ef41b6f4ef97f7d19b3195b87574b5a2f90..7ffe3371e85dbebb1507007a1f17dc5c1a6774b3 100644 (file)
@@ -111,6 +111,18 @@ typedef unsigned int php_stat_len;
 typedef int php_stat_len;
 #endif
 
+#if SIZEOF_INT == 4
+/* Most 32-bit and 64-bit systems have 32-bit ints */
+typedef unsigned int uint32;
+#elif SIZEOF_LONG == 4
+/* 16-bit systems? */
+typedef unsigned long uint32;
+#else
+#error Need type which holds 32 bits
+#endif
+
+#define MT_N (624)
+
 typedef struct {
        HashTable *user_shutdown_function_names;
        HashTable putenv_ht;
@@ -132,6 +144,11 @@ typedef struct {
        php_stat_len CurrentStatLength;
        struct stat sb;
        struct stat lsb;
+
+       /* rand.c */
+       uint32   state[MT_N+1];  /* state vector + 1 extra to not violate ANSI C */
+       uint32   *next;       /* next random value is computed from here */
+       int      left;        /* can *next++ this many times before reloading */
 } php_basic_globals;
 
 #ifdef ZTS
index e7ea2ac493684119cf2731650551db88e9ac6894..d7e9d8bc27e43255aa3c8a4e14e2c68c7a68bc8e 100644 (file)
@@ -27,6 +27,8 @@
 #include "phpmath.h"
 #include "php_rand.h"
 
+#include "basic_functions.h"
+
 /*
    This is the ``Mersenne Twister'' random number generator MT19937, which
    generates pseudorandom integers uniformly distributed in 0..(2^32 - 1)
    uint32 must be an unsigned integer type capable of holding at least 32
    bits; exactly 32 should be fastest, but 64 is better on an Alpha with
    GCC at -O3 optimization so try your options and see what's best for you
-  
+
    Melo: we should put some ifdefs here to catch those alphas...
 */
 
-typedef unsigned int uint32;
 
-#define N             (624)                /* length of state vector */
+#define N             MT_N                 /* length of state vector */
 #define M             (397)                /* a period parameter */
 #define K             (0x9908B0DFU)        /* a magic constant */
 #define hiBit(u)      ((u) & 0x80000000U)  /* mask all but highest   bit of u */
@@ -91,12 +92,7 @@ typedef unsigned int uint32;
 #define loBits(u)     ((u) & 0x7FFFFFFFU)  /* mask     the highest   bit of u */
 #define mixBits(u, v) (hiBit(u)|loBits(v)) /* move hi bit of u to hi bit of v */
 
-static uint32   state[N+1];  /* state vector + 1 extra to not violate ANSI C */
-static uint32   *next;       /* next random value is computed from here */
-static int      left = -1;   /* can *next++ this many times before reloading */
-
-
-static void seedMT(uint32 seed)
+static void seedMT(uint32 seed BLS_DC)
 {
     /*
        We initialize state[0..(N-1)] via the generator
@@ -144,31 +140,31 @@ static void seedMT(uint32 seed)
        so-- that's why the only change I made is to restrict to odd seeds.
     */
 
-    register uint32 x = (seed | 1U) & 0xFFFFFFFFU, *s = state;
+    register uint32 x = (seed | 1U) & 0xFFFFFFFFU, *s = BG(state);
     register int    j;
 
-    for(left=0, *s++=x, j=N; --j;
+    for(BG(left)=0, *s++=x, j=N; --j;
         *s++ = (x*=69069U) & 0xFFFFFFFFU);
 }
 
 
-static uint32 reloadMT(void)
+static uint32 reloadMT(BLS_D)
 {
-    register uint32 *p0=state, *p2=state+2, *pM=state+M, s0, s1;
+    register uint32 *p0=BG(state), *p2=BG(state)+2, *pM=BG(state)+M, s0, s1;
     register int    j;
 
-    if(left < -1)
-        seedMT(4357U);
+    if(BG(left) < -1)
+        seedMT(4357U BLS_CC);
 
-    left=N-1, next=state+1;
+    BG(left)=N-1, BG(next)=BG(state)+1;
 
-    for(s0=state[0], s1=state[1], j=N-M+1; --j; s0=s1, s1=*p2++)
+    for(s0=BG(state)[0], s1=BG(state)[1], j=N-M+1; --j; s0=s1, s1=*p2++)
         *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
 
-    for(pM=state, j=M; --j; s0=s1, s1=*p2++)
+    for(pM=BG(state), j=M; --j; s0=s1, s1=*p2++)
         *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
 
-    s1=state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
+    s1=BG(state)[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
     s1 ^= (s1 >> 11);
     s1 ^= (s1 <<  7) & 0x9D2C5680U;
     s1 ^= (s1 << 15) & 0xEFC60000U;
@@ -179,11 +175,12 @@ static uint32 reloadMT(void)
 static inline uint32 randomMT(void)
 {
     uint32 y;
+       BLS_FETCH();
 
-    if(--left < 0)
-        return(reloadMT());
+    if(--BG(left) < 0)
+        return(reloadMT(BLS_C));
 
-    y  = *next++;
+    y  = *BG(next)++;
     y ^= (y >> 11);
     y ^= (y <<  7) & 0x9D2C5680U;
     y ^= (y << 15) & 0xEFC60000U;
@@ -217,12 +214,13 @@ PHP_FUNCTION(srand)
 PHP_FUNCTION(mt_srand)
 {
        pval **arg;
+       BLS_FETCH();
 
        if (ARG_COUNT(ht) != 1 || getParametersEx(1, &arg) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
        convert_to_long_ex(arg);
-       seedMT((*arg)->value.lval);
+       seedMT((*arg)->value.lval BLS_CC);
 }
 /* }}} */