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 }
|
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 void (*__libm_mt_fex_sync)() = NULL; /* new, improved version of above */
61 #pragma weak __libm_mt_fex_sync
62
63 /* private variables */
64 static fex_handler_t main_handlers;
65 static int handlers_initialized = 0;
66 static thread_key_t handlers_key;
67 static mutex_t handlers_key_lock = DEFAULTMUTEX;
68
69 static struct sigaction oact = { 0, SIG_DFL };
70 static mutex_t hdlr_lock = DEFAULTMUTEX;
71 static int hdlr_installed = 0;
72
73 /* private const data */
74 static const int te_bit[FEX_NUM_EXC] = {
75 1 << fp_trap_inexact,
76 1 << fp_trap_division,
77 1 << fp_trap_underflow,
78 1 << fp_trap_overflow,
79 1 << fp_trap_invalid,
80 1 << fp_trap_invalid,
81 1 << fp_trap_invalid,
126 __fex_sync_with_libmtsk(int begin, int master)
127 {
128 static fenv_t master_env;
129 static int env_initialized = 0;
130 static mutex_t env_lock = DEFAULTMUTEX;
131
132 if (begin) {
133 mutex_lock(&env_lock);
134 if (master) {
135 (void) fegetenv(&master_env);
136 env_initialized = 1;
137 }
138 else if (env_initialized)
139 (void) fesetenv(&master_env);
140 mutex_unlock(&env_lock);
141 }
142 else if (master && fex_get_log())
143 __fex_update_te();
144 }
145
146 /*
147 * The following function may be used for synchronization with any
148 * internal project that manages multiple threads
149 */
150 enum __libm_mt_fex_sync_actions {
151 __libm_mt_fex_start_master = 0,
152 __libm_mt_fex_start_slave,
153 __libm_mt_fex_finish_master,
154 __libm_mt_fex_finish_slave
155 };
156
157 struct __libm_mt_fex_sync_data {
158 fenv_t master_env;
159 int initialized;
160 mutex_t lock;
161 };
162
163 static void
164 __fex_sync_with_threads(enum __libm_mt_fex_sync_actions action,
165 struct __libm_mt_fex_sync_data *thr_env)
184 __fex_update_te();
185 #else
186 if (fex_get_log())
187 __fex_update_te();
188 #endif
189 break;
190
191 case __libm_mt_fex_finish_slave:
192 #if defined(__x86)
193 /* clear traps, making all accrued flags visible in status word */
194 {
195 unsigned long fsr;
196 __fenv_getfsr(&fsr);
197 __fenv_set_te(fsr, 0);
198 __fenv_setfsr(&fsr);
199 }
200 #endif
201 break;
202 }
203 }
204
205 #if defined(__sparc)
206
207 /*
208 * Code for setting or clearing interval mode on US-III and above.
209 * This is embedded as data so we don't have to mark the library
210 * as a v8plusb/v9b object. (I could have just used one entry and
211 * modified the second word to set the bits I want, but that would
212 * have required another mutex.)
213 */
214 static const unsigned int siam[][2] = {
215 { 0x81c3e008, 0x81b01020 }, /* retl, siam 0 */
216 { 0x81c3e008, 0x81b01024 }, /* retl, siam 4 */
217 { 0x81c3e008, 0x81b01025 }, /* retl, siam 5 */
218 { 0x81c3e008, 0x81b01026 }, /* retl, siam 6 */
219 { 0x81c3e008, 0x81b01027 } /* retl, siam 7 */
220 };
221
222 /*
223 * If a handling mode is in effect, apply it; otherwise invoke the
821 sigaction(SIGFPE, &act, &tmpact);
822 if (tmpact.sa_handler != __fex_hdlr)
823 {
824 mutex_lock(&hdlr_lock);
825 oact = tmpact;
826 mutex_unlock(&hdlr_lock);
827 }
828 hdlr_installed = 1;
829 }
830
831 /* set the new trap enable bits (only if SIGFPE is not blocked) */
832 if (sigprocmask(0, NULL, &blocked) == 0 &&
833 !sigismember(&blocked, SIGFPE)) {
834 __fenv_set_te(fsr, te);
835 __fenv_setfsr(&fsr);
836 }
837
838 /* synchronize with libmtsk */
839 __mt_fex_sync = __fex_sync_with_libmtsk;
840
841 /* synchronize with other projects */
842 __libm_mt_fex_sync = __fex_sync_with_threads;
843 }
|