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