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 Content-Type: multipart/mixed; boundary="nextPart8606667.zIJbB62Pao" Content-Transfer-Encoding: 7Bit 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 List-Archive: List-Post: List-Help: List-Subscribe: , From: Bruno Haible via Cygwin Reply-To: Bruno Haible Sender: "Cygwin" 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 . */ /* Written by Bruno Haible , 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 #include #include #include #if EXPLICIT_YIELD # include # 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--