Bump to m4 1.4.19
[platform/upstream/m4.git] / tests / test-setlocale_null-mt-one.c
1 /* Multithread-safety test for setlocale_null_r (LC_xxx, ...).
2    Copyright (C) 2019-2021 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>.  */
16
17 /* Written by Bruno Haible <bruno@clisp.org>, 2019.  */
18
19 #include <config.h>
20
21 /* Work around GCC bug 44511.  */
22 #if 4 < __GNUC__ + (3 <= __GNUC_MINOR__)
23 # pragma GCC diagnostic ignored "-Wreturn-type"
24 #endif
25
26 #if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS
27
28 /* Specification.  */
29 #include <locale.h>
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <time.h>
35
36 #include "glthread/thread.h"
37
38 /* We want to use the system's setlocale() function here, not the gnulib
39    override.  */
40 #undef setlocale
41
42
43 /* Some common locale names.  */
44
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
62
63 static const char LOCALE1[] = ENGLISH ENCODING;
64 static const char LOCALE2[] = GERMAN ENCODING;
65 static const char LOCALE3[] = FRENCH ENCODING;
66
67 static char *expected;
68
69 static void *
70 thread1_func (void *arg)
71 {
72   for (;;)
73     {
74       char buf[SETLOCALE_NULL_MAX];
75
76       if (setlocale_null_r (LC_NUMERIC, buf, sizeof (buf)))
77         abort ();
78       if (strcmp (expected, buf) != 0)
79         {
80           fprintf (stderr, "thread1 disturbed by thread2!\n"); fflush (stderr);
81           abort ();
82         }
83     }
84
85   /*NOTREACHED*/
86 }
87
88 static void *
89 thread2_func (void *arg)
90 {
91   for (;;)
92     {
93       char buf[SETLOCALE_NULL_MAX];
94
95       setlocale_null_r (LC_NUMERIC, buf, sizeof (buf));
96       setlocale_null_r (LC_TIME, buf, sizeof (buf));
97     }
98
99   /*NOTREACHED*/
100 }
101
102 int
103 main (int argc, char *argv[])
104 {
105   if (setlocale (LC_ALL, LOCALE1) == NULL)
106     {
107       fprintf (stderr, "Skipping test: LOCALE1 not recognized\n");
108       return 77;
109     }
110   if (setlocale (LC_NUMERIC, LOCALE2) == NULL)
111     {
112       fprintf (stderr, "Skipping test: LOCALE2 not recognized\n");
113       return 77;
114     }
115   if (setlocale (LC_TIME, LOCALE3) == NULL)
116     {
117       fprintf (stderr, "Skipping test: LOCALE3 not recognized\n");
118       return 77;
119     }
120
121   expected = strdup (setlocale (LC_NUMERIC, NULL));
122
123   /* Create the two threads.  */
124   gl_thread_create (thread1_func, NULL);
125   gl_thread_create (thread2_func, NULL);
126
127   /* Let them run for 2 seconds.  */
128   {
129     struct timespec duration;
130     duration.tv_sec = 2;
131     duration.tv_nsec = 0;
132
133     nanosleep (&duration, NULL);
134   }
135
136   return 0;
137 }
138
139 #else
140
141 /* No multithreading available.  */
142
143 #include <stdio.h>
144
145 int
146 main ()
147 {
148   fputs ("Skipping test: multithreading not enabled\n", stderr);
149   return 77;
150 }
151
152 #endif
153
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 !)
172 */