33 *
44 * \brief GIS Library - Pseudo-random number generation
55 *
6- * (C) 2014 by the GRASS Development Team
6+ * (C) 2014, 2025 by the GRASS Development Team
77 *
88 * This program is free software under the GNU General Public License
99 * (>=v2). Read the file COPYING that comes with GRASS for details.
1010 *
11- * \author Glynn Clements
11+ * \authors Glynn Clements, Maris Nartiss (thread safety)
1212 */
1313
1414#include <stdio.h>
1919#include <grass/gis.h>
2020#include <grass/glocale.h>
2121
22+ #ifdef HAVE_PTHREAD
23+ #include <pthread.h>
24+ #endif
25+
2226#ifdef HAVE_GETTIMEOFDAY
2327#include <sys/time.h>
2428#else
@@ -41,22 +45,36 @@ static const uint32 b0 = 0xB;
4145
4246static int seeded ;
4347
48+ #ifdef HAVE_PTHREAD
49+ static pthread_mutex_t lrand48_mutex = PTHREAD_MUTEX_INITIALIZER ;
50+ #endif
51+
4452#define LO (x ) ((x) & 0xFFFFU)
4553#define HI (x ) ((x) >> 16)
4654
4755/*!
4856 * \brief Seed the pseudo-random number generator
4957 *
5058 * \param[in] seedval 32-bit integer used to seed the PRNG
59+ *
60+ * This function is thread-safe.
5161 */
5262void G_srand48 (long seedval )
5363{
5464 uint32 x = (uint32 ) * (unsigned long * )& seedval ;
5565
66+ #ifdef HAVE_PTHREAD
67+ pthread_mutex_lock (& lrand48_mutex );
68+ #endif
69+
5670 x2 = (uint16 )HI (x );
5771 x1 = (uint16 )LO (x );
5872 x0 = (uint16 )0x330E ;
5973 seeded = 1 ;
74+
75+ #ifdef HAVE_PTHREAD
76+ pthread_mutex_unlock (& lrand48_mutex );
77+ #endif
6078}
6179
6280/*!
@@ -65,6 +83,8 @@ void G_srand48(long seedval)
6583 * A weak hash of the current time and PID is generated and used to
6684 * seed the PRNG
6785 *
86+ * This function is thread-safe.
87+ *
6888 * \return generated seed value passed to G_srand48()
6989 */
7090long G_srand48_auto (void )
@@ -104,6 +124,10 @@ long G_srand48_auto(void)
104124
105125static void G__next (void )
106126{
127+ #ifdef HAVE_PTHREAD
128+ pthread_mutex_lock (& lrand48_mutex );
129+ #endif
130+
107131 uint32 a0x0 = a0 * x0 ;
108132 uint32 a0x1 = a0 * x1 ;
109133 uint32 a0x2 = a0 * x2 ;
@@ -123,11 +147,17 @@ static void G__next(void)
123147 x1 = (uint16 )LO (y1 );
124148 y2 += HI (y1 );
125149 x2 = (uint16 )LO (y2 );
150+
151+ #ifdef HAVE_PTHREAD
152+ pthread_mutex_unlock (& lrand48_mutex );
153+ #endif
126154}
127155
128156/*!
129157 * \brief Generate an integer in the range [0, 2^31)
130158 *
159+ * This function is thread-safe.
160+ *
131161 * \return the generated value
132162 */
133163long G_lrand48 (void )
@@ -142,6 +172,8 @@ long G_lrand48(void)
142172/*!
143173 * \brief Generate an integer in the range [-2^31, 2^31)
144174 *
175+ * This function is thread-safe.
176+ *
145177 * \return the generated value
146178 */
147179long G_mrand48 (void )
@@ -156,6 +188,8 @@ long G_mrand48(void)
156188/*!
157189 * \brief Generate a floating-point value in the range [0,1)
158190 *
191+ * This function is thread-safe.
192+ *
159193 * \return the generated value
160194 */
161195double G_drand48 (void )
0 commit comments