maint.mk: Update system header list for #include syntax checks.
[gnulib.git] / tests / test-setlocale_null-mt-one.c
blobcbd057f94f6d080e8334713b3ec4106155b4b179
1 /* Multithread-safety test for setlocale_null_r (LC_xxx, ...).
2 Copyright (C) 2019-2024 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>, 2019. */
19 #include <config.h>
21 /* Work around GCC bug 44511. */
22 #if 4 < __GNUC__ + (3 <= __GNUC_MINOR__)
23 # pragma GCC diagnostic ignored "-Wreturn-type"
24 #endif
26 #if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS
28 /* Specification. */
29 #include <locale.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <time.h>
36 #include "glthread/thread.h"
38 /* We want to use the system's setlocale() function here, not the gnulib
39 override. */
40 #undef setlocale
43 /* Some common locale names. */
45 #if defined _WIN32 && !defined __CYGWIN__
46 # define ENGLISH "English_United States"
47 # define GERMAN "German_Germany"
48 # define FRENCH "French_France"
49 # define ENCODING ".1252"
50 #else
51 # define ENGLISH "en_US"
52 # define GERMAN "de_DE"
53 # define FRENCH "fr_FR"
54 # if defined __sgi
55 # define ENCODING ".ISO8859-15"
56 # elif defined __hpux
57 # define ENCODING ".utf8"
58 # else
59 # define ENCODING ".UTF-8"
60 # endif
61 #endif
63 static const char LOCALE1[] = ENGLISH ENCODING;
64 static const char LOCALE2[] = GERMAN ENCODING;
65 static const char LOCALE3[] = FRENCH ENCODING;
67 static char *expected;
69 static void *
70 thread1_func (void *arg)
72 for (;;)
74 char buf[SETLOCALE_NULL_MAX];
76 if (setlocale_null_r (LC_NUMERIC, buf, sizeof (buf)))
77 abort ();
78 if (strcmp (expected, buf) != 0)
80 fprintf (stderr, "thread1 disturbed by thread2!\n"); fflush (stderr);
81 abort ();
85 /*NOTREACHED*/
88 static void *
89 thread2_func (void *arg)
91 for (;;)
93 char buf[SETLOCALE_NULL_MAX];
95 setlocale_null_r (LC_NUMERIC, buf, sizeof (buf));
96 setlocale_null_r (LC_TIME, buf, sizeof (buf));
99 /*NOTREACHED*/
103 main (int argc, char *argv[])
105 if (setlocale (LC_ALL, LOCALE1) == NULL)
107 fprintf (stderr, "Skipping test: LOCALE1 not recognized\n");
108 return 77;
110 if (setlocale (LC_NUMERIC, LOCALE2) == NULL)
112 fprintf (stderr, "Skipping test: LOCALE2 not recognized\n");
113 return 77;
115 if (setlocale (LC_TIME, LOCALE3) == NULL)
117 fprintf (stderr, "Skipping test: LOCALE3 not recognized\n");
118 return 77;
121 expected = strdup (setlocale (LC_NUMERIC, NULL));
123 /* Create the two threads. */
124 gl_thread_create (thread1_func, NULL);
125 gl_thread_create (thread2_func, NULL);
127 /* Let them run for 2 seconds. */
129 struct timespec duration;
130 duration.tv_sec = 2;
131 duration.tv_nsec = 0;
133 nanosleep (&duration, NULL);
136 return 0;
139 #else
141 /* No multithreading available. */
143 #include <stdio.h>
146 main ()
148 fputs ("Skipping test: multithreading not enabled\n", stderr);
149 return 77;
152 #endif
154 /* Without locking, the results of this test would be:
155 glibc OK
156 musl libc OK
157 macOS OK
158 FreeBSD OK
159 NetBSD OK
160 OpenBSD crash < 1 sec
161 AIX crash < 2 sec
162 HP-UX OK
163 IRIX OK
164 Solaris 10 OK
165 Solaris 11.0 OK
166 Solaris 11.4 OK
167 Solaris OpenIndiana OK
168 Haiku OK
169 Cygwin OK
170 mingw OK
171 MSVC OK (assuming compiler option /MD !)