summaryrefslogtreecommitdiff
path: root/ext/standard/lcg.c
diff options
context:
space:
mode:
authorSascha Schumann <sas@php.net>2001-09-21 13:38:44 +0000
committerSascha Schumann <sas@php.net>2001-09-21 13:38:44 +0000
commit9002e37e4e25cf751d675612bdde48316c1a0613 (patch)
tree9ac38f3f3d5b26c6147cf9f8a48114f9df80756d /ext/standard/lcg.c
parent78fb121a61f5b940308ad33ab8db66c685b0ecba (diff)
downloadphp-git-9002e37e4e25cf751d675612bdde48316c1a0613.tar.gz
Always seed the LCG from the request-init hook, otherwise the seed
would be shared among the threads which is quite pointless. Also use a function of the current time as one factor. Use gettimeofday() instead of time(), because it is faster on some operating systems.
Diffstat (limited to 'ext/standard/lcg.c')
-rw-r--r--ext/standard/lcg.c39
1 files changed, 28 insertions, 11 deletions
diff --git a/ext/standard/lcg.c b/ext/standard/lcg.c
index 91863d0a48..a76725ec38 100644
--- a/ext/standard/lcg.c
+++ b/ext/standard/lcg.c
@@ -25,11 +25,14 @@
#include <unistd.h>
#endif
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
#ifdef ZTS
int lcg_globals_id;
#else
static php_lcg_globals lcg_globals;
-static int php_lcg_initialized = 0;
#endif
@@ -46,7 +49,7 @@ static int php_lcg_initialized = 0;
#define MODMULT(a, b, c, m, s) q = s/a;s=b*(s-a*q)-c*q;if(s<0)s+=m
-double php_combined_lcg(TSRMLS_D)
+PHPAPI double php_combined_lcg(TSRMLS_D)
{
php_int32 q;
php_int32 z;
@@ -55,39 +58,53 @@ double php_combined_lcg(TSRMLS_D)
MODMULT(52774, 40692, 3791, 2147483399L, LCG(s2));
z = LCG(s1) - LCG(s2);
- if(z < 1) {
+ if (z < 1) {
z += 2147483562;
}
return z * 4.656613e-10;
}
-static void lcg_init_globals(php_lcg_globals *lcg_globals_p TSRMLS_DC)
+static void lcg_seed(TSRMLS_D)
{
- LCG(s1) = 1;
+ struct timeval tv;
+
+ if (gettimeofday(&tv, NULL) == 0) {
+ LCG(s1) = tv.tv_sec ^ (~tv.tv_usec);
+ } else {
+ LCG(s1) = 1;
+ }
#ifdef ZTS
LCG(s2) = (long) tsrm_thread_id();
#else
LCG(s2) = (long) getpid();
#endif
+
+ LCG(seeded) = 1;
+}
+
+static void lcg_init_globals(php_lcg_globals *lcg_globals_p TSRMLS_DC)
+{
+ LCG(seeded) = 0;
}
-#ifdef ZTS
PHP_MINIT_FUNCTION(lcg)
{
+#ifdef ZTS
ts_allocate_id(&lcg_globals_id, sizeof(php_lcg_globals), (ts_allocate_ctor) lcg_init_globals, NULL);
+#else
+ lcg_init_globals(&lcg_globals);
+#endif
return SUCCESS;
}
-#else
+
PHP_RINIT_FUNCTION(lcg)
{
- if (!php_lcg_initialized) {
- lcg_init_globals(&lcg_globals TSRMLS_CC);
- php_lcg_initialized = 1;
+ if (!LCG(seeded)) {
+ lcg_seed(TSRMLS_C);
}
return SUCCESS;
}
-#endif
/* {{{ proto double lcg_value()
Returns a value from the combined linear congruential generator */