Print this page
5261 libm should stop using synonyms.h
5298 fabs is 0-sized, confuses dis(1) and others
Reviewed by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
Approved by: Gordon Ross <gwr@nexenta.com>
5262 libm needs to be carefully unifdef'd
5268 libm doesn't need to hide symbols which are already local
Reviewed by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com>
Reviewed by: Gordon Ross <gwr@nexenta.com>
Approved by: Gordon Ross <gwr@nexenta.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libm/common/m9x/__fex_hdlr.c
+++ new/usr/src/lib/libm/common/m9x/__fex_hdlr.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
20 20 */
21 21
22 22 /*
23 23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24 24 */
25 25 /*
26 26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
27 27 * Use is subject to license terms.
28 28 */
29 29
30 -#include "fenv_synonyms.h"
31 30 #undef lint
32 31 #include <signal.h>
33 32 #include <siginfo.h>
34 33 #include <ucontext.h>
35 34 #include <stdio.h>
36 35 #include <stdlib.h>
37 36 #include <unistd.h>
38 37 #include <thread.h>
39 38 #include <math.h>
40 39 #if defined(__SUNPRO_C)
41 40 #include <sunmath.h>
42 41 #endif
43 42 #include <fenv.h>
44 43 #include "fex_handler.h"
45 44 #include "fenv_inlines.h"
46 45
47 46 #if defined(__sparc) && !defined(__sparcv9)
48 47 #include <sys/procfs.h>
49 48 #endif
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
50 49
51 50 /* 2.x signal.h doesn't declare sigemptyset or sigismember
52 51 if they're #defined (see sys/signal.h) */
53 52 extern int sigemptyset(sigset_t *);
54 53 extern int sigismember(const sigset_t *, int);
55 54
56 55 /* external globals */
57 56 void (*__mt_fex_sync)() = NULL; /* for synchronization with libmtsk */
58 57 #pragma weak __mt_fex_sync
59 58
60 -#ifdef LIBM_MT_FEX_SYNC
61 59 void (*__libm_mt_fex_sync)() = NULL; /* new, improved version of above */
62 60 #pragma weak __libm_mt_fex_sync
63 -#endif
64 61
65 62 /* private variables */
66 63 static fex_handler_t main_handlers;
67 64 static int handlers_initialized = 0;
68 65 static thread_key_t handlers_key;
69 66 static mutex_t handlers_key_lock = DEFAULTMUTEX;
70 67
71 68 static struct sigaction oact = { 0, SIG_DFL };
72 69 static mutex_t hdlr_lock = DEFAULTMUTEX;
73 70 static int hdlr_installed = 0;
74 71
75 72 /* private const data */
76 73 static const int te_bit[FEX_NUM_EXC] = {
77 74 1 << fp_trap_inexact,
78 75 1 << fp_trap_division,
79 76 1 << fp_trap_underflow,
80 77 1 << fp_trap_overflow,
81 78 1 << fp_trap_invalid,
82 79 1 << fp_trap_invalid,
83 80 1 << fp_trap_invalid,
84 81 1 << fp_trap_invalid,
85 82 1 << fp_trap_invalid,
86 83 1 << fp_trap_invalid,
87 84 1 << fp_trap_invalid,
88 85 1 << fp_trap_invalid
89 86 };
90 87
91 88 /*
92 89 * Return the traps to be enabled given the current handling modes
93 90 * and flags
94 91 */
95 92 static int
96 93 __fex_te_needed(struct fex_handler_data *thr_handlers, unsigned long fsr)
97 94 {
98 95 int i, ex, te;
99 96
100 97 /* set traps for handling modes */
101 98 te = 0;
102 99 for (i = 0; i < FEX_NUM_EXC; i++)
103 100 if (thr_handlers[i].__mode != FEX_NONSTOP)
104 101 te |= te_bit[i];
105 102
106 103 /* add traps for retrospective diagnostics */
107 104 if (fex_get_log()) {
108 105 ex = (int)__fenv_get_ex(fsr);
109 106 if (!(ex & FE_INEXACT))
110 107 te |= (1 << fp_trap_inexact);
111 108 if (!(ex & FE_UNDERFLOW))
112 109 te |= (1 << fp_trap_underflow);
113 110 if (!(ex & FE_OVERFLOW))
114 111 te |= (1 << fp_trap_overflow);
115 112 if (!(ex & FE_DIVBYZERO))
116 113 te |= (1 << fp_trap_division);
117 114 if (!(ex & FE_INVALID))
118 115 te |= (1 << fp_trap_invalid);
119 116 }
120 117
121 118 return te;
122 119 }
123 120
124 121 /*
125 122 * The following function synchronizes with libmtsk (SPARC only, for now)
126 123 */
127 124 static void
128 125 __fex_sync_with_libmtsk(int begin, int master)
129 126 {
130 127 static fenv_t master_env;
131 128 static int env_initialized = 0;
132 129 static mutex_t env_lock = DEFAULTMUTEX;
133 130
134 131 if (begin) {
135 132 mutex_lock(&env_lock);
136 133 if (master) {
137 134 (void) fegetenv(&master_env);
↓ open down ↓ |
64 lines elided |
↑ open up ↑ |
138 135 env_initialized = 1;
139 136 }
140 137 else if (env_initialized)
141 138 (void) fesetenv(&master_env);
142 139 mutex_unlock(&env_lock);
143 140 }
144 141 else if (master && fex_get_log())
145 142 __fex_update_te();
146 143 }
147 144
148 -#ifdef LIBM_MT_FEX_SYNC
149 145 /*
150 146 * The following function may be used for synchronization with any
151 147 * internal project that manages multiple threads
152 148 */
153 149 enum __libm_mt_fex_sync_actions {
154 150 __libm_mt_fex_start_master = 0,
155 151 __libm_mt_fex_start_slave,
156 152 __libm_mt_fex_finish_master,
157 153 __libm_mt_fex_finish_slave
158 154 };
159 155
160 156 struct __libm_mt_fex_sync_data {
161 157 fenv_t master_env;
162 158 int initialized;
163 159 mutex_t lock;
164 160 };
165 161
166 162 static void
167 163 __fex_sync_with_threads(enum __libm_mt_fex_sync_actions action,
168 164 struct __libm_mt_fex_sync_data *thr_env)
169 165 {
170 166 switch (action) {
171 167 case __libm_mt_fex_start_master:
172 168 mutex_lock(&thr_env->lock);
173 169 (void) fegetenv(&thr_env->master_env);
174 170 thr_env->initialized = 1;
175 171 mutex_unlock(&thr_env->lock);
176 172 break;
177 173
178 174 case __libm_mt_fex_start_slave:
179 175 mutex_lock(&thr_env->lock);
180 176 if (thr_env->initialized)
181 177 (void) fesetenv(&thr_env->master_env);
182 178 mutex_unlock(&thr_env->lock);
183 179 break;
184 180
185 181 case __libm_mt_fex_finish_master:
186 182 #if defined(__x86)
187 183 __fex_update_te();
188 184 #else
189 185 if (fex_get_log())
190 186 __fex_update_te();
191 187 #endif
192 188 break;
193 189
194 190 case __libm_mt_fex_finish_slave:
195 191 #if defined(__x86)
196 192 /* clear traps, making all accrued flags visible in status word */
↓ open down ↓ |
38 lines elided |
↑ open up ↑ |
197 193 {
198 194 unsigned long fsr;
199 195 __fenv_getfsr(&fsr);
200 196 __fenv_set_te(fsr, 0);
201 197 __fenv_setfsr(&fsr);
202 198 }
203 199 #endif
204 200 break;
205 201 }
206 202 }
207 -#endif
208 203
209 204 #if defined(__sparc)
210 205
211 206 /*
212 207 * Code for setting or clearing interval mode on US-III and above.
213 208 * This is embedded as data so we don't have to mark the library
214 209 * as a v8plusb/v9b object. (I could have just used one entry and
215 210 * modified the second word to set the bits I want, but that would
216 211 * have required another mutex.)
217 212 */
218 213 static const unsigned int siam[][2] = {
219 214 { 0x81c3e008, 0x81b01020 }, /* retl, siam 0 */
220 215 { 0x81c3e008, 0x81b01024 }, /* retl, siam 4 */
221 216 { 0x81c3e008, 0x81b01025 }, /* retl, siam 5 */
222 217 { 0x81c3e008, 0x81b01026 }, /* retl, siam 6 */
223 218 { 0x81c3e008, 0x81b01027 } /* retl, siam 7 */
224 219 };
225 220
226 221 /*
227 222 * If a handling mode is in effect, apply it; otherwise invoke the
228 223 * saved handler
229 224 */
230 225 static void
231 226 __fex_hdlr(int sig, siginfo_t *sip, ucontext_t *uap)
232 227 {
233 228 struct fex_handler_data *thr_handlers;
234 229 struct sigaction act;
235 230 void (*handler)(), (*siamp)();
236 231 int mode, i;
237 232 enum fex_exception e;
238 233 fex_info_t info;
239 234 unsigned long fsr, tmpfsr, addr;
240 235 unsigned int gsr;
241 236
242 237 /* determine which exception occurred */
243 238 switch (sip->si_code) {
244 239 case FPE_FLTDIV:
245 240 e = fex_division;
246 241 break;
247 242 case FPE_FLTOVF:
248 243 e = fex_overflow;
249 244 break;
250 245 case FPE_FLTUND:
251 246 e = fex_underflow;
252 247 break;
253 248 case FPE_FLTRES:
254 249 e = fex_inexact;
255 250 break;
256 251 case FPE_FLTINV:
257 252 if ((int)(e = __fex_get_invalid_type(sip, uap)) < 0)
258 253 goto not_ieee;
259 254 break;
260 255 default:
261 256 /* not an IEEE exception */
262 257 goto not_ieee;
263 258 }
264 259
265 260 /* get the handling mode */
266 261 mode = FEX_NOHANDLER;
267 262 handler = oact.sa_handler; /* for log; just looking, no need to lock */
268 263 thr_handlers = __fex_get_thr_handlers();
269 264 if (thr_handlers && thr_handlers[(int)e].__mode != FEX_NOHANDLER) {
270 265 mode = thr_handlers[(int)e].__mode;
271 266 handler = thr_handlers[(int)e].__handler;
272 267 }
273 268
274 269 /* make an entry in the log of retro. diag. if need be */
275 270 i = ((int)uap->uc_mcontext.fpregs.fpu_fsr >> 5) & 0x1f;
276 271 __fex_mklog(uap, (char *)sip->si_addr, i, e, mode, (void *)handler);
277 272
278 273 /* handle the exception based on the mode */
279 274 if (mode == FEX_NOHANDLER)
280 275 goto not_ieee;
281 276 else if (mode == FEX_ABORT)
282 277 abort();
283 278 else if (mode == FEX_SIGNAL) {
284 279 handler(sig, sip, uap);
285 280 return;
286 281 }
287 282
288 283 /* custom or nonstop mode; disable traps and clear flags */
289 284 __fenv_getfsr(&fsr);
290 285 __fenv_set_te(fsr, 0);
291 286 __fenv_set_ex(fsr, 0);
292 287
293 288 /* if interval mode was set, clear it, then substitute the
294 289 interval rounding direction and clear ns mode in the fsr */
295 290 #ifdef __sparcv9
296 291 gsr = uap->uc_mcontext.asrs[3];
297 292 #else
298 293 gsr = 0;
299 294 if (uap->uc_mcontext.xrs.xrs_id == XRS_ID)
300 295 gsr = (*(unsigned long long*)((prxregset_t*)uap->uc_mcontext.
301 296 xrs.xrs_ptr)->pr_un.pr_v8p.pr_filler);
302 297 #endif
303 298 gsr = (gsr >> 25) & 7;
304 299 if (gsr & 4) {
305 300 siamp = (void (*)()) siam[0];
306 301 siamp();
307 302 tmpfsr = fsr;
308 303 fsr = (fsr & ~0xc0400000ul) | ((gsr & 3) << 30);
309 304 }
310 305 __fenv_setfsr(&fsr);
311 306
312 307 /* decode the operation */
313 308 __fex_get_op(sip, uap, &info);
314 309
315 310 /* if a custom mode handler is installed, invoke it */
316 311 if (mode == FEX_CUSTOM) {
317 312 /* if we got here from feraiseexcept, pass dummy info */
318 313 addr = (unsigned long)sip->si_addr;
319 314 if (addr >= (unsigned long)feraiseexcept &&
320 315 addr < (unsigned long)fetestexcept) {
321 316 info.op = fex_other;
322 317 info.op1.type = info.op2.type = info.res.type =
323 318 fex_nodata;
324 319 }
325 320
326 321 /* restore interval mode if it was set, and put the original
327 322 rounding direction and ns mode back in the fsr */
328 323 if (gsr & 4) {
329 324 __fenv_setfsr(&tmpfsr);
330 325 siamp = (void (*)()) siam[1 + (gsr & 3)];
331 326 siamp();
332 327 }
333 328
334 329 handler(1 << (int)e, &info);
335 330
336 331 /* restore modes in case the user's handler changed them */
337 332 if (gsr & 4) {
338 333 siamp = (void (*)()) siam[0];
339 334 siamp();
340 335 }
341 336 __fenv_setfsr(&fsr);
342 337 }
343 338
344 339 /* stuff the result */
345 340 __fex_st_result(sip, uap, &info);
346 341
347 342 /* "or" in any exception flags and update traps */
348 343 fsr = uap->uc_mcontext.fpregs.fpu_fsr;
349 344 fsr |= ((info.flags & 0x1f) << 5);
350 345 i = __fex_te_needed(thr_handlers, fsr);
351 346 __fenv_set_te(fsr, i);
352 347 uap->uc_mcontext.fpregs.fpu_fsr = fsr;
353 348 return;
354 349
355 350 not_ieee:
356 351 /* revert to the saved handler (if any) */
357 352 mutex_lock(&hdlr_lock);
358 353 act = oact;
359 354 mutex_unlock(&hdlr_lock);
360 355 switch ((unsigned long)act.sa_handler) {
361 356 case (unsigned long)SIG_DFL:
362 357 /* simulate trap with no handler installed */
363 358 sigaction(SIGFPE, &act, NULL);
364 359 kill(getpid(), SIGFPE);
365 360 break;
366 361 #if !defined(__lint)
367 362 case (unsigned long)SIG_IGN:
368 363 break;
369 364 #endif
370 365 default:
371 366 act.sa_handler(sig, sip, uap);
372 367 }
373 368 }
374 369
375 370 #elif defined(__x86)
376 371
377 372 #if defined(__amd64)
378 373 #define test_sse_hw 1
379 374 #else
380 375 extern int _sse_hw;
381 376 #define test_sse_hw _sse_hw
382 377 #endif
383 378
384 379 #if !defined(REG_PC)
385 380 #define REG_PC EIP
386 381 #endif
387 382
388 383 /*
389 384 * If a handling mode is in effect, apply it; otherwise invoke the
390 385 * saved handler
391 386 */
392 387 static void
393 388 __fex_hdlr(int sig, siginfo_t *sip, ucontext_t *uap)
394 389 {
395 390 struct fex_handler_data *thr_handlers;
396 391 struct sigaction act;
397 392 void (*handler)() = NULL, (*simd_handler[4])();
398 393 int mode, simd_mode[4], i, len, accrued, *ap;
399 394 unsigned int cwsw, oldcwsw, mxcsr, oldmxcsr;
400 395 enum fex_exception e, simd_e[4];
401 396 fex_info_t info, simd_info[4];
402 397 unsigned long addr;
403 398 siginfo_t osip = *sip;
404 399 sseinst_t inst;
405 400
406 401 /* check for an exception caused by an SSE instruction */
407 402 if (!(uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.status & 0x80)) {
408 403 len = __fex_parse_sse(uap, &inst);
409 404 if (len == 0)
410 405 goto not_ieee;
411 406
412 407 /* disable all traps and clear flags */
413 408 __fenv_getcwsw(&oldcwsw);
414 409 cwsw = (oldcwsw & ~0x3f) | 0x003f0000;
415 410 __fenv_setcwsw(&cwsw);
416 411 __fenv_getmxcsr(&oldmxcsr);
417 412 mxcsr = (oldmxcsr & ~0x3f) | 0x1f80;
418 413 __fenv_setmxcsr(&mxcsr);
419 414
420 415 if ((int)inst.op & SIMD) {
421 416 __fex_get_simd_op(uap, &inst, simd_e, simd_info);
422 417
423 418 thr_handlers = __fex_get_thr_handlers();
424 419 addr = (unsigned long)uap->uc_mcontext.gregs[REG_PC];
425 420 accrued = uap->uc_mcontext.fpregs.fp_reg_set.
426 421 fpchip_state.mxcsr;
427 422
428 423 e = (enum fex_exception)-1;
429 424 mode = FEX_NONSTOP;
430 425 for (i = 0; i < 4; i++) {
431 426 if ((int)simd_e[i] < 0)
432 427 continue;
433 428
434 429 e = simd_e[i];
435 430 simd_mode[i] = FEX_NOHANDLER;
436 431 simd_handler[i] = oact.sa_handler;
437 432 if (thr_handlers &&
438 433 thr_handlers[(int)e].__mode !=
439 434 FEX_NOHANDLER) {
440 435 simd_mode[i] =
441 436 thr_handlers[(int)e].__mode;
442 437 simd_handler[i] =
443 438 thr_handlers[(int)e].__handler;
444 439 }
445 440 accrued &= ~te_bit[(int)e];
446 441 switch (simd_mode[i]) {
447 442 case FEX_ABORT:
448 443 mode = FEX_ABORT;
449 444 break;
450 445 case FEX_SIGNAL:
451 446 if (mode != FEX_ABORT)
452 447 mode = FEX_SIGNAL;
453 448 handler = simd_handler[i];
454 449 break;
455 450 case FEX_NOHANDLER:
456 451 if (mode != FEX_ABORT && mode !=
457 452 FEX_SIGNAL)
458 453 mode = FEX_NOHANDLER;
459 454 break;
460 455 }
461 456 }
462 457 if (e == (enum fex_exception)-1) {
463 458 __fenv_setcwsw(&oldcwsw);
464 459 __fenv_setmxcsr(&oldmxcsr);
465 460 goto not_ieee;
466 461 }
467 462 accrued |= uap->uc_mcontext.fpregs.fp_reg_set.
468 463 fpchip_state.status;
469 464 ap = __fex_accrued();
470 465 accrued |= *ap;
471 466 accrued &= 0x3d;
472 467
473 468 for (i = 0; i < 4; i++) {
474 469 if ((int)simd_e[i] < 0)
475 470 continue;
476 471
477 472 __fex_mklog(uap, (char *)addr, accrued,
478 473 simd_e[i], simd_mode[i],
479 474 (void *)simd_handler[i]);
480 475 }
481 476
482 477 if (mode == FEX_NOHANDLER) {
483 478 __fenv_setcwsw(&oldcwsw);
484 479 __fenv_setmxcsr(&oldmxcsr);
485 480 goto not_ieee;
486 481 } else if (mode == FEX_ABORT) {
487 482 abort();
488 483 } else if (mode == FEX_SIGNAL) {
489 484 __fenv_setcwsw(&oldcwsw);
490 485 __fenv_setmxcsr(&oldmxcsr);
491 486 handler(sig, &osip, uap);
492 487 return;
493 488 }
494 489
495 490 *ap = 0;
496 491 for (i = 0; i < 4; i++) {
497 492 if ((int)simd_e[i] < 0)
498 493 continue;
499 494
500 495 if (simd_mode[i] == FEX_CUSTOM) {
501 496 handler(1 << (int)simd_e[i],
502 497 &simd_info[i]);
503 498 __fenv_setcwsw(&cwsw);
504 499 __fenv_setmxcsr(&mxcsr);
505 500 }
506 501 }
507 502
508 503 __fex_st_simd_result(uap, &inst, simd_e, simd_info);
509 504 for (i = 0; i < 4; i++) {
510 505 if ((int)simd_e[i] < 0)
511 506 continue;
512 507
513 508 accrued |= simd_info[i].flags;
514 509 }
515 510
516 511 if ((int)inst.op & INTREG) {
517 512 /* set MMX mode */
518 513 #if defined(__amd64)
519 514 uap->uc_mcontext.fpregs.fp_reg_set.
520 515 fpchip_state.sw &= ~0x3800;
521 516 uap->uc_mcontext.fpregs.fp_reg_set.
522 517 fpchip_state.fctw = 0;
523 518 #else
524 519 uap->uc_mcontext.fpregs.fp_reg_set.
525 520 fpchip_state.state[1] &= ~0x3800;
526 521 uap->uc_mcontext.fpregs.fp_reg_set.
527 522 fpchip_state.state[2] = 0;
528 523 #endif
529 524 }
530 525 } else {
531 526 e = __fex_get_sse_op(uap, &inst, &info);
532 527 if ((int)e < 0) {
533 528 __fenv_setcwsw(&oldcwsw);
534 529 __fenv_setmxcsr(&oldmxcsr);
535 530 goto not_ieee;
536 531 }
537 532
538 533 mode = FEX_NOHANDLER;
539 534 handler = oact.sa_handler;
540 535 thr_handlers = __fex_get_thr_handlers();
541 536 if (thr_handlers && thr_handlers[(int)e].__mode !=
542 537 FEX_NOHANDLER) {
543 538 mode = thr_handlers[(int)e].__mode;
544 539 handler = thr_handlers[(int)e].__handler;
545 540 }
546 541
547 542 addr = (unsigned long)uap->uc_mcontext.gregs[REG_PC];
548 543 accrued = uap->uc_mcontext.fpregs.fp_reg_set.
549 544 fpchip_state.mxcsr & ~te_bit[(int)e];
550 545 accrued |= uap->uc_mcontext.fpregs.fp_reg_set.
551 546 fpchip_state.status;
552 547 ap = __fex_accrued();
553 548 accrued |= *ap;
554 549 accrued &= 0x3d;
555 550 __fex_mklog(uap, (char *)addr, accrued, e, mode,
556 551 (void *)handler);
557 552
558 553 if (mode == FEX_NOHANDLER) {
559 554 __fenv_setcwsw(&oldcwsw);
560 555 __fenv_setmxcsr(&oldmxcsr);
561 556 goto not_ieee;
562 557 } else if (mode == FEX_ABORT) {
563 558 abort();
564 559 } else if (mode == FEX_SIGNAL) {
565 560 __fenv_setcwsw(&oldcwsw);
566 561 __fenv_setmxcsr(&oldmxcsr);
567 562 handler(sig, &osip, uap);
568 563 return;
569 564 } else if (mode == FEX_CUSTOM) {
570 565 *ap = 0;
571 566 if (addr >= (unsigned long)feraiseexcept &&
572 567 addr < (unsigned long)fetestexcept) {
573 568 info.op = fex_other;
574 569 info.op1.type = info.op2.type =
575 570 info.res.type = fex_nodata;
576 571 }
577 572 handler(1 << (int)e, &info);
578 573 __fenv_setcwsw(&cwsw);
579 574 __fenv_setmxcsr(&mxcsr);
580 575 }
581 576
582 577 __fex_st_sse_result(uap, &inst, e, &info);
583 578 accrued |= info.flags;
584 579
585 580 #if defined(__amd64)
586 581 /*
587 582 * In 64-bit mode, the 32-bit convert-to-integer
588 583 * instructions zero the upper 32 bits of the
589 584 * destination. (We do this here and not in
590 585 * __fex_st_sse_result because __fex_st_sse_result
591 586 * can be called from __fex_st_simd_result, too.)
592 587 */
593 588 if (inst.op == cvtss2si || inst.op == cvttss2si ||
594 589 inst.op == cvtsd2si || inst.op == cvttsd2si)
595 590 inst.op1->i[1] = 0;
596 591 #endif
597 592 }
598 593
599 594 /* advance the pc past the SSE instruction */
600 595 uap->uc_mcontext.gregs[REG_PC] += len;
601 596 goto update_state;
602 597 }
603 598
604 599 /* determine which exception occurred */
605 600 __fex_get_x86_exc(sip, uap);
606 601 switch (sip->si_code) {
607 602 case FPE_FLTDIV:
608 603 e = fex_division;
609 604 break;
610 605 case FPE_FLTOVF:
611 606 e = fex_overflow;
612 607 break;
613 608 case FPE_FLTUND:
614 609 e = fex_underflow;
615 610 break;
616 611 case FPE_FLTRES:
617 612 e = fex_inexact;
618 613 break;
619 614 case FPE_FLTINV:
620 615 if ((int)(e = __fex_get_invalid_type(sip, uap)) < 0)
621 616 goto not_ieee;
622 617 break;
623 618 default:
624 619 /* not an IEEE exception */
625 620 goto not_ieee;
626 621 }
627 622
628 623 /* get the handling mode */
629 624 mode = FEX_NOHANDLER;
630 625 handler = oact.sa_handler; /* for log; just looking, no need to lock */
631 626 thr_handlers = __fex_get_thr_handlers();
632 627 if (thr_handlers && thr_handlers[(int)e].__mode != FEX_NOHANDLER) {
633 628 mode = thr_handlers[(int)e].__mode;
634 629 handler = thr_handlers[(int)e].__handler;
635 630 }
636 631
637 632 /* make an entry in the log of retro. diag. if need be */
638 633 #if defined(__amd64)
639 634 addr = (unsigned long)uap->uc_mcontext.fpregs.fp_reg_set.
640 635 fpchip_state.rip;
641 636 #else
642 637 addr = (unsigned long)uap->uc_mcontext.fpregs.fp_reg_set.
643 638 fpchip_state.state[3];
644 639 #endif
645 640 accrued = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.status &
646 641 ~te_bit[(int)e];
647 642 if (test_sse_hw)
648 643 accrued |= uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.
649 644 mxcsr;
650 645 ap = __fex_accrued();
651 646 accrued |= *ap;
652 647 accrued &= 0x3d;
653 648 __fex_mklog(uap, (char *)addr, accrued, e, mode, (void *)handler);
654 649
655 650 /* handle the exception based on the mode */
656 651 if (mode == FEX_NOHANDLER)
657 652 goto not_ieee;
658 653 else if (mode == FEX_ABORT)
659 654 abort();
660 655 else if (mode == FEX_SIGNAL) {
661 656 handler(sig, &osip, uap);
662 657 return;
663 658 }
664 659
665 660 /* disable all traps and clear flags */
666 661 __fenv_getcwsw(&cwsw);
667 662 cwsw = (cwsw & ~0x3f) | 0x003f0000;
668 663 __fenv_setcwsw(&cwsw);
669 664 if (test_sse_hw) {
670 665 __fenv_getmxcsr(&mxcsr);
671 666 mxcsr = (mxcsr & ~0x3f) | 0x1f80;
672 667 __fenv_setmxcsr(&mxcsr);
673 668 }
674 669 *ap = 0;
675 670
676 671 /* decode the operation */
677 672 __fex_get_op(sip, uap, &info);
678 673
679 674 /* if a custom mode handler is installed, invoke it */
680 675 if (mode == FEX_CUSTOM) {
681 676 /* if we got here from feraiseexcept, pass dummy info */
682 677 if (addr >= (unsigned long)feraiseexcept &&
683 678 addr < (unsigned long)fetestexcept) {
684 679 info.op = fex_other;
685 680 info.op1.type = info.op2.type = info.res.type =
686 681 fex_nodata;
687 682 }
688 683
689 684 handler(1 << (int)e, &info);
690 685
691 686 /* restore modes in case the user's handler changed them */
692 687 __fenv_setcwsw(&cwsw);
693 688 if (test_sse_hw)
694 689 __fenv_setmxcsr(&mxcsr);
695 690 }
696 691
697 692 /* stuff the result */
698 693 __fex_st_result(sip, uap, &info);
699 694 accrued |= info.flags;
700 695
701 696 update_state:
702 697 accrued &= 0x3d;
703 698 i = __fex_te_needed(thr_handlers, accrued);
704 699 *ap = accrued & i;
705 700 #if defined(__amd64)
706 701 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw &= ~0x3d;
707 702 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |= (accrued & ~i);
708 703 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.cw |= 0x3d;
709 704 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.cw &= ~i;
710 705 #else
711 706 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[1] &= ~0x3d;
712 707 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[1] |=
713 708 (accrued & ~i);
714 709 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[0] |= 0x3d;
715 710 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[0] &= ~i;
716 711 #endif
717 712 if (test_sse_hw) {
718 713 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr &= ~0x3d;
719 714 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr |=
720 715 0x1e80 | (accrued & ~i);
721 716 uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr &=
722 717 ~(i << 7);
723 718 }
724 719 return;
725 720
726 721 not_ieee:
727 722 /* revert to the saved handler (if any) */
728 723 mutex_lock(&hdlr_lock);
729 724 act = oact;
730 725 mutex_unlock(&hdlr_lock);
731 726 switch ((unsigned long)act.sa_handler) {
732 727 case (unsigned long)SIG_DFL:
733 728 /* simulate trap with no handler installed */
734 729 sigaction(SIGFPE, &act, NULL);
735 730 kill(getpid(), SIGFPE);
736 731 break;
737 732 #if !defined(__lint)
738 733 case (unsigned long)SIG_IGN:
739 734 break;
740 735 #endif
741 736 default:
742 737 act.sa_handler(sig, &osip, uap);
743 738 }
744 739 }
745 740
746 741 #else
747 742 #error Unknown architecture
748 743 #endif
749 744
750 745 /*
751 746 * Return a pointer to the thread-specific handler data, and
752 747 * initialize it if necessary
753 748 */
754 749 struct fex_handler_data *
755 750 __fex_get_thr_handlers()
756 751 {
757 752 struct fex_handler_data *ptr;
758 753 unsigned long fsr;
759 754 int i, te;
760 755
761 756 if (thr_main()) {
762 757 if (!handlers_initialized) {
763 758 /* initialize to FEX_NOHANDLER if trap is enabled,
764 759 FEX_NONSTOP if trap is disabled */
765 760 __fenv_getfsr(&fsr);
766 761 te = (int)__fenv_get_te(fsr);
767 762 for (i = 0; i < FEX_NUM_EXC; i++)
768 763 main_handlers[i].__mode =
769 764 ((te & te_bit[i])? FEX_NOHANDLER : FEX_NONSTOP);
770 765 handlers_initialized = 1;
771 766 }
772 767 return main_handlers;
773 768 }
774 769 else {
775 770 ptr = NULL;
776 771 mutex_lock(&handlers_key_lock);
777 772 if (thr_getspecific(handlers_key, (void **)&ptr) != 0 &&
778 773 thr_keycreate(&handlers_key, free) != 0) {
779 774 mutex_unlock(&handlers_key_lock);
780 775 return NULL;
781 776 }
782 777 mutex_unlock(&handlers_key_lock);
783 778 if (!ptr) {
784 779 if ((ptr = (struct fex_handler_data *)
785 780 malloc(sizeof(fex_handler_t))) == NULL) {
786 781 return NULL;
787 782 }
788 783 if (thr_setspecific(handlers_key, (void *)ptr) != 0) {
789 784 (void)free(ptr);
790 785 return NULL;
791 786 }
792 787 /* initialize to FEX_NOHANDLER if trap is enabled,
793 788 FEX_NONSTOP if trap is disabled */
794 789 __fenv_getfsr(&fsr);
795 790 te = (int)__fenv_get_te(fsr);
796 791 for (i = 0; i < FEX_NUM_EXC; i++)
797 792 ptr[i].__mode = ((te & te_bit[i])? FEX_NOHANDLER : FEX_NONSTOP);
798 793 }
799 794 return ptr;
800 795 }
801 796 }
802 797
803 798 /*
804 799 * Update the trap enable bits according to the selected modes
805 800 */
806 801 void
807 802 __fex_update_te()
808 803 {
809 804 struct fex_handler_data *thr_handlers;
810 805 struct sigaction act, tmpact;
811 806 sigset_t blocked;
812 807 unsigned long fsr;
813 808 int te;
814 809
815 810 /* determine which traps are needed */
816 811 thr_handlers = __fex_get_thr_handlers();
817 812 __fenv_getfsr(&fsr);
818 813 te = __fex_te_needed(thr_handlers, fsr);
819 814
820 815 /* install __fex_hdlr as necessary */
821 816 if (!hdlr_installed && te) {
822 817 act.sa_handler = __fex_hdlr;
823 818 sigemptyset(&act.sa_mask);
824 819 act.sa_flags = SA_SIGINFO;
825 820 sigaction(SIGFPE, &act, &tmpact);
826 821 if (tmpact.sa_handler != __fex_hdlr)
827 822 {
828 823 mutex_lock(&hdlr_lock);
829 824 oact = tmpact;
830 825 mutex_unlock(&hdlr_lock);
831 826 }
832 827 hdlr_installed = 1;
833 828 }
834 829
↓ open down ↓ |
617 lines elided |
↑ open up ↑ |
835 830 /* set the new trap enable bits (only if SIGFPE is not blocked) */
836 831 if (sigprocmask(0, NULL, &blocked) == 0 &&
837 832 !sigismember(&blocked, SIGFPE)) {
838 833 __fenv_set_te(fsr, te);
839 834 __fenv_setfsr(&fsr);
840 835 }
841 836
842 837 /* synchronize with libmtsk */
843 838 __mt_fex_sync = __fex_sync_with_libmtsk;
844 839
845 -#ifdef LIBM_MT_FEX_SYNC
846 840 /* synchronize with other projects */
847 841 __libm_mt_fex_sync = __fex_sync_with_threads;
848 -#endif
849 842 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX