delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2023/11/10/11:20:08

X-Recipient: archive-cygwin AT delorie DOT com
DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 646AD3858436
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cygwin.com;
s=default; t=1699633207;
bh=Qh/4E+qTGRVgAc/j7IBvT084D6iNvuCp7dkJc98AqbI=;
h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post:
List-Help:List-Subscribe:From:Reply-To:From;
b=PoY5wSrhG0B19XTgoaR2VzU0N6CQ4FJGclgqwCQA0HKrcPC21duW0L0ZWE48qFmad
IOsNDXmZnZg20swKjZiESH4ct8YVnMTH4/hYTjIcvC0DJ2sL71LouaaMWJLJ9mvR9F
8yR9K2kclKTeWl6FXn0/1GwUAtZFIhPFMHcJLPk8=
X-Original-To: cygwin AT cygwin DOT com
Delivered-To: cygwin AT cygwin DOT com
DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B86F33858D32
ARC-Filter: OpenARC Filter v1.0.0 sourceware.org B86F33858D32
ARC-Seal: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1699633193; cv=pass;
b=BPD83Ojin6IgIoWgPYr5TNnnAsfJZPBpIzbP4bogjSzcF41cnAo/HsNTJYZ8/zDJ6sx+i3nZD7V6nSJjlWGQh78CrWCXTKINAT17CicIBy8eYdAGaBrthUhAuM9r0o48GaNUZDtoR4Q1BkvRqtzEY52ivqKb301+Ukzr0t/BwuQ=
ARC-Message-Signature: i=2; a=rsa-sha256; d=sourceware.org; s=key;
t=1699633193; c=relaxed/simple;
bh=E0C9GKKKlYCGpv2EYI1t8fXZqdorjg12Ra3fOlBJTyg=;
h=DKIM-Signature:DKIM-Signature:From:To:Subject:Date:Message-ID:
MIME-Version;
b=Ba5hXz8bAqJ2MXkYx3GUx9V+QTNK2hX4+djemNKF/jKdk7Ccxc5H8dIXu7/Y7K0l4AgZbFQiAaCG+MwdedA14Q/yl0DVwfYVcD3Ih261Xbob2YFFXE9Q9gs66VmuP1/dXmR+QcRkNfhK4XdJ4uEV+uxSoVsEm5N3PcNfK15VbjE=
ARC-Authentication-Results: i=2; server2.sourceware.org
ARC-Seal: i=1; a=rsa-sha256; t=1699633188; cv=none;
d=strato.com; s=strato-dkim-0002;
b=LBEPcXXKVPK0dEllCHwEfKEabkc/NY+vn9E7++csETGGmM6hFi2THqx+cW5h97YS5Z
KF8yEsO2wdNVN8GTZqaGR6m+fsm7fsP9+gk3f9e7bHc3rbRuOEKJ+V7XLDdvGf+93D9r
pPqKzw4k8zHWhQDK+vFkeSesVYdFQ+K66zs0oJKnhLpAI8+GXtzgXJCkqN+Z2bT8zHxF
26GWNhyGl06IUeiQtt8XPa1ejJ85KhE0xx1zVt3xTMqqcNs4DggOq/XP29eLFn61bErY
TK8R+FlpM/pZPKSdQ8qvy2Ih9Q8OZPaSuAq5e2dnjHbAaTy5w7R1pIiuCKYWOYwGZek0
JDTQ==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; t=1699633188;
s=strato-dkim-0002; d=strato.com;
h=Message-ID:Date:Subject:To:From:Cc:Date:From:Subject:Sender;
bh=Ush54FjcxPBMlc9Rz3FPTk3jVacKOe+nx5arf+ChFvw=;
b=jnILRDw/k7MIuQgiooSV5/OXQ/15+TjhH0YYuT78BNXDSgG4eV7gyCLju4zHRuIoFl
LOdijLnzqpbWIgUS71uDLMaXJUVLXyWI2Js2OqaCJUdl8nE7ZQi690KpSk3sV4+Oyj6H
Q8nPQOqpklxVRswwilcUhbYC9laN9wUFOkhd5YinE1FdeCIsWKN6Pko8x+rjLcMOgve7
wa7TqILz7LO2JZqgBxnE+gN0k8/txBPtDv+pvQiU8Oc82rEn++5cwAAvsXPLPxqz6VQy
8xqvzFLAad5XbcP40dzgQPNksMoriweWmQCn2IixQfy9k7xlSA4zLOqC6O3ZwCZWxv5b
IkRg==
ARC-Authentication-Results: i=1; strato.com;
arc=none;
dkim=none
X-RZG-CLASS-ID: mo00
X-RZG-AUTH: ":Ln4Re0+Ic/6oZXR1YgKryK8brlshOcZlIWs+iCP5vnk6shH0WWb0LN8XZoH94zq68+3cfpOVivRrqAkwB7g/1OdqjfT+fMz02A=="
To: cygwin AT cygwin DOT com
Subject: random is not multithread-safe in Cygwin
Date: Fri, 10 Nov 2023 17:19:47 +0100
Message-ID: <3811044.57xzQst1vy@nimes>
MIME-Version: 1.0
X-Spam-Status: No, score=-3.7 required=5.0 tests=BAYES_00, DKIM_SIGNED,
DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, KAM_SHORT, RCVD_IN_DNSWL_LOW,
RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS, SPF_NONE, TXREP,
T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6
X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on
server2.sourceware.org
X-BeenThere: cygwin AT cygwin DOT com
X-Mailman-Version: 2.1.30
List-Id: General Cygwin discussions and problem reports <cygwin.cygwin.com>
List-Archive: <https://cygwin.com/pipermail/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-request AT cygwin DOT com?subject=help>
List-Subscribe: <https://cygwin.com/mailman/listinfo/cygwin>,
<mailto:cygwin-request AT cygwin DOT com?subject=subscribe>
From: Bruno Haible via Cygwin <cygwin AT cygwin DOT com>
Reply-To: Bruno Haible <bruno AT clisp DOT org>
Sender: "Cygwin" <cygwin-bounces+archive-cygwin=delorie DOT com AT cygwin DOT com>

This is a multi-part message in MIME format.

--nextPart8606667.zIJbB62Pao
Content-Transfer-Encoding: 7Bit
Content-Type: text/plain; charset="us-ascii"

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.

On Cygwin 2.9.0 and 3.4.6, it is not multithread-safe.

How to reproduce:
1. Compile the attached program.
   $ x86_64-pc-cygwin-gcc foo.c
2. Run it.
   $ ./a.exe
Expected: No output.
Actual: Output such as
  Expected value #367 not found in multithreaded results.

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

--nextPart8606667.zIJbB62Pao
Content-Disposition: attachment; filename="foo.c"
Content-Transfer-Encoding: 7Bit
Content-Type: text/x-csrc; charset="UTF-8"; name="foo.c"

/* Multithread-safety test for random().
   Copyright (C) 2023 Free Software Foundation, Inc.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */

/* Written by Bruno Haible <bruno AT clisp DOT org>, 2023.  */

/* Whether to help the scheduler through explicit yield().
   Uncomment this to see if the operating system has a fair scheduler.  */
#define EXPLICIT_YIELD 1

/* Number of simultaneous threads.  */
#define THREAD_COUNT 4

/* Number of random() invocations operations performed in each thread.
   This value is chosen so that the unit test terminates quickly.
   To reliably determine whether a random() implementation is multithread-safe,
   set REPEAT_COUNT to 1000000 and run the test 100 times:
     $ for i in `seq 100`; do ./test-random-mt; done
 */
#define REPEAT_COUNT 1000000

/* Specification.  */
#include <stdlib.h>

#include <assert.h>
#include <pthread.h>
#include <stdio.h>

#if EXPLICIT_YIELD
# include <sched.h>
# define yield() sched_yield ()
#else
# define yield()
#endif

/* This test runs REPEAT_COUNT invocations of random() in each thread and stores
   the result, then compares the first REPEAT_COUNT among these
     THREAD_COUNT * REPEAT_COUNT
   random numbers against a precomputed sequence with the same seed.  */

static void *
random_invocator_thread (void *arg)
{
  long *storage = (long *) arg;
  int repeat;

  for (repeat = 0; repeat < REPEAT_COUNT; repeat++)
    {
      storage[repeat] = random ();
      yield ();
    }

  return NULL;
}

int
main ()
{
  unsigned int seed = 19891109;

  /* First, get the expected sequence of random() results.  */
  srandom (seed);
  long *expected = (long *) malloc (REPEAT_COUNT * sizeof (long));
  assert (expected != NULL);
  {
    int repeat;
    for (repeat = 0; repeat < REPEAT_COUNT; repeat++)
      expected[repeat] = random ();
  }

  /* Then, run REPEAT_COUNT invocations of random() each, in THREAD_COUNT
     separate threads.  */
  pthread_t threads[THREAD_COUNT];
  long *thread_results[THREAD_COUNT];
  srandom (seed);
  {
    int i;
    for (i = 0; i < THREAD_COUNT; i++)
      {
        thread_results[i] = (long *) malloc (REPEAT_COUNT * sizeof (long));
        assert (thread_results[i] != NULL);
      }
    for (i = 0; i < THREAD_COUNT; i++)
      assert (pthread_create (&threads[i], NULL, random_invocator_thread, thread_results[i]) == 0);
  }

  /* Wait for the threads to terminate.  */
  {
    int i;
    for (i = 0; i < THREAD_COUNT; i++)
      assert (pthread_join (threads[i], NULL) == 0);
  }

  /* Finally, determine whether the threads produced the same sequence of
     random() results.  */
  {
    int expected_index;
    int result_index[THREAD_COUNT];
    int i;

    for (i = 0; i < THREAD_COUNT; i++)
      result_index[i] = 0;

    for (expected_index = 0; expected_index < REPEAT_COUNT; expected_index++)
      {
        long expected_value = expected[expected_index];

        for (i = 0; i < THREAD_COUNT; i++)
          {
            if (thread_results[i][result_index[i]] == expected_value)
              {
                result_index[i]++;
                break;
              }
          }
        if (i == THREAD_COUNT)
          {
            if (expected_index == 0)
              {
                /* This occurs on platforms like OpenBSD, where srandom() has no
                   effect and random() always return non-deterministic values.
                   Mark the test as SKIP.  */
                fprintf (stderr, "Skipping test: random() is non-deterministic.\n");
                return 77;
              }
            else
              {
                fprintf (stderr, "Expected value #%d not found in multithreaded results.\n",
                         expected_index);
                return 1;
              }
          }
      }
  }

  return 0;
}

--nextPart8606667.zIJbB62Pao
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline


-- 
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

--nextPart8606667.zIJbB62Pao--



- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019