On 2023-11-13 09:12, Corinna Vinschen via Cygwin wrote:
On Nov 10 17:19, Bruno Haible via Cygwin wrote:
The function 'random' is, unlike 'rand', not marked as not MT-safe in POSIX
[1][2]. Thus it must be multithread-safe [3]:
   "Each function defined in the System Interfaces volume of POSIX.1-2017
    is thread-safe unless explicitly stated otherwise."
And indeed glibc, musl libc, AIX, Android, and even NetBSD implement it in a
multithread-safe way.

Our code is from FreeBSD, originally. I checked the latest code from
FreeBSD. It doesn't lock anything in random() and generates the same
error when running the same test app.
Why is that ok for FreeBSD?

It appears that random(3) is intended to provide a single random series during execution of a program with simple needs; behaviour is not reproducible when threaded, says POSIX, newlib, and Linux (below).

From POSIX The Open Group Base Specifications Issue 7, 2018 edition IEEE Std 1003.1-2017 Volume 2: System Interfaces and initstate(3p) to which random(3p) refers and defers but does not link or .so:

"NAME
       random — generate pseudo‐random number

SYNOPSIS
       #include <stdlib.h>

       long random(void);

DESCRIPTION
       Refer to initstate()."

* That's all folks!

"NAME
        initstate, random, setstate, srandom - pseudo-random number functions
...
APPLICATION USAGE
...
Threaded applications should use erand48(), nrand48(), or jrand48() instead of random() when an independent random number sequence in multiple threads is required."

From newlib:

"NAME
       random, srandom - pseudo-random numbers
...
NOTES
       random and srandom are unsafe for multi-threaded applications.

       _XOPEN_SOURCE may be any value >= 500.

PORTABILITY
random is required by XSI. This implementation uses the same algorithm as rand."

* Newlib, and presumably FreeBSD, do not support initstate, setstate, or > 8 (for amd64/x86_64) bytes state.

From man-pages-linux random(3):

"CAVEATS
...
The random() function should not be used in multithreaded programs where reproducible behavior is required.
       Use random_r(3) for that purpose."

* As usual, random_r(3) requires the caller to provide an initialized state vector buffer (of 8-256 bytes), allowing the caller to decide the amount of randomness and scope of the random series, and possibly call initstate_r(3), to control the seed.

--
Take care. Thanks, Brian Inglis              Calgary, Alberta, Canada

La perfection est atteinte                   Perfection is achieved
non pas lorsqu'il n'y a plus rien à ajouter  not when there is no more to add
mais lorsqu'il n'y a plus rien à retirer     but when there is no more to cut
                                -- Antoine de Saint-Exupéry

--
Problem reports:      https://cygwin.com/problems.html
FAQ:                  https://cygwin.com/faq/
Documentation:        https://cygwin.com/docs.html
Unsubscribe info:     https://cygwin.com/ml/#unsubscribe-simple

Reply via email to