xref: /openbsd-src/regress/lib/libpthread/preemption_float/preemption_float.c (revision f624289e6d27f6b2c3637045d15e255875b0fecc)
1*f624289eSmiod /*	$OpenBSD: preemption_float.c,v 1.5 2010/12/26 13:50:20 miod Exp $	*/
2b2ea75c1Sfgsch /*
3b2ea75c1Sfgsch  * Copyright (c) 1993, 1994, 1995, 1996 by Chris Provenzano and contributors,
4b2ea75c1Sfgsch  * proven@mit.edu All rights reserved.
5b2ea75c1Sfgsch  *
6b2ea75c1Sfgsch  * Redistribution and use in source and binary forms, with or without
7b2ea75c1Sfgsch  * modification, are permitted provided that the following conditions
8b2ea75c1Sfgsch  * are met:
9b2ea75c1Sfgsch  * 1. Redistributions of source code must retain the above copyright
10b2ea75c1Sfgsch  *    notice, this list of conditions and the following disclaimer.
11b2ea75c1Sfgsch  * 2. Redistributions in binary form must reproduce the above copyright
12b2ea75c1Sfgsch  *    notice, this list of conditions and the following disclaimer in the
13b2ea75c1Sfgsch  *    documentation and/or other materials provided with the distribution.
14b2ea75c1Sfgsch  * 3. All advertising materials mentioning features or use of this software
15b2ea75c1Sfgsch  *    must display the following acknowledgement:
16b2ea75c1Sfgsch  *	This product includes software developed by Chris Provenzano,
17b2ea75c1Sfgsch  *	the University of California, Berkeley, and contributors.
18b2ea75c1Sfgsch  * 4. Neither the name of Chris Provenzano, the University, nor the names of
19b2ea75c1Sfgsch  *   contributors may be used to endorse or promote products derived
20b2ea75c1Sfgsch  *   from this software without specific prior written permission.
21b2ea75c1Sfgsch  *
22b2ea75c1Sfgsch  * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO AND CONTRIBUTORS ``AS IS'' AND
23b2ea75c1Sfgsch  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24b2ea75c1Sfgsch  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25b2ea75c1Sfgsch  * ARE DISCLAIMED.  IN NO EVENT SHALL CHRIS PROVENZANO, THE REGENTS OR
26b2ea75c1Sfgsch  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27b2ea75c1Sfgsch  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28b2ea75c1Sfgsch  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29b2ea75c1Sfgsch  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30b2ea75c1Sfgsch  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31b2ea75c1Sfgsch  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32b2ea75c1Sfgsch  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33b2ea75c1Sfgsch  */
34b2ea75c1Sfgsch 
35b2ea75c1Sfgsch /* Test to see if floating point state is being properly maintained
36b2ea75c1Sfgsch    for each thread.  Different threads doing floating point operations
37b2ea75c1Sfgsch    simultaneously should not interfere with one another.  This
38b2ea75c1Sfgsch    includes operations that might change some FPU flags, such as
39b2ea75c1Sfgsch    rounding modes, at least implicitly.  */
40b2ea75c1Sfgsch 
41b2ea75c1Sfgsch #include <pthread.h>
42b2ea75c1Sfgsch #include <math.h>
43b2ea75c1Sfgsch #include <stdio.h>
44b2ea75c1Sfgsch #include "test.h"
45b2ea75c1Sfgsch 
46b2ea75c1Sfgsch int limit = 2;
47b2ea75c1Sfgsch int float_passed = 0;
48b2ea75c1Sfgsch int float_failed = 1;
49b2ea75c1Sfgsch 
50db3296cfSderaadt static void *
log_loop(void * x)51db3296cfSderaadt log_loop (void *x) {
52b2ea75c1Sfgsch   int i;
53b2ea75c1Sfgsch   double d, d1, d2;
54b2ea75c1Sfgsch   /* sleep (1); */
55b2ea75c1Sfgsch   for (i = 0; i < limit; i++) {
56b2ea75c1Sfgsch     d = 42.0;
57b2ea75c1Sfgsch     d = log (exp (d));
58b2ea75c1Sfgsch     d = (d + 39.0) / d;
59b2ea75c1Sfgsch     if (i == 0)
60b2ea75c1Sfgsch       d1 = d;
61b2ea75c1Sfgsch     else {
62b2ea75c1Sfgsch 		d2 = d;
63b2ea75c1Sfgsch 		d = sin(d);
64b2ea75c1Sfgsch 		/* if (d2 != d1) { */
65*f624289eSmiod 		if (memcmp (&d2, &d1, sizeof(double))) {
6674899bb9Smarc 			printf("log loop: %f != %f\n", d1, d2);
67b2ea75c1Sfgsch 			pthread_exit(&float_failed);
68b2ea75c1Sfgsch 		}
69b2ea75c1Sfgsch 	}
70b2ea75c1Sfgsch   }
71b2ea75c1Sfgsch   pthread_exit(&float_passed);
72b2ea75c1Sfgsch }
73b2ea75c1Sfgsch 
74db3296cfSderaadt static void *
trig_loop(void * x)75db3296cfSderaadt trig_loop (void *x) {
76b2ea75c1Sfgsch   int i;
77b2ea75c1Sfgsch   double d, d1, d2;
78b2ea75c1Sfgsch   /* sleep (1);  */
79b2ea75c1Sfgsch   for (i = 0; i < limit; i++) {
80b2ea75c1Sfgsch     d = 35.0;
81b2ea75c1Sfgsch     d *= M_PI;
82b2ea75c1Sfgsch     d /= M_LN2;
83b2ea75c1Sfgsch     d = sin (d);
84b2ea75c1Sfgsch     d = cos (1 / d);
85b2ea75c1Sfgsch     if (i == 0)
86b2ea75c1Sfgsch       d1 = d;
87b2ea75c1Sfgsch     else {
88b2ea75c1Sfgsch 		d2 = d;
89b2ea75c1Sfgsch 		d = sin(d);
90b2ea75c1Sfgsch 		/* if (d2 != d1) { */
91*f624289eSmiod 		if (memcmp (&d2, &d1, sizeof(double))) {
9274899bb9Smarc 			printf("trig loop: %f != %f\n", d1, d2);
93b2ea75c1Sfgsch   			pthread_exit(&float_failed);
94b2ea75c1Sfgsch 		}
95b2ea75c1Sfgsch 	}
96b2ea75c1Sfgsch   }
97b2ea75c1Sfgsch   pthread_exit(&float_passed);
98b2ea75c1Sfgsch }
99b2ea75c1Sfgsch 
100db3296cfSderaadt static int
floatloop(void)101235b9332Smarc floatloop(void)
102b2ea75c1Sfgsch {
103b2ea75c1Sfgsch 	pthread_t thread[2];
104b2ea75c1Sfgsch 	int *x, *y;
105b2ea75c1Sfgsch 
106235b9332Smarc 	CHECKr(pthread_create (&thread[0], NULL, trig_loop, NULL));
107235b9332Smarc 	CHECKr(pthread_create (&thread[1], NULL, log_loop, NULL));
108b2ea75c1Sfgsch 	CHECKr(pthread_join(thread[0], (void **) &x));
109b2ea75c1Sfgsch 	CHECKr(pthread_join(thread[1], (void **) &y));
110b2ea75c1Sfgsch 
111b2ea75c1Sfgsch 	/* Return 0 for success */
112b2ea75c1Sfgsch 	return ((*y == float_failed)?2:0) |
113b2ea75c1Sfgsch 	       ((*x == float_failed)?1:0);
114b2ea75c1Sfgsch }
115b2ea75c1Sfgsch 
116b2ea75c1Sfgsch int
main(int argc,char * argv[])117db3296cfSderaadt main(int argc, char *argv[])
118b2ea75c1Sfgsch {
119235b9332Smarc 	pthread_t thread;
120235b9332Smarc 	int *result;
121b2ea75c1Sfgsch 
122235b9332Smarc 	/* single active thread, trig test */
123235b9332Smarc 	for(limit = 2; limit < 100000; limit *=4) {
124235b9332Smarc 		CHECKr(pthread_create (&thread, NULL, trig_loop, NULL));
125235b9332Smarc 		CHECKr(pthread_join(thread, (void **) &result));
126235b9332Smarc 		ASSERT(*result == 0);
127b2ea75c1Sfgsch 	}
128b2ea75c1Sfgsch 
129235b9332Smarc 	/* single active thread, log test */
130235b9332Smarc 	for(limit = 2; limit < 100000; limit *=4) {
131235b9332Smarc 		CHECKr(pthread_create (&thread, NULL, log_loop, NULL));
132235b9332Smarc 		CHECKr(pthread_join(thread, (void **) &result));
133235b9332Smarc 		ASSERT(*result == 0);
134b2ea75c1Sfgsch 	}
135b2ea75c1Sfgsch 
136235b9332Smarc 	/* run both threads concurrently using a higher limit */
137235b9332Smarc 	limit *= 4;
138235b9332Smarc 	ASSERT(floatloop() == 0);
139b2ea75c1Sfgsch 	SUCCEED;
140b2ea75c1Sfgsch }
141