summaryrefslogtreecommitdiff
path: root/mysys/thr_mutex.c
diff options
context:
space:
mode:
authorDavi Arnaut <Davi.Arnaut@Sun.COM>2008-10-15 19:21:00 -0300
committerDavi Arnaut <Davi.Arnaut@Sun.COM>2008-10-15 19:21:00 -0300
commit28f29b731383d192064deeab46ab5c6f00ca4ef8 (patch)
tree5c3529f978b6058febb966b44ed713579eb7a036 /mysys/thr_mutex.c
parentd320ca5c484b95eaa2a93e69b81a7e63f6081613 (diff)
downloadmariadb-git-28f29b731383d192064deeab46ab5c6f00ca4ef8.tar.gz
Bug#38941: fast mutexes in MySQL 5.1 have mutex contention when calling random()
The problem is that MySQL's 'fast' mutex implementation uses the random() routine to determine the spin delay. Unfortunately, the routine interface is not thead-safe and some implementations (eg: glibc) might use a internal lock to protect the RNG state, causing excessive locking contention if lots of threads are spinning on a MySQL's 'fast' mutex. The code was also misusing the value of the RAND_MAX macro, this macro represents the largest value that can be returned from the rand() function, not random(). The solution is to use the quite simple Park-Miller random number generator. The initial seed is set to 1 because the previously used generator wasn't being seeded -- the initial seed is 1 if srandom() is not called. Futhermore, the 'fast' mutex implementation has several shortcomings and provides no measurable performance benefit. Therefore, its use is not recommended unless it provides directly measurable results.
Diffstat (limited to 'mysys/thr_mutex.c')
-rw-r--r--mysys/thr_mutex.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c
index 49003553f0b..8f9928026ba 100644
--- a/mysys/thr_mutex.c
+++ b/mysys/thr_mutex.c
@@ -438,9 +438,33 @@ int my_pthread_fastmutex_init(my_pthread_fastmutex_t *mp,
mp->spins= MY_PTHREAD_FASTMUTEX_SPINS;
else
mp->spins= 0;
+ mp->rng_state= 1;
return pthread_mutex_init(&mp->mutex, attr);
}
+/**
+ Park-Miller random number generator. A simple linear congruential
+ generator that operates in multiplicative group of integers modulo n.
+
+ x_{k+1} = (x_k g) mod n
+
+ Popular pair of parameters: n = 2^32 − 5 = 4294967291 and g = 279470273.
+ The period of the generator is about 2^31.
+ Largest value that can be returned: 2147483646 (RAND_MAX)
+
+ Reference:
+
+ S. K. Park and K. W. Miller
+ "Random number generators: good ones are hard to find"
+ Commun. ACM, October 1988, Volume 31, No 10, pages 1192-1201.
+*/
+
+static double park_rng(my_pthread_fastmutex_t *mp)
+{
+ mp->rng_state= ((my_ulonglong)mp->rng_state * 279470273U) % 4294967291U;
+ return (mp->rng_state / 2147483647.0);
+}
+
int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp)
{
int res;
@@ -458,8 +482,7 @@ int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp)
return res;
mutex_delay(maxdelay);
- maxdelay += ((double) random() / (double) RAND_MAX) *
- MY_PTHREAD_FASTMUTEX_DELAY + 1;
+ maxdelay += park_rng(mp) * MY_PTHREAD_FASTMUTEX_DELAY + 1;
}
return pthread_mutex_lock(&mp->mutex);
}