10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24 */
25 /*
26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
28 */
29
30 #include "fenv_synonyms.h"
31 #undef lint
32 #include <signal.h>
33 #include <siginfo.h>
34 #include <ucontext.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <thread.h>
39 #include <math.h>
40 #if defined(__SUNPRO_C)
41 #include <sunmath.h>
42 #endif
43 #include <fenv.h>
44 #include "fex_handler.h"
45 #include "fenv_inlines.h"
46
47 #if defined(__sparc) && !defined(__sparcv9)
48 #include <sys/procfs.h>
49 #endif
50
51 /* 2.x signal.h doesn't declare sigemptyset or sigismember
52 if they're #defined (see sys/signal.h) */
53 extern int sigemptyset(sigset_t *);
54 extern int sigismember(const sigset_t *, int);
55
56 /* external globals */
57 void (*__mt_fex_sync)() = NULL; /* for synchronization with libmtsk */
58 #pragma weak __mt_fex_sync
59
60 #ifdef LIBM_MT_FEX_SYNC
61 void (*__libm_mt_fex_sync)() = NULL; /* new, improved version of above */
62 #pragma weak __libm_mt_fex_sync
63 #endif
64
65 /* private variables */
66 static fex_handler_t main_handlers;
67 static int handlers_initialized = 0;
68 static thread_key_t handlers_key;
69 static mutex_t handlers_key_lock = DEFAULTMUTEX;
70
71 static struct sigaction oact = { 0, SIG_DFL };
72 static mutex_t hdlr_lock = DEFAULTMUTEX;
73 static int hdlr_installed = 0;
74
75 /* private const data */
76 static const int te_bit[FEX_NUM_EXC] = {
77 1 << fp_trap_inexact,
78 1 << fp_trap_division,
79 1 << fp_trap_underflow,
80 1 << fp_trap_overflow,
81 1 << fp_trap_invalid,
82 1 << fp_trap_invalid,
83 1 << fp_trap_invalid,
128 __fex_sync_with_libmtsk(int begin, int master)
129 {
130 static fenv_t master_env;
131 static int env_initialized = 0;
132 static mutex_t env_lock = DEFAULTMUTEX;
133
134 if (begin) {
135 mutex_lock(&env_lock);
136 if (master) {
137 (void) fegetenv(&master_env);
138 env_initialized = 1;
139 }
140 else if (env_initialized)
141 (void) fesetenv(&master_env);
142 mutex_unlock(&env_lock);
143 }
144 else if (master && fex_get_log())
145 __fex_update_te();
146 }
147
148 #ifdef LIBM_MT_FEX_SYNC
149 /*
150 * The following function may be used for synchronization with any
151 * internal project that manages multiple threads
152 */
153 enum __libm_mt_fex_sync_actions {
154 __libm_mt_fex_start_master = 0,
155 __libm_mt_fex_start_slave,
156 __libm_mt_fex_finish_master,
157 __libm_mt_fex_finish_slave
158 };
159
160 struct __libm_mt_fex_sync_data {
161 fenv_t master_env;
162 int initialized;
163 mutex_t lock;
164 };
165
166 static void
167 __fex_sync_with_threads(enum __libm_mt_fex_sync_actions action,
168 struct __libm_mt_fex_sync_data *thr_env)
187 __fex_update_te();
188 #else
189 if (fex_get_log())
190 __fex_update_te();
191 #endif
192 break;
193
194 case __libm_mt_fex_finish_slave:
195 #if defined(__x86)
196 /* clear traps, making all accrued flags visible in status word */
197 {
198 unsigned long fsr;
199 __fenv_getfsr(&fsr);
200 __fenv_set_te(fsr, 0);
201 __fenv_setfsr(&fsr);
202 }
203 #endif
204 break;
205 }
206 }
207 #endif
208
209 #if defined(__sparc)
210
211 /*
212 * Code for setting or clearing interval mode on US-III and above.
213 * This is embedded as data so we don't have to mark the library
214 * as a v8plusb/v9b object. (I could have just used one entry and
215 * modified the second word to set the bits I want, but that would
216 * have required another mutex.)
217 */
218 static const unsigned int siam[][2] = {
219 { 0x81c3e008, 0x81b01020 }, /* retl, siam 0 */
220 { 0x81c3e008, 0x81b01024 }, /* retl, siam 4 */
221 { 0x81c3e008, 0x81b01025 }, /* retl, siam 5 */
222 { 0x81c3e008, 0x81b01026 }, /* retl, siam 6 */
223 { 0x81c3e008, 0x81b01027 } /* retl, siam 7 */
224 };
225
226 /*
227 * If a handling mode is in effect, apply it; otherwise invoke the
825 sigaction(SIGFPE, &act, &tmpact);
826 if (tmpact.sa_handler != __fex_hdlr)
827 {
828 mutex_lock(&hdlr_lock);
829 oact = tmpact;
830 mutex_unlock(&hdlr_lock);
831 }
832 hdlr_installed = 1;
833 }
834
835 /* set the new trap enable bits (only if SIGFPE is not blocked) */
836 if (sigprocmask(0, NULL, &blocked) == 0 &&
837 !sigismember(&blocked, SIGFPE)) {
838 __fenv_set_te(fsr, te);
839 __fenv_setfsr(&fsr);
840 }
841
842 /* synchronize with libmtsk */
843 __mt_fex_sync = __fex_sync_with_libmtsk;
844
845 #ifdef LIBM_MT_FEX_SYNC
846 /* synchronize with other projects */
847 __libm_mt_fex_sync = __fex_sync_with_threads;
848 #endif
849 }
|
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24 */
25 /*
26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
28 */
29
30 #undef lint
31 #include <signal.h>
32 #include <siginfo.h>
33 #include <ucontext.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <thread.h>
38 #include <math.h>
39 #if defined(__SUNPRO_C)
40 #include <sunmath.h>
41 #endif
42 #include <fenv.h>
43 #include "fex_handler.h"
44 #include "fenv_inlines.h"
45
46 #if defined(__sparc) && !defined(__sparcv9)
47 #include <sys/procfs.h>
48 #endif
49
50 /* 2.x signal.h doesn't declare sigemptyset or sigismember
51 if they're #defined (see sys/signal.h) */
52 extern int sigemptyset(sigset_t *);
53 extern int sigismember(const sigset_t *, int);
54
55 /* external globals */
56 void (*__mt_fex_sync)() = NULL; /* for synchronization with libmtsk */
57 #pragma weak __mt_fex_sync
58
59 void (*__libm_mt_fex_sync)() = NULL; /* new, improved version of above */
60 #pragma weak __libm_mt_fex_sync
61
62 /* private variables */
63 static fex_handler_t main_handlers;
64 static int handlers_initialized = 0;
65 static thread_key_t handlers_key;
66 static mutex_t handlers_key_lock = DEFAULTMUTEX;
67
68 static struct sigaction oact = { 0, SIG_DFL };
69 static mutex_t hdlr_lock = DEFAULTMUTEX;
70 static int hdlr_installed = 0;
71
72 /* private const data */
73 static const int te_bit[FEX_NUM_EXC] = {
74 1 << fp_trap_inexact,
75 1 << fp_trap_division,
76 1 << fp_trap_underflow,
77 1 << fp_trap_overflow,
78 1 << fp_trap_invalid,
79 1 << fp_trap_invalid,
80 1 << fp_trap_invalid,
125 __fex_sync_with_libmtsk(int begin, int master)
126 {
127 static fenv_t master_env;
128 static int env_initialized = 0;
129 static mutex_t env_lock = DEFAULTMUTEX;
130
131 if (begin) {
132 mutex_lock(&env_lock);
133 if (master) {
134 (void) fegetenv(&master_env);
135 env_initialized = 1;
136 }
137 else if (env_initialized)
138 (void) fesetenv(&master_env);
139 mutex_unlock(&env_lock);
140 }
141 else if (master && fex_get_log())
142 __fex_update_te();
143 }
144
145 /*
146 * The following function may be used for synchronization with any
147 * internal project that manages multiple threads
148 */
149 enum __libm_mt_fex_sync_actions {
150 __libm_mt_fex_start_master = 0,
151 __libm_mt_fex_start_slave,
152 __libm_mt_fex_finish_master,
153 __libm_mt_fex_finish_slave
154 };
155
156 struct __libm_mt_fex_sync_data {
157 fenv_t master_env;
158 int initialized;
159 mutex_t lock;
160 };
161
162 static void
163 __fex_sync_with_threads(enum __libm_mt_fex_sync_actions action,
164 struct __libm_mt_fex_sync_data *thr_env)
183 __fex_update_te();
184 #else
185 if (fex_get_log())
186 __fex_update_te();
187 #endif
188 break;
189
190 case __libm_mt_fex_finish_slave:
191 #if defined(__x86)
192 /* clear traps, making all accrued flags visible in status word */
193 {
194 unsigned long fsr;
195 __fenv_getfsr(&fsr);
196 __fenv_set_te(fsr, 0);
197 __fenv_setfsr(&fsr);
198 }
199 #endif
200 break;
201 }
202 }
203
204 #if defined(__sparc)
205
206 /*
207 * Code for setting or clearing interval mode on US-III and above.
208 * This is embedded as data so we don't have to mark the library
209 * as a v8plusb/v9b object. (I could have just used one entry and
210 * modified the second word to set the bits I want, but that would
211 * have required another mutex.)
212 */
213 static const unsigned int siam[][2] = {
214 { 0x81c3e008, 0x81b01020 }, /* retl, siam 0 */
215 { 0x81c3e008, 0x81b01024 }, /* retl, siam 4 */
216 { 0x81c3e008, 0x81b01025 }, /* retl, siam 5 */
217 { 0x81c3e008, 0x81b01026 }, /* retl, siam 6 */
218 { 0x81c3e008, 0x81b01027 } /* retl, siam 7 */
219 };
220
221 /*
222 * If a handling mode is in effect, apply it; otherwise invoke the
820 sigaction(SIGFPE, &act, &tmpact);
821 if (tmpact.sa_handler != __fex_hdlr)
822 {
823 mutex_lock(&hdlr_lock);
824 oact = tmpact;
825 mutex_unlock(&hdlr_lock);
826 }
827 hdlr_installed = 1;
828 }
829
830 /* set the new trap enable bits (only if SIGFPE is not blocked) */
831 if (sigprocmask(0, NULL, &blocked) == 0 &&
832 !sigismember(&blocked, SIGFPE)) {
833 __fenv_set_te(fsr, te);
834 __fenv_setfsr(&fsr);
835 }
836
837 /* synchronize with libmtsk */
838 __mt_fex_sync = __fex_sync_with_libmtsk;
839
840 /* synchronize with other projects */
841 __libm_mt_fex_sync = __fex_sync_with_threads;
842 }
|