1/* Test floating-point environment is thread-local.
2 Copyright (C) 2013-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <fenv.h>
20#include <pthread.h>
21#include <stdio.h>
22#include <stdint.h>
23
24#define TEST_ONE_RM(RM) \
25 do \
26 { \
27 if (fesetround (RM) == 0) \
28 { \
29 rm = fegetround (); \
30 if (rm != RM) \
31 { \
32 printf ("expected " #RM ", got %d\n", rm); \
33 ret = 1; \
34 } \
35 } \
36 } \
37 while (0)
38
39static void *
40test_round (void *arg)
41{
42 intptr_t ret = 0;
43 for (int i = 0; i < 10000; i++)
44 {
45 int rm;
46#ifdef FE_DOWNWARD
47 TEST_ONE_RM (FE_DOWNWARD);
48#endif
49#ifdef FE_TONEAREST
50 TEST_ONE_RM (FE_TONEAREST);
51#endif
52#ifdef FE_TOWARDZERO
53 TEST_ONE_RM (FE_TOWARDZERO);
54#endif
55#ifdef FE_UPWARD
56 TEST_ONE_RM (FE_UPWARD);
57#endif
58 }
59 return (void *) ret;
60}
61
62#define TEST_ONE_RAISE(EX) \
63 do \
64 { \
65 if (feraiseexcept (EX) == 0) \
66 if (fetestexcept (EX) != EX) \
67 { \
68 printf (#EX " not raised\n"); \
69 ret = 1; \
70 } \
71 if (feclearexcept (FE_ALL_EXCEPT) == 0) \
72 if (fetestexcept (FE_ALL_EXCEPT) != 0) \
73 { \
74 printf ("exceptions not all cleared\n"); \
75 ret = 1; \
76 } \
77 } \
78 while (0)
79
80static void *
81test_raise (void *arg)
82{
83 intptr_t ret = 0;
84 for (int i = 0; i < 10000; i++)
85 {
86#ifdef FE_DIVBYZERO
87 TEST_ONE_RAISE (FE_DIVBYZERO);
88#endif
89#ifdef FE_INEXACT
90 TEST_ONE_RAISE (FE_INEXACT);
91#endif
92#ifdef FE_INVALID
93 TEST_ONE_RAISE (FE_INVALID);
94#endif
95#ifdef FE_OVERFLOW
96 TEST_ONE_RAISE (FE_OVERFLOW);
97#endif
98#ifdef UNDERFLOW
99 TEST_ONE_RAISE (FE_UNDERFLOW);
100#endif
101 }
102 return (void *) ret;
103}
104
105#define TEST_ONE_ENABLE(EX) \
106 do \
107 { \
108 if (feenableexcept (EX) != -1) \
109 if (fegetexcept () != EX) \
110 { \
111 printf (#EX " not enabled\n"); \
112 ret = 1; \
113 } \
114 if (fedisableexcept (EX) != -1) \
115 if (fegetexcept () != 0) \
116 { \
117 printf ("exceptions not all disabled\n"); \
118 ret = 1; \
119 } \
120 } \
121 while (0)
122
123static void *
124test_enable (void *arg)
125{
126 intptr_t ret = 0;
127 for (int i = 0; i < 10000; i++)
128 {
129#ifdef FE_DIVBYZERO
130 TEST_ONE_ENABLE (FE_DIVBYZERO);
131#endif
132#ifdef FE_INEXACT
133 TEST_ONE_ENABLE (FE_INEXACT);
134#endif
135#ifdef FE_INVALID
136 TEST_ONE_ENABLE (FE_INVALID);
137#endif
138#ifdef FE_OVERFLOW
139 TEST_ONE_ENABLE (FE_OVERFLOW);
140#endif
141#ifdef UNDERFLOW
142 TEST_ONE_ENABLE (FE_UNDERFLOW);
143#endif
144 }
145 return (void *) ret;
146}
147
148static int
149do_test (void)
150{
151 int ret = 0;
152 void *vret;
153 pthread_t thread_id;
154 int pret;
155
156 pret = pthread_create (newthread: &thread_id, NULL, start_routine: test_round, NULL);
157 if (pret != 0)
158 {
159 printf (format: "pthread_create failed: %d\n", pret);
160 return 1;
161 }
162 vret = test_round (NULL);
163 ret |= (intptr_t) vret;
164 pret = pthread_join (th: thread_id, thread_return: &vret);
165 if (pret != 0)
166 {
167 printf (format: "pthread_join failed: %d\n", pret);
168 return 1;
169 }
170 ret |= (intptr_t) vret;
171
172 pret = pthread_create (newthread: &thread_id, NULL, start_routine: test_raise, NULL);
173 if (pret != 0)
174 {
175 printf (format: "pthread_create failed: %d\n", pret);
176 return 1;
177 }
178 vret = test_raise (NULL);
179 ret |= (intptr_t) vret;
180 pret = pthread_join (th: thread_id, thread_return: &vret);
181 if (pret != 0)
182 {
183 printf (format: "pthread_join failed: %d\n", pret);
184 return 1;
185 }
186 ret |= (intptr_t) vret;
187
188 pret = pthread_create (newthread: &thread_id, NULL, start_routine: test_enable, NULL);
189 if (pret != 0)
190 {
191 printf (format: "pthread_create failed: %d\n", pret);
192 return 1;
193 }
194 vret = test_enable (NULL);
195 ret |= (intptr_t) vret;
196 pret = pthread_join (th: thread_id, thread_return: &vret);
197 if (pret != 0)
198 {
199 printf (format: "pthread_join failed: %d\n", pret);
200 return 1;
201 }
202 ret |= (intptr_t) vret;
203
204 return ret;
205}
206
207#define TEST_FUNCTION do_test ()
208#include "../test-skeleton.c"
209

source code of glibc/math/test-fenv-tls.c