While POSIX mandates that random() is multithread-safe [1][2], rand() is not
required to be multithread-safe [3].

Therefore, in tests where multiple threads fetch pseudo-random numbers,
we better use rand(), even if that requires extra code on native Windows.

[1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/initstate.html
[2] 
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_407
[3] https://pubs.opengroup.org/onlinepubs/9699919799/functions/rand.html


2023-11-10  Bruno Haible  <br...@clisp.org>

        tests: In multithreaded tests, use random() instead of rand().
        * tests/test-asyncsafe-spin2.c (random_account, lock_mutator_thread):
        Use random() instead of rand().
        * tests/test-lock.c (random_account, lock_mutator_thread,
        rwlock_mutator_thread, recshuffle): Likewise.
        * tests/test-mtx.c (random_account, lock_mutator_thread, recshuffle):
        Likewise.
        * tests/test-pthread-mutex.c (random_account, lock_mutator_thread,
        recshuffle): Likewise.
        * tests/test-pthread-rwlock.c (random_account, rwlock_mutator_thread):
        Likewise.
        * tests/test-pthread-spin.c (random_account, lock_mutator_thread):
        Likewise.
        * tests/test-pthread-tss.c (perhaps_yield, worker_thread,
        racecheck_thread): Likewise.
        * tests/test-thread_local.c (perhaps_yield, worker_thread): Likewise.
        * tests/test-tls.c (perhaps_yield, worker_thread, racecheck_thread):
        Likewise.
        * tests/test-tss.c (perhaps_yield, worker_thread, racecheck_thread):
        Likewise.
        * asyncsafe-spin-tests (Depends-on): Add random.
        * lock-tests (Depends-on): Likewise.
        * mtx-tests (Depends-on): Likewise.
        * pthread-mutex-tests (Depends-on): Likewise.
        * pthread-rwlock-tests (Depends-on): Likewise.
        * pthread-spin-tests (Depends-on): Likewise.
        * pthread-tss-tests (Depends-on): Likewise.
        * threads-h-tests (Depends-on): Likewise.
        * tls-tests (Depends-on): Likewise.
        * tss-tests (Depends-on): Likewise.

diff --git a/modules/asyncsafe-spin-tests b/modules/asyncsafe-spin-tests
index 301c2afc1a..dacb26aaac 100644
--- a/modules/asyncsafe-spin-tests
+++ b/modules/asyncsafe-spin-tests
@@ -8,6 +8,7 @@ Depends-on:
 thread
 lock
 yield
+random
 
 configure.ac:
 AC_CHECK_HEADERS_ONCE([semaphore.h])
diff --git a/modules/lock-tests b/modules/lock-tests
index 502c36882f..7b398e2327 100644
--- a/modules/lock-tests
+++ b/modules/lock-tests
@@ -11,6 +11,7 @@ thread
 stdint
 usleep
 yield
+random
 
 configure.ac:
 AC_CHECK_HEADERS_ONCE([semaphore.h])
diff --git a/modules/mtx-tests b/modules/mtx-tests
index 4a021d22fa..063a56d67f 100644
--- a/modules/mtx-tests
+++ b/modules/mtx-tests
@@ -7,6 +7,7 @@ Depends-on:
 thrd
 lock
 stdint
+random
 
 configure.ac:
 AC_CHECK_HEADERS_ONCE([semaphore.h])
diff --git a/modules/pthread-mutex-tests b/modules/pthread-mutex-tests
index 4575ef5c79..9475a84a99 100644
--- a/modules/pthread-mutex-tests
+++ b/modules/pthread-mutex-tests
@@ -6,6 +6,7 @@ tests/macros.h
 Depends-on:
 pthread-thread
 sched_yield
+random
 
 configure.ac:
 
diff --git a/modules/pthread-rwlock-tests b/modules/pthread-rwlock-tests
index af29895580..129570b67d 100644
--- a/modules/pthread-rwlock-tests
+++ b/modules/pthread-rwlock-tests
@@ -7,6 +7,7 @@ Depends-on:
 pthread-thread
 pthread-mutex
 sched_yield
+random
 
 configure.ac:
 
diff --git a/modules/pthread-spin-tests b/modules/pthread-spin-tests
index 9dfa698ca4..4aec8e20be 100644
--- a/modules/pthread-spin-tests
+++ b/modules/pthread-spin-tests
@@ -8,6 +8,7 @@ Depends-on:
 pthread-thread
 pthread-mutex
 sched_yield
+random
 
 configure.ac:
 AC_CHECK_HEADERS_ONCE([semaphore.h])
diff --git a/modules/pthread-tss-tests b/modules/pthread-tss-tests
index 1d339345dd..c3060b5ee5 100644
--- a/modules/pthread-tss-tests
+++ b/modules/pthread-tss-tests
@@ -6,6 +6,7 @@ Depends-on:
 pthread-thread
 pthread-mutex
 sched_yield
+random
 
 configure.ac:
 
diff --git a/modules/threads-h-tests b/modules/threads-h-tests
index abbd43aca5..c9195e5f56 100644
--- a/modules/threads-h-tests
+++ b/modules/threads-h-tests
@@ -7,6 +7,7 @@ Depends-on:
 threads-h-c++-tests
 thrd
 stdint
+random
 
 configure.ac:
 AC_CHECK_DECLS_ONCE([alarm])
diff --git a/modules/tls-tests b/modules/tls-tests
index aec1935afc..2eed659425 100644
--- a/modules/tls-tests
+++ b/modules/tls-tests
@@ -6,6 +6,7 @@ thread
 lock
 stdint
 yield
+random
 
 configure.ac:
 AC_CHECK_DECLS_ONCE([alarm])
diff --git a/modules/tss-tests b/modules/tss-tests
index c96c10d002..3526d22c28 100644
--- a/modules/tss-tests
+++ b/modules/tss-tests
@@ -6,6 +6,7 @@ Depends-on:
 thrd
 mtx
 stdint
+random
 
 configure.ac:
 AC_CHECK_DECLS_ONCE([alarm])
diff --git a/tests/test-asyncsafe-spin2.c b/tests/test-asyncsafe-spin2.c
index ac4eab52c3..9824aef66c 100644
--- a/tests/test-asyncsafe-spin2.c
+++ b/tests/test-asyncsafe-spin2.c
@@ -95,7 +95,7 @@ static int account[ACCOUNT_COUNT];
 static int
 random_account (void)
 {
-  return ((unsigned int) rand () >> 3) % ACCOUNT_COUNT;
+  return ((unsigned long) random () >> 3) % ACCOUNT_COUNT;
 }
 
 static void
@@ -135,7 +135,7 @@ lock_mutator_thread (void *arg)
 
       i1 = random_account ();
       i2 = random_account ();
-      value = ((unsigned int) rand () >> 3) % 10;
+      value = ((unsigned long) random () >> 3) % 10;
       account[i1] += value;
       account[i2] -= value;
 
diff --git a/tests/test-lock.c b/tests/test-lock.c
index d7fcec0235..cf5504d146 100644
--- a/tests/test-lock.c
+++ b/tests/test-lock.c
@@ -118,7 +118,7 @@ static int account[ACCOUNT_COUNT];
 static int
 random_account (void)
 {
-  return ((unsigned int) rand () >> 3) % ACCOUNT_COUNT;
+  return ((unsigned long) random () >> 3) % ACCOUNT_COUNT;
 }
 
 static void
@@ -157,7 +157,7 @@ lock_mutator_thread (_GL_UNUSED void *arg)
 
       i1 = random_account ();
       i2 = random_account ();
-      value = ((unsigned int) rand () >> 3) % 10;
+      value = ((unsigned long) random () >> 3) % 10;
       account[i1] += value;
       account[i2] -= value;
 
@@ -248,7 +248,7 @@ rwlock_mutator_thread (_GL_UNUSED void *arg)
 
       i1 = random_account ();
       i2 = random_account ();
-      value = ((unsigned int) rand () >> 3) % 10;
+      value = ((unsigned long) random () >> 3) % 10;
       account[i1] += value;
       account[i2] -= value;
 
@@ -331,12 +331,12 @@ recshuffle (void)
 
   i1 = random_account ();
   i2 = random_account ();
-  value = ((unsigned int) rand () >> 3) % 10;
+  value = ((unsigned long) random () >> 3) % 10;
   account[i1] += value;
   account[i2] -= value;
 
   /* Recursive with probability 0.5.  */
-  if (((unsigned int) rand () >> 3) % 2)
+  if (((unsigned long) random () >> 3) % 2)
     recshuffle ();
 
   dbgprintf ("Mutator %p before unlock\n", gl_thread_self_pointer ());
diff --git a/tests/test-mtx.c b/tests/test-mtx.c
index b00a9a554a..7e7d9a6a2c 100644
--- a/tests/test-mtx.c
+++ b/tests/test-mtx.c
@@ -92,7 +92,7 @@ static int account[ACCOUNT_COUNT];
 static int
 random_account (void)
 {
-  return ((unsigned int) rand () >> 3) % ACCOUNT_COUNT;
+  return ((unsigned long) random () >> 3) % ACCOUNT_COUNT;
 }
 
 static void
@@ -131,7 +131,7 @@ lock_mutator_thread (void *arg)
 
       i1 = random_account ();
       i2 = random_account ();
-      value = ((unsigned int) rand () >> 3) % 10;
+      value = ((unsigned long) random () >> 3) % 10;
       account[i1] += value;
       account[i2] -= value;
 
@@ -220,12 +220,12 @@ recshuffle (void)
 
   i1 = random_account ();
   i2 = random_account ();
-  value = ((unsigned int) rand () >> 3) % 10;
+  value = ((unsigned long) random () >> 3) % 10;
   account[i1] += value;
   account[i2] -= value;
 
   /* Recursive with probability 0.5.  */
-  if (((unsigned int) rand () >> 3) % 2)
+  if (((unsigned long) random () >> 3) % 2)
     recshuffle ();
 
   dbgprintf ("Mutator %p before unlock\n", thrd_current_pointer ());
diff --git a/tests/test-pthread-mutex.c b/tests/test-pthread-mutex.c
index 4f093eb25f..ca698093a4 100644
--- a/tests/test-pthread-mutex.c
+++ b/tests/test-pthread-mutex.c
@@ -93,7 +93,7 @@ static int account[ACCOUNT_COUNT];
 static int
 random_account (void)
 {
-  return ((unsigned int) rand () >> 3) % ACCOUNT_COUNT;
+  return ((unsigned long) random () >> 3) % ACCOUNT_COUNT;
 }
 
 static void
@@ -132,7 +132,7 @@ lock_mutator_thread (void *arg)
 
       i1 = random_account ();
       i2 = random_account ();
-      value = ((unsigned int) rand () >> 3) % 10;
+      value = ((unsigned long) random () >> 3) % 10;
       account[i1] += value;
       account[i2] -= value;
 
@@ -220,12 +220,12 @@ recshuffle (void)
 
   i1 = random_account ();
   i2 = random_account ();
-  value = ((unsigned int) rand () >> 3) % 10;
+  value = ((unsigned long) random () >> 3) % 10;
   account[i1] += value;
   account[i2] -= value;
 
   /* Recursive with probability 0.5.  */
-  if (((unsigned int) rand () >> 3) % 2)
+  if (((unsigned long) random () >> 3) % 2)
     recshuffle ();
 
   dbgprintf ("Mutator %p before unlock\n", pthread_self_pointer ());
diff --git a/tests/test-pthread-rwlock.c b/tests/test-pthread-rwlock.c
index d4a59812ff..467357abd6 100644
--- a/tests/test-pthread-rwlock.c
+++ b/tests/test-pthread-rwlock.c
@@ -87,7 +87,7 @@ static int account[ACCOUNT_COUNT];
 static int
 random_account (void)
 {
-  return ((unsigned int) rand () >> 3) % ACCOUNT_COUNT;
+  return ((unsigned long) random () >> 3) % ACCOUNT_COUNT;
 }
 
 static void
@@ -126,7 +126,7 @@ rwlock_mutator_thread (void *arg)
 
       i1 = random_account ();
       i2 = random_account ();
-      value = ((unsigned int) rand () >> 3) % 10;
+      value = ((unsigned long) random () >> 3) % 10;
       account[i1] += value;
       account[i2] -= value;
 
diff --git a/tests/test-pthread-spin.c b/tests/test-pthread-spin.c
index ede62e33dd..8abe9cfb72 100644
--- a/tests/test-pthread-spin.c
+++ b/tests/test-pthread-spin.c
@@ -85,7 +85,7 @@ static int account[ACCOUNT_COUNT];
 static int
 random_account (void)
 {
-  return ((unsigned int) rand () >> 3) % ACCOUNT_COUNT;
+  return ((unsigned long) random () >> 3) % ACCOUNT_COUNT;
 }
 
 static void
@@ -124,7 +124,7 @@ lock_mutator_thread (void *arg)
 
       i1 = random_account ();
       i2 = random_account ();
-      value = ((unsigned int) rand () >> 3) % 10;
+      value = ((unsigned long) random () >> 3) % 10;
       account[i1] += value;
       account[i2] -= value;
 
diff --git a/tests/test-pthread-tss.c b/tests/test-pthread-tss.c
index 0caf475e54..e68e890e53 100644
--- a/tests/test-pthread-tss.c
+++ b/tests/test-pthread-tss.c
@@ -71,7 +71,7 @@ perhaps_yield (void)
 {
   /* Call yield () only with a certain probability, otherwise the
      sequence of thread activations may be too predictable.  */
-  if ((((unsigned int) rand () >> 3) % 4) == 0)
+  if ((((unsigned long) random () >> 3) % 4) == 0)
     yield ();
 }
 
@@ -100,7 +100,7 @@ worker_thread (void *arg)
   /* Initialize the per-thread storage.  */
   for (i = 0; i < KEYS_COUNT; i++)
     {
-      values[i] = (((unsigned int) rand () >> 3) % 1000000) * THREAD_COUNT + 
id;
+      values[i] = (((unsigned long) random () >> 3) % 1000000) * THREAD_COUNT 
+ id;
       /* Hopefully no arithmetic overflow.  */
       if ((values[i] % THREAD_COUNT) != id)
         abort ();
@@ -132,8 +132,8 @@ worker_thread (void *arg)
   for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
     {
       dbgprintf ("Worker %p doing value swapping\n", pthread_self_pointer ());
-      i = ((unsigned int) rand () >> 3) % KEYS_COUNT;
-      j = ((unsigned int) rand () >> 3) % KEYS_COUNT;
+      i = ((unsigned long) random () >> 3) % KEYS_COUNT;
+      j = ((unsigned long) random () >> 3) % KEYS_COUNT;
       if (i != j)
         {
           void *vi = pthread_getspecific (mykeys[i]);
@@ -462,7 +462,7 @@ racecheck_thread (void *arg)
 
   for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
     {
-      i = ((unsigned int) rand () >> 3) % KEYS_COUNT;
+      i = ((unsigned long) random () >> 3) % KEYS_COUNT;
       dbgprintf ("Worker %p reallocating key %d\n", pthread_self_pointer (), 
i);
       ASSERT (pthread_key_delete (keys[i]) == 0);
       ASSERT (pthread_key_create (&keys[i], destructor_table[i]) == 0);
diff --git a/tests/test-thread_local.c b/tests/test-thread_local.c
index 28536535ff..4ea788f902 100644
--- a/tests/test-thread_local.c
+++ b/tests/test-thread_local.c
@@ -76,7 +76,7 @@ perhaps_yield (void)
 {
   /* Call yield () only with a certain probability, otherwise the
      sequence of thread activations may be too predictable.  */
-  if ((((unsigned int) rand () >> 3) % 4) == 0)
+  if ((((unsigned long) random () >> 3) % 4) == 0)
     yield ();
 }
 
@@ -102,7 +102,7 @@ worker_thread (void *arg)
   dbgprintf ("Worker %p before first assignment\n", thrd_current_pointer ());
   for (i = 0; i < KEYS_COUNT; i++)
     {
-      *values[i] = (((unsigned int) rand () >> 3) % 1000000) * THREAD_COUNT + 
id;
+      *values[i] = (((unsigned long) random () >> 3) % 1000000) * THREAD_COUNT 
+ id;
       /* Hopefully no arithmetic overflow.  */
       if ((*values[i] % THREAD_COUNT) != id)
         abort ();
@@ -114,8 +114,8 @@ worker_thread (void *arg)
   for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
     {
       dbgprintf ("Worker %p doing value swapping\n", thrd_current_pointer ());
-      i = ((unsigned int) rand () >> 3) % KEYS_COUNT;
-      j = ((unsigned int) rand () >> 3) % KEYS_COUNT;
+      i = ((unsigned long) random () >> 3) % KEYS_COUNT;
+      j = ((unsigned long) random () >> 3) % KEYS_COUNT;
       if (i != j)
         {
           unsigned int vi = *values[i];
diff --git a/tests/test-tls.c b/tests/test-tls.c
index 6a59a65ab0..a29afbd90a 100644
--- a/tests/test-tls.c
+++ b/tests/test-tls.c
@@ -68,7 +68,7 @@ static void
 perhaps_yield (void)
 {
   /* This helps making the sequence of thread activations less predictable.  */
-  if ((((unsigned int) rand () >> 3) % 4) == 0)
+  if ((((unsigned long) random () >> 3) % 4) == 0)
     yield ();
 }
 
@@ -97,7 +97,7 @@ worker_thread (void *arg)
   /* Initialize the per-thread storage.  */
   for (i = 0; i < KEYS_COUNT; i++)
     {
-      values[i] = (((unsigned int) rand () >> 3) % 1000000) * THREAD_COUNT + 
id;
+      values[i] = (((unsigned long) random () >> 3) % 1000000) * THREAD_COUNT 
+ id;
       /* Hopefully no arithmetic overflow.  */
       if ((values[i] % THREAD_COUNT) != id)
         abort ();
@@ -127,8 +127,8 @@ worker_thread (void *arg)
   for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
     {
       dbgprintf ("Worker %p doing value swapping\n", gl_thread_self_pointer 
());
-      i = ((unsigned int) rand () >> 3) % KEYS_COUNT;
-      j = ((unsigned int) rand () >> 3) % KEYS_COUNT;
+      i = ((unsigned long) random () >> 3) % KEYS_COUNT;
+      j = ((unsigned long) random () >> 3) % KEYS_COUNT;
       if (i != j)
         {
           void *vi = gl_tls_get (mykeys[i]);
@@ -436,7 +436,7 @@ racecheck_thread (void *arg)
 
   for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
     {
-      i = ((unsigned int) rand () >> 3) % KEYS_COUNT;
+      i = ((unsigned long) random () >> 3) % KEYS_COUNT;
       dbgprintf ("Worker %p reallocating key %d\n", gl_thread_self_pointer (), 
i);
       gl_tls_key_destroy (keys[i]);
       gl_tls_key_init (keys[i], destructor_table[i]);
diff --git a/tests/test-tss.c b/tests/test-tss.c
index 9d1db0249a..ad9fd45b57 100644
--- a/tests/test-tss.c
+++ b/tests/test-tss.c
@@ -68,7 +68,7 @@ perhaps_yield (void)
 {
   /* Call yield () only with a certain probability, otherwise the
      sequence of thread activations may be too predictable.  */
-  if ((((unsigned int) rand () >> 3) % 4) == 0)
+  if ((((unsigned long) random () >> 3) % 4) == 0)
     yield ();
 }
 
@@ -97,7 +97,7 @@ worker_thread (void *arg)
   /* Initialize the per-thread storage.  */
   for (i = 0; i < KEYS_COUNT; i++)
     {
-      values[i] = (((unsigned int) rand () >> 3) % 1000000) * THREAD_COUNT + 
id;
+      values[i] = (((unsigned long) random () >> 3) % 1000000) * THREAD_COUNT 
+ id;
       /* Hopefully no arithmetic overflow.  */
       if ((values[i] % THREAD_COUNT) != id)
         abort ();
@@ -127,8 +127,8 @@ worker_thread (void *arg)
   for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
     {
       dbgprintf ("Worker %p doing value swapping\n", thrd_current_pointer ());
-      i = ((unsigned int) rand () >> 3) % KEYS_COUNT;
-      j = ((unsigned int) rand () >> 3) % KEYS_COUNT;
+      i = ((unsigned long) random () >> 3) % KEYS_COUNT;
+      j = ((unsigned long) random () >> 3) % KEYS_COUNT;
       if (i != j)
         {
           void *vi = tss_get (mykeys[i]);
@@ -442,7 +442,7 @@ racecheck_thread (void *arg)
 
   for (repeat = REPEAT_COUNT; repeat > 0; repeat--)
     {
-      i = ((unsigned int) rand () >> 3) % KEYS_COUNT;
+      i = ((unsigned long) random () >> 3) % KEYS_COUNT;
       dbgprintf ("Worker %p reallocating key %d\n", thrd_current_pointer (), 
i);
       tss_delete (keys[i]);
       ASSERT (tss_create (&keys[i], destructor_table[i]) == thrd_success);




Reply via email to