Re: rand is not ISO C compliant in Cygwin

Bruno Haible <[email protected]>
Newsgroups gmane.comp.lib.newlib,gmane.os.cygwin
Message-ID <4205183.RD5H4TdPZm@nimes>
Corinna Vinschen wrote:
> I took a look into POSIX and I'm a bit puzzled now.  From
> https://pubs.opengroup.org/onlinepubs/9699919799/functions/rand.html

Part of the confusion is that POSIX and ISO C have slightly different
wording. This POSIX page says:
   "The functionality described on this reference page is aligned
    with the ISO C standard. Any conflict between the requirements
    described here and the ISO C standard is unintentional. This
    volume of POSIX.1-2017 defers to the ISO C standard."

In ISO C 99 § 7.20.2, the only relevant sentence is:

  "The srand function uses the argument as a seed for a new sequence
   of pseudo-random numbers to be returned by subsequent calls to rand.
   If srand is then called with the same seed value, the sequence of
   pseudo-random numbers shall be repeated."

In ISO C 11 § 7.22.2 and ISO C 17 § 7.22.2, additionally two sentences
were inserted:

  "The rand function is not required to avoid data races with other
   calls to pseudo-random sequence generation functions."

  "The srand function is not required to avoid data races with other
   calls to pseudo-random sequence generation functions."

ISO C 23 (which is still is draft state, but compared to the draft
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3054.pdf I cannot
see any change regarding rand() in the changes summary
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3148.doc) has the
same wording.

POSIX does not have these two sentences, but instead has:

  "The rand() function need not be thread-safe."

> RATIONAL
> 
>   The ISO C standard rand() and srand() functions allow per-process
>                                                   ^^^^^ (not requires)
> 
>   pseudo-random streams shared by all threads.

Indeed, "requires" would fit better here, IMO, because the texts of
both ISO C and POSIX have multithreading in mind and still talk about
"subsequent calls to rand" — which makes a reference to time, but not
to threads.

> Ok, so, *iff* rand/srand share per-process state, then they have to
> use locking to prevent MT interference.

... if the implementor wants to prevent MT interference (which both
ISO C and POSIX allows).

> POSIX continues:
> 
>   With regard to rand(), there are two different behaviors that may be
>   wanted in a multi-threaded program:
> 
>   1. A single per-process sequence of pseudo-random numbers that is
>      shared by all threads that call rand()
> 
>   2. A different sequence of pseudo-random numbers for each thread that
>      calls rand()
>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This paragraph continues after the two items:
   "This is provided by the modified thread-safe function based on whether
    the seed value is global to the entire process or local to each thread."

My understanding of this paragraph is:
  - If an application wants 1., they can use rand_r with SEED pointing
    to a global variable.
  - If an application wants 2., they can use rand_r with SEED pointing
    to a per-thread variable.

> I read this as the newlib technique being one way of correctly
> implementing rand/srand, no?

I don't think so. The critical sentence is the one with
"subsequent calls to rand".

Bruno
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.