Print this page
11210 libm should be cstyle(1ONBLD) clean

*** 20,29 **** --- 20,30 ---- */ /* * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ + /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */
*** 45,56 **** #if defined(__sparc) && !defined(__sparcv9) #include <sys/procfs.h> #endif ! /* 2.x signal.h doesn't declare sigemptyset or sigismember ! if they're #defined (see sys/signal.h) */ extern int sigemptyset(sigset_t *); extern int sigismember(const sigset_t *, int); /* external globals */ void (*__mt_fex_sync)() = NULL; /* for synchronization with libmtsk */ --- 46,59 ---- #if defined(__sparc) && !defined(__sparcv9) #include <sys/procfs.h> #endif ! /* ! * 2.x signal.h doesn't declare sigemptyset or sigismember ! * if they're #define'd (see sys/signal.h) ! */ extern int sigemptyset(sigset_t *); extern int sigismember(const sigset_t *, int); /* external globals */ void (*__mt_fex_sync)() = NULL; /* for synchronization with libmtsk */
*** 62,169 **** /* private variables */ static fex_handler_t main_handlers; static int handlers_initialized = 0; static thread_key_t handlers_key; static mutex_t handlers_key_lock = DEFAULTMUTEX; - static struct sigaction oact = { 0, SIG_DFL }; static mutex_t hdlr_lock = DEFAULTMUTEX; static int hdlr_installed = 0; /* private const data */ static const int te_bit[FEX_NUM_EXC] = { ! 1 << fp_trap_inexact, ! 1 << fp_trap_division, ! 1 << fp_trap_underflow, ! 1 << fp_trap_overflow, ! 1 << fp_trap_invalid, ! 1 << fp_trap_invalid, ! 1 << fp_trap_invalid, ! 1 << fp_trap_invalid, ! 1 << fp_trap_invalid, ! 1 << fp_trap_invalid, ! 1 << fp_trap_invalid, ! 1 << fp_trap_invalid }; /* ! * Return the traps to be enabled given the current handling modes ! * and flags ! */ static int __fex_te_needed(struct fex_handler_data *thr_handlers, unsigned long fsr) { int i, ex, te; /* set traps for handling modes */ te = 0; for (i = 0; i < FEX_NUM_EXC; i++) if (thr_handlers[i].__mode != FEX_NONSTOP) te |= te_bit[i]; /* add traps for retrospective diagnostics */ if (fex_get_log()) { ex = (int)__fenv_get_ex(fsr); if (!(ex & FE_INEXACT)) te |= (1 << fp_trap_inexact); if (!(ex & FE_UNDERFLOW)) te |= (1 << fp_trap_underflow); if (!(ex & FE_OVERFLOW)) te |= (1 << fp_trap_overflow); if (!(ex & FE_DIVBYZERO)) te |= (1 << fp_trap_division); if (!(ex & FE_INVALID)) te |= (1 << fp_trap_invalid); } ! return te; } /* ! * The following function synchronizes with libmtsk (SPARC only, for now) ! */ static void __fex_sync_with_libmtsk(int begin, int master) { static fenv_t master_env; static int env_initialized = 0; static mutex_t env_lock = DEFAULTMUTEX; if (begin) { mutex_lock(&env_lock); if (master) { (void) fegetenv(&master_env); env_initialized = 1; ! } ! else if (env_initialized) (void) fesetenv(&master_env); - mutex_unlock(&env_lock); } ! else if (master && fex_get_log()) __fex_update_te(); } /* ! * The following function may be used for synchronization with any ! * internal project that manages multiple threads ! */ enum __libm_mt_fex_sync_actions { ! __libm_mt_fex_start_master = 0, ! __libm_mt_fex_start_slave, ! __libm_mt_fex_finish_master, ! __libm_mt_fex_finish_slave }; struct __libm_mt_fex_sync_data { fenv_t master_env; int initialized; mutex_t lock; }; static void ! __fex_sync_with_threads(enum __libm_mt_fex_sync_actions action, ! struct __libm_mt_fex_sync_data *thr_env) { switch (action) { case __libm_mt_fex_start_master: mutex_lock(&thr_env->lock); (void) fegetenv(&thr_env->master_env); --- 65,170 ---- /* private variables */ static fex_handler_t main_handlers; static int handlers_initialized = 0; static thread_key_t handlers_key; static mutex_t handlers_key_lock = DEFAULTMUTEX; static struct sigaction oact = { 0, SIG_DFL }; static mutex_t hdlr_lock = DEFAULTMUTEX; static int hdlr_installed = 0; /* private const data */ static const int te_bit[FEX_NUM_EXC] = { ! 1 << fp_trap_inexact, 1 << fp_trap_division, 1 << fp_trap_underflow, ! 1 << fp_trap_overflow, 1 << fp_trap_invalid, 1 << fp_trap_invalid, ! 1 << fp_trap_invalid, 1 << fp_trap_invalid, 1 << fp_trap_invalid, ! 1 << fp_trap_invalid, 1 << fp_trap_invalid, 1 << fp_trap_invalid }; /* ! * Return the traps to be enabled given the current handling modes ! * and flags ! */ static int __fex_te_needed(struct fex_handler_data *thr_handlers, unsigned long fsr) { int i, ex, te; /* set traps for handling modes */ te = 0; + for (i = 0; i < FEX_NUM_EXC; i++) if (thr_handlers[i].__mode != FEX_NONSTOP) te |= te_bit[i]; /* add traps for retrospective diagnostics */ + if (fex_get_log()) { ex = (int)__fenv_get_ex(fsr); + if (!(ex & FE_INEXACT)) te |= (1 << fp_trap_inexact); + if (!(ex & FE_UNDERFLOW)) te |= (1 << fp_trap_underflow); + if (!(ex & FE_OVERFLOW)) te |= (1 << fp_trap_overflow); + if (!(ex & FE_DIVBYZERO)) te |= (1 << fp_trap_division); + if (!(ex & FE_INVALID)) te |= (1 << fp_trap_invalid); } ! return (te); } /* ! * The following function synchronizes with libmtsk (SPARC only, for now) ! */ static void __fex_sync_with_libmtsk(int begin, int master) { static fenv_t master_env; static int env_initialized = 0; static mutex_t env_lock = DEFAULTMUTEX; if (begin) { mutex_lock(&env_lock); + if (master) { (void) fegetenv(&master_env); env_initialized = 1; ! } else if (env_initialized) { (void) fesetenv(&master_env); } ! ! mutex_unlock(&env_lock); ! } else if (master && fex_get_log()) { __fex_update_te(); + } } /* ! * The following function may be used for synchronization with any ! * internal project that manages multiple threads ! */ enum __libm_mt_fex_sync_actions { ! __libm_mt_fex_start_master = 0, __libm_mt_fex_start_slave, ! __libm_mt_fex_finish_master, __libm_mt_fex_finish_slave }; struct __libm_mt_fex_sync_data { fenv_t master_env; int initialized; mutex_t lock; }; static void ! __fex_sync_with_threads(enum __libm_mt_fex_sync_actions action, struct ! __libm_mt_fex_sync_data *thr_env) { switch (action) { case __libm_mt_fex_start_master: mutex_lock(&thr_env->lock); (void) fegetenv(&thr_env->master_env);
*** 171,182 **** --- 172,185 ---- mutex_unlock(&thr_env->lock); break; case __libm_mt_fex_start_slave: mutex_lock(&thr_env->lock); + if (thr_env->initialized) (void) fesetenv(&thr_env->master_env); + mutex_unlock(&thr_env->lock); break; case __libm_mt_fex_finish_master: #if defined(__x86)
*** 187,235 **** #endif break; case __libm_mt_fex_finish_slave: #if defined(__x86) ! /* clear traps, making all accrued flags visible in status word */ { unsigned long fsr; __fenv_getfsr(&fsr); __fenv_set_te(fsr, 0); __fenv_setfsr(&fsr); } #endif break; } } #if defined(__sparc) - /* ! * Code for setting or clearing interval mode on US-III and above. ! * This is embedded as data so we don't have to mark the library ! * as a v8plusb/v9b object. (I could have just used one entry and ! * modified the second word to set the bits I want, but that would ! * have required another mutex.) ! */ static const unsigned int siam[][2] = { { 0x81c3e008, 0x81b01020 }, /* retl, siam 0 */ { 0x81c3e008, 0x81b01024 }, /* retl, siam 4 */ { 0x81c3e008, 0x81b01025 }, /* retl, siam 5 */ { 0x81c3e008, 0x81b01026 }, /* retl, siam 6 */ { 0x81c3e008, 0x81b01027 } /* retl, siam 7 */ }; /* ! * If a handling mode is in effect, apply it; otherwise invoke the ! * saved handler ! */ static void __fex_hdlr(int sig, siginfo_t *sip, ucontext_t *uap) { struct fex_handler_data *thr_handlers; struct sigaction act; void (*handler)(), (*siamp)(); int mode, i; enum fex_exception e; fex_info_t info; unsigned long fsr, tmpfsr, addr; unsigned int gsr; --- 190,243 ---- #endif break; case __libm_mt_fex_finish_slave: #if defined(__x86) ! /* ! * clear traps, making all accrued flags visible in status ! * word ! */ { unsigned long fsr; + __fenv_getfsr(&fsr); __fenv_set_te(fsr, 0); __fenv_setfsr(&fsr); } #endif break; } } #if defined(__sparc) /* ! * Code for setting or clearing interval mode on US-III and above. ! * This is embedded as data so we don't have to mark the library ! * as a v8plusb/v9b object. (I could have just used one entry and ! * modified the second word to set the bits I want, but that would ! * have required another mutex.) ! */ static const unsigned int siam[][2] = { { 0x81c3e008, 0x81b01020 }, /* retl, siam 0 */ { 0x81c3e008, 0x81b01024 }, /* retl, siam 4 */ { 0x81c3e008, 0x81b01025 }, /* retl, siam 5 */ { 0x81c3e008, 0x81b01026 }, /* retl, siam 6 */ { 0x81c3e008, 0x81b01027 } /* retl, siam 7 */ }; /* ! * If a handling mode is in effect, apply it; otherwise invoke the ! * saved handler ! */ static void __fex_hdlr(int sig, siginfo_t *sip, ucontext_t *uap) { struct fex_handler_data *thr_handlers; struct sigaction act; + void (*handler)(), (*siamp)(); + int mode, i; enum fex_exception e; fex_info_t info; unsigned long fsr, tmpfsr, addr; unsigned int gsr;
*** 247,340 **** break; case FPE_FLTRES: e = fex_inexact; break; case FPE_FLTINV: if ((int)(e = __fex_get_invalid_type(sip, uap)) < 0) goto not_ieee; break; default: /* not an IEEE exception */ goto not_ieee; } /* get the handling mode */ mode = FEX_NOHANDLER; handler = oact.sa_handler; /* for log; just looking, no need to lock */ thr_handlers = __fex_get_thr_handlers(); if (thr_handlers && thr_handlers[(int)e].__mode != FEX_NOHANDLER) { mode = thr_handlers[(int)e].__mode; handler = thr_handlers[(int)e].__handler; } /* make an entry in the log of retro. diag. if need be */ i = ((int)uap->uc_mcontext.fpregs.fpu_fsr >> 5) & 0x1f; __fex_mklog(uap, (char *)sip->si_addr, i, e, mode, (void *)handler); /* handle the exception based on the mode */ ! if (mode == FEX_NOHANDLER) goto not_ieee; ! else if (mode == FEX_ABORT) abort(); ! else if (mode == FEX_SIGNAL) { handler(sig, sip, uap); return; } /* custom or nonstop mode; disable traps and clear flags */ __fenv_getfsr(&fsr); __fenv_set_te(fsr, 0); __fenv_set_ex(fsr, 0); ! /* if interval mode was set, clear it, then substitute the ! interval rounding direction and clear ns mode in the fsr */ #ifdef __sparcv9 gsr = uap->uc_mcontext.asrs[3]; #else gsr = 0; if (uap->uc_mcontext.xrs.xrs_id == XRS_ID) ! gsr = (*(unsigned long long*)((prxregset_t*)uap->uc_mcontext. ! xrs.xrs_ptr)->pr_un.pr_v8p.pr_filler); #endif gsr = (gsr >> 25) & 7; if (gsr & 4) { ! siamp = (void (*)()) siam[0]; siamp(); tmpfsr = fsr; fsr = (fsr & ~0xc0400000ul) | ((gsr & 3) << 30); } __fenv_setfsr(&fsr); /* decode the operation */ __fex_get_op(sip, uap, &info); /* if a custom mode handler is installed, invoke it */ if (mode == FEX_CUSTOM) { /* if we got here from feraiseexcept, pass dummy info */ addr = (unsigned long)sip->si_addr; ! if (addr >= (unsigned long)feraiseexcept && ! addr < (unsigned long)fetestexcept) { info.op = fex_other; info.op1.type = info.op2.type = info.res.type = fex_nodata; } ! /* restore interval mode if it was set, and put the original ! rounding direction and ns mode back in the fsr */ if (gsr & 4) { __fenv_setfsr(&tmpfsr); ! siamp = (void (*)()) siam[1 + (gsr & 3)]; siamp(); } handler(1 << (int)e, &info); /* restore modes in case the user's handler changed them */ if (gsr & 4) { ! siamp = (void (*)()) siam[0]; siamp(); } __fenv_setfsr(&fsr); } /* stuff the result */ __fex_st_result(sip, uap, &info); --- 255,361 ---- break; case FPE_FLTRES: e = fex_inexact; break; case FPE_FLTINV: + if ((int)(e = __fex_get_invalid_type(sip, uap)) < 0) goto not_ieee; + break; default: /* not an IEEE exception */ goto not_ieee; } /* get the handling mode */ mode = FEX_NOHANDLER; handler = oact.sa_handler; /* for log; just looking, no need to lock */ thr_handlers = __fex_get_thr_handlers(); + if (thr_handlers && thr_handlers[(int)e].__mode != FEX_NOHANDLER) { mode = thr_handlers[(int)e].__mode; handler = thr_handlers[(int)e].__handler; } /* make an entry in the log of retro. diag. if need be */ i = ((int)uap->uc_mcontext.fpregs.fpu_fsr >> 5) & 0x1f; __fex_mklog(uap, (char *)sip->si_addr, i, e, mode, (void *)handler); /* handle the exception based on the mode */ ! if (mode == FEX_NOHANDLER) { goto not_ieee; ! } else if (mode == FEX_ABORT) { abort(); ! } else if (mode == FEX_SIGNAL) { handler(sig, sip, uap); return; } /* custom or nonstop mode; disable traps and clear flags */ __fenv_getfsr(&fsr); __fenv_set_te(fsr, 0); __fenv_set_ex(fsr, 0); ! /* ! * if interval mode was set, clear it, then substitute the interval ! * rounding direction and clear ns mode in the fsr ! */ #ifdef __sparcv9 gsr = uap->uc_mcontext.asrs[3]; #else gsr = 0; + if (uap->uc_mcontext.xrs.xrs_id == XRS_ID) ! gsr = (*(unsigned long long *) ! ((prxregset_t *)uap->uc_mcontext.xrs.xrs_ptr)->pr_un. ! pr_v8p.pr_filler); #endif gsr = (gsr >> 25) & 7; + if (gsr & 4) { ! siamp = (void (*)())siam[0]; siamp(); tmpfsr = fsr; fsr = (fsr & ~0xc0400000ul) | ((gsr & 3) << 30); } + __fenv_setfsr(&fsr); /* decode the operation */ __fex_get_op(sip, uap, &info); /* if a custom mode handler is installed, invoke it */ if (mode == FEX_CUSTOM) { /* if we got here from feraiseexcept, pass dummy info */ addr = (unsigned long)sip->si_addr; ! ! if (addr >= (unsigned long)feraiseexcept && addr < (unsigned ! long)fetestexcept) { info.op = fex_other; info.op1.type = info.op2.type = info.res.type = fex_nodata; } ! /* ! * restore interval mode if it was set, and put the original ! * rounding direction and ns mode back in the fsr ! */ if (gsr & 4) { __fenv_setfsr(&tmpfsr); ! siamp = (void (*)())siam[1 + (gsr & 3)]; siamp(); } handler(1 << (int)e, &info); /* restore modes in case the user's handler changed them */ if (gsr & 4) { ! siamp = (void (*)())siam[0]; siamp(); } + __fenv_setfsr(&fsr); } /* stuff the result */ __fex_st_result(sip, uap, &info);
*** 350,359 **** --- 371,381 ---- not_ieee: /* revert to the saved handler (if any) */ mutex_lock(&hdlr_lock); act = oact; mutex_unlock(&hdlr_lock); + switch ((unsigned long)act.sa_handler) { case (unsigned long)SIG_DFL: /* simulate trap with no handler installed */ sigaction(SIGFPE, &act, NULL); kill(getpid(), SIGFPE);
*** 364,397 **** #endif default: act.sa_handler(sig, sip, uap); } } - #elif defined(__x86) - #if defined(__amd64) #define test_sse_hw 1 #else extern int _sse_hw; #define test_sse_hw _sse_hw #endif #if !defined(REG_PC) #define REG_PC EIP #endif /* ! * If a handling mode is in effect, apply it; otherwise invoke the ! * saved handler ! */ static void __fex_hdlr(int sig, siginfo_t *sip, ucontext_t *uap) { struct fex_handler_data *thr_handlers; struct sigaction act; void (*handler)() = NULL, (*simd_handler[4])(); int mode, simd_mode[4], i, len, accrued, *ap; unsigned int cwsw, oldcwsw, mxcsr, oldmxcsr; enum fex_exception e, simd_e[4]; fex_info_t info, simd_info[4]; unsigned long addr; --- 386,420 ---- #endif default: act.sa_handler(sig, sip, uap); } } #elif defined(__x86) #if defined(__amd64) #define test_sse_hw 1 #else extern int _sse_hw; + #define test_sse_hw _sse_hw #endif #if !defined(REG_PC) #define REG_PC EIP #endif /* ! * If a handling mode is in effect, apply it; otherwise invoke the ! * saved handler ! */ static void __fex_hdlr(int sig, siginfo_t *sip, ucontext_t *uap) { struct fex_handler_data *thr_handlers; struct sigaction act; + void (*handler)() = NULL, (*simd_handler[4])(); + int mode, simd_mode[4], i, len, accrued, *ap; unsigned int cwsw, oldcwsw, mxcsr, oldmxcsr; enum fex_exception e, simd_e[4]; fex_info_t info, simd_info[4]; unsigned long addr;
*** 399,408 **** --- 422,432 ---- sseinst_t inst; /* check for an exception caused by an SSE instruction */ if (!(uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.status & 0x80)) { len = __fex_parse_sse(uap, &inst); + if (len == 0) goto not_ieee; /* disable all traps and clear flags */ __fenv_getcwsw(&oldcwsw);
*** 415,468 **** if ((int)inst.op & SIMD) { __fex_get_simd_op(uap, &inst, simd_e, simd_info); thr_handlers = __fex_get_thr_handlers(); addr = (unsigned long)uap->uc_mcontext.gregs[REG_PC]; ! accrued = uap->uc_mcontext.fpregs.fp_reg_set. ! fpchip_state.mxcsr; e = (enum fex_exception)-1; mode = FEX_NONSTOP; for (i = 0; i < 4; i++) { if ((int)simd_e[i] < 0) continue; e = simd_e[i]; simd_mode[i] = FEX_NOHANDLER; simd_handler[i] = oact.sa_handler; if (thr_handlers && thr_handlers[(int)e].__mode != FEX_NOHANDLER) { simd_mode[i] = thr_handlers[(int)e].__mode; simd_handler[i] = thr_handlers[(int)e].__handler; } accrued &= ~te_bit[(int)e]; switch (simd_mode[i]) { case FEX_ABORT: mode = FEX_ABORT; break; case FEX_SIGNAL: if (mode != FEX_ABORT) mode = FEX_SIGNAL; handler = simd_handler[i]; break; case FEX_NOHANDLER: if (mode != FEX_ABORT && mode != FEX_SIGNAL) mode = FEX_NOHANDLER; break; } } if (e == (enum fex_exception)-1) { __fenv_setcwsw(&oldcwsw); __fenv_setmxcsr(&oldmxcsr); goto not_ieee; } ! accrued |= uap->uc_mcontext.fpregs.fp_reg_set. ! fpchip_state.status; ap = __fex_accrued(); accrued |= *ap; accrued &= 0x3d; for (i = 0; i < 4; i++) { --- 439,504 ---- if ((int)inst.op & SIMD) { __fex_get_simd_op(uap, &inst, simd_e, simd_info); thr_handlers = __fex_get_thr_handlers(); addr = (unsigned long)uap->uc_mcontext.gregs[REG_PC]; ! accrued = ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state. ! mxcsr; e = (enum fex_exception)-1; mode = FEX_NONSTOP; + for (i = 0; i < 4; i++) { if ((int)simd_e[i] < 0) continue; e = simd_e[i]; simd_mode[i] = FEX_NOHANDLER; simd_handler[i] = oact.sa_handler; + if (thr_handlers && thr_handlers[(int)e].__mode != FEX_NOHANDLER) { simd_mode[i] = thr_handlers[(int)e].__mode; simd_handler[i] = thr_handlers[(int)e].__handler; } + accrued &= ~te_bit[(int)e]; + switch (simd_mode[i]) { case FEX_ABORT: mode = FEX_ABORT; break; case FEX_SIGNAL: + if (mode != FEX_ABORT) mode = FEX_SIGNAL; + handler = simd_handler[i]; break; case FEX_NOHANDLER: + if (mode != FEX_ABORT && mode != FEX_SIGNAL) mode = FEX_NOHANDLER; + break; } } + if (e == (enum fex_exception)-1) { __fenv_setcwsw(&oldcwsw); __fenv_setmxcsr(&oldmxcsr); goto not_ieee; } ! ! accrued |= ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state. ! status; ap = __fex_accrued(); accrued |= *ap; accrued &= 0x3d; for (i = 0; i < 4; i++) {
*** 486,495 **** --- 522,532 ---- handler(sig, &osip, uap); return; } *ap = 0; + for (i = 0; i < 4; i++) { if ((int)simd_e[i] < 0) continue; if (simd_mode[i] == FEX_CUSTOM) {
*** 499,551 **** __fenv_setmxcsr(&mxcsr); } } __fex_st_simd_result(uap, &inst, simd_e, simd_info); for (i = 0; i < 4; i++) { if ((int)simd_e[i] < 0) continue; accrued |= simd_info[i].flags; } if ((int)inst.op & INTREG) { /* set MMX mode */ #if defined(__amd64) ! uap->uc_mcontext.fpregs.fp_reg_set. ! fpchip_state.sw &= ~0x3800; ! uap->uc_mcontext.fpregs.fp_reg_set. ! fpchip_state.fctw = 0; #else ! uap->uc_mcontext.fpregs.fp_reg_set. ! fpchip_state.state[1] &= ~0x3800; ! uap->uc_mcontext.fpregs.fp_reg_set. ! fpchip_state.state[2] = 0; #endif } } else { e = __fex_get_sse_op(uap, &inst, &info); if ((int)e < 0) { __fenv_setcwsw(&oldcwsw); __fenv_setmxcsr(&oldmxcsr); goto not_ieee; } mode = FEX_NOHANDLER; handler = oact.sa_handler; thr_handlers = __fex_get_thr_handlers(); if (thr_handlers && thr_handlers[(int)e].__mode != FEX_NOHANDLER) { mode = thr_handlers[(int)e].__mode; handler = thr_handlers[(int)e].__handler; } addr = (unsigned long)uap->uc_mcontext.gregs[REG_PC]; ! accrued = uap->uc_mcontext.fpregs.fp_reg_set. ! fpchip_state.mxcsr & ~te_bit[(int)e]; ! accrued |= uap->uc_mcontext.fpregs.fp_reg_set. ! fpchip_state.status; ap = __fex_accrued(); accrued |= *ap; accrued &= 0x3d; __fex_mklog(uap, (char *)addr, accrued, e, mode, (void *)handler); --- 536,593 ---- __fenv_setmxcsr(&mxcsr); } } __fex_st_simd_result(uap, &inst, simd_e, simd_info); + for (i = 0; i < 4; i++) { if ((int)simd_e[i] < 0) continue; accrued |= simd_info[i].flags; } if ((int)inst.op & INTREG) { /* set MMX mode */ #if defined(__amd64) ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state. ! sw &= ~0x3800; ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state. ! fctw = 0; #else ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state. ! state[1] &= ~0x3800; ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state. ! state[2] = 0; #endif } } else { e = __fex_get_sse_op(uap, &inst, &info); + if ((int)e < 0) { __fenv_setcwsw(&oldcwsw); __fenv_setmxcsr(&oldmxcsr); goto not_ieee; } mode = FEX_NOHANDLER; handler = oact.sa_handler; thr_handlers = __fex_get_thr_handlers(); + if (thr_handlers && thr_handlers[(int)e].__mode != FEX_NOHANDLER) { mode = thr_handlers[(int)e].__mode; handler = thr_handlers[(int)e].__handler; } addr = (unsigned long)uap->uc_mcontext.gregs[REG_PC]; ! accrued = ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state. ! mxcsr & ~te_bit[(int)e]; ! accrued |= ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state. ! status; ap = __fex_accrued(); accrued |= *ap; accrued &= 0x3d; __fex_mklog(uap, (char *)addr, accrued, e, mode, (void *)handler);
*** 561,576 **** --- 603,620 ---- __fenv_setmxcsr(&oldmxcsr); handler(sig, &osip, uap); return; } else if (mode == FEX_CUSTOM) { *ap = 0; + if (addr >= (unsigned long)feraiseexcept && addr < (unsigned long)fetestexcept) { info.op = fex_other; info.op1.type = info.op2.type = info.res.type = fex_nodata; } + handler(1 << (int)e, &info); __fenv_setcwsw(&cwsw); __fenv_setmxcsr(&mxcsr); }
*** 596,605 **** --- 640,650 ---- goto update_state; } /* determine which exception occurred */ __fex_get_x86_exc(sip, uap); + switch (sip->si_code) { case FPE_FLTDIV: e = fex_division; break; case FPE_FLTOVF:
*** 610,692 **** break; case FPE_FLTRES: e = fex_inexact; break; case FPE_FLTINV: if ((int)(e = __fex_get_invalid_type(sip, uap)) < 0) goto not_ieee; break; default: /* not an IEEE exception */ goto not_ieee; } /* get the handling mode */ mode = FEX_NOHANDLER; handler = oact.sa_handler; /* for log; just looking, no need to lock */ thr_handlers = __fex_get_thr_handlers(); if (thr_handlers && thr_handlers[(int)e].__mode != FEX_NOHANDLER) { mode = thr_handlers[(int)e].__mode; handler = thr_handlers[(int)e].__handler; } /* make an entry in the log of retro. diag. if need be */ #if defined(__amd64) ! addr = (unsigned long)uap->uc_mcontext.fpregs.fp_reg_set. ! fpchip_state.rip; #else ! addr = (unsigned long)uap->uc_mcontext.fpregs.fp_reg_set. ! fpchip_state.state[3]; #endif accrued = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.status & ~te_bit[(int)e]; if (test_sse_hw) ! accrued |= uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state. ! mxcsr; ap = __fex_accrued(); accrued |= *ap; accrued &= 0x3d; __fex_mklog(uap, (char *)addr, accrued, e, mode, (void *)handler); /* handle the exception based on the mode */ ! if (mode == FEX_NOHANDLER) goto not_ieee; ! else if (mode == FEX_ABORT) abort(); ! else if (mode == FEX_SIGNAL) { handler(sig, &osip, uap); return; } /* disable all traps and clear flags */ __fenv_getcwsw(&cwsw); cwsw = (cwsw & ~0x3f) | 0x003f0000; __fenv_setcwsw(&cwsw); if (test_sse_hw) { __fenv_getmxcsr(&mxcsr); mxcsr = (mxcsr & ~0x3f) | 0x1f80; __fenv_setmxcsr(&mxcsr); } *ap = 0; /* decode the operation */ __fex_get_op(sip, uap, &info); /* if a custom mode handler is installed, invoke it */ if (mode == FEX_CUSTOM) { /* if we got here from feraiseexcept, pass dummy info */ ! if (addr >= (unsigned long)feraiseexcept && ! addr < (unsigned long)fetestexcept) { info.op = fex_other; info.op1.type = info.op2.type = info.res.type = fex_nodata; } handler(1 << (int)e, &info); /* restore modes in case the user's handler changed them */ __fenv_setcwsw(&cwsw); if (test_sse_hw) __fenv_setmxcsr(&mxcsr); } /* stuff the result */ --- 655,745 ---- break; case FPE_FLTRES: e = fex_inexact; break; case FPE_FLTINV: + if ((int)(e = __fex_get_invalid_type(sip, uap)) < 0) goto not_ieee; + break; default: /* not an IEEE exception */ goto not_ieee; } /* get the handling mode */ mode = FEX_NOHANDLER; handler = oact.sa_handler; /* for log; just looking, no need to lock */ thr_handlers = __fex_get_thr_handlers(); + if (thr_handlers && thr_handlers[(int)e].__mode != FEX_NOHANDLER) { mode = thr_handlers[(int)e].__mode; handler = thr_handlers[(int)e].__handler; } /* make an entry in the log of retro. diag. if need be */ #if defined(__amd64) ! addr = (unsigned ! long)uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.rip; #else ! addr = (unsigned ! long)uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[3]; #endif accrued = uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.status & ~te_bit[(int)e]; + if (test_sse_hw) ! accrued |= ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr; ! ap = __fex_accrued(); accrued |= *ap; accrued &= 0x3d; __fex_mklog(uap, (char *)addr, accrued, e, mode, (void *)handler); /* handle the exception based on the mode */ ! if (mode == FEX_NOHANDLER) { goto not_ieee; ! } else if (mode == FEX_ABORT) { abort(); ! } else if (mode == FEX_SIGNAL) { handler(sig, &osip, uap); return; } /* disable all traps and clear flags */ __fenv_getcwsw(&cwsw); cwsw = (cwsw & ~0x3f) | 0x003f0000; __fenv_setcwsw(&cwsw); + if (test_sse_hw) { __fenv_getmxcsr(&mxcsr); mxcsr = (mxcsr & ~0x3f) | 0x1f80; __fenv_setmxcsr(&mxcsr); } + *ap = 0; /* decode the operation */ __fex_get_op(sip, uap, &info); /* if a custom mode handler is installed, invoke it */ if (mode == FEX_CUSTOM) { /* if we got here from feraiseexcept, pass dummy info */ ! if (addr >= (unsigned long)feraiseexcept && addr < (unsigned ! long)fetestexcept) { info.op = fex_other; info.op1.type = info.op2.type = info.res.type = fex_nodata; } handler(1 << (int)e, &info); /* restore modes in case the user's handler changed them */ __fenv_setcwsw(&cwsw); + if (test_sse_hw) __fenv_setmxcsr(&mxcsr); } /* stuff the result */
*** 702,730 **** uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |= (accrued & ~i); uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.cw |= 0x3d; uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.cw &= ~i; #else uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[1] &= ~0x3d; ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[1] |= ! (accrued & ~i); uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[0] |= 0x3d; uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[0] &= ~i; #endif if (test_sse_hw) { uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr &= ~0x3d; uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr |= 0x1e80 | (accrued & ~i); ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr &= ! ~(i << 7); } return; not_ieee: /* revert to the saved handler (if any) */ mutex_lock(&hdlr_lock); act = oact; mutex_unlock(&hdlr_lock); switch ((unsigned long)act.sa_handler) { case (unsigned long)SIG_DFL: /* simulate trap with no handler installed */ sigaction(SIGFPE, &act, NULL); kill(getpid(), SIGFPE); --- 755,786 ---- uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.sw |= (accrued & ~i); uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.cw |= 0x3d; uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.cw &= ~i; #else uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[1] &= ~0x3d; ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[1] |= (accrued & ! ~i); uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[0] |= 0x3d; uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.state[0] &= ~i; #endif + if (test_sse_hw) { uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr &= ~0x3d; uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr |= 0x1e80 | (accrued & ~i); ! uap->uc_mcontext.fpregs.fp_reg_set.fpchip_state.mxcsr &= ~(i << ! 7); } + return; not_ieee: /* revert to the saved handler (if any) */ mutex_lock(&hdlr_lock); act = oact; mutex_unlock(&hdlr_lock); + switch ((unsigned long)act.sa_handler) { case (unsigned long)SIG_DFL: /* simulate trap with no handler installed */ sigaction(SIGFPE, &act, NULL); kill(getpid(), SIGFPE);
*** 735,805 **** #endif default: act.sa_handler(sig, &osip, uap); } } - #else #error Unknown architecture #endif /* ! * Return a pointer to the thread-specific handler data, and ! * initialize it if necessary ! */ struct fex_handler_data * __fex_get_thr_handlers() { struct fex_handler_data *ptr; unsigned long fsr; int i, te; if (thr_main()) { if (!handlers_initialized) { ! /* initialize to FEX_NOHANDLER if trap is enabled, ! FEX_NONSTOP if trap is disabled */ __fenv_getfsr(&fsr); te = (int)__fenv_get_te(fsr); for (i = 0; i < FEX_NUM_EXC; i++) ! main_handlers[i].__mode = ! ((te & te_bit[i])? FEX_NOHANDLER : FEX_NONSTOP); handlers_initialized = 1; } ! return main_handlers; ! } ! else { ptr = NULL; mutex_lock(&handlers_key_lock); if (thr_getspecific(handlers_key, (void **)&ptr) != 0 && thr_keycreate(&handlers_key, free) != 0) { mutex_unlock(&handlers_key_lock); ! return NULL; } mutex_unlock(&handlers_key_lock); if (!ptr) { ! if ((ptr = (struct fex_handler_data *) ! malloc(sizeof(fex_handler_t))) == NULL) { ! return NULL; ! } if (thr_setspecific(handlers_key, (void *)ptr) != 0) { ! (void)free(ptr); ! return NULL; } ! /* initialize to FEX_NOHANDLER if trap is enabled, ! FEX_NONSTOP if trap is disabled */ __fenv_getfsr(&fsr); te = (int)__fenv_get_te(fsr); for (i = 0; i < FEX_NUM_EXC; i++) ! ptr[i].__mode = ((te & te_bit[i])? FEX_NOHANDLER : FEX_NONSTOP); } ! return ptr; } } /* ! * Update the trap enable bits according to the selected modes ! */ void __fex_update_te() { struct fex_handler_data *thr_handlers; struct sigaction act, tmpact; --- 791,872 ---- #endif default: act.sa_handler(sig, &osip, uap); } } #else #error Unknown architecture #endif /* ! * Return a pointer to the thread-specific handler data, and ! * initialize it if necessary ! */ struct fex_handler_data * __fex_get_thr_handlers() { struct fex_handler_data *ptr; unsigned long fsr; int i, te; if (thr_main()) { if (!handlers_initialized) { ! /* ! * initialize to FEX_NOHANDLER if trap is enabled, ! * FEX_NONSTOP if trap is disabled ! */ __fenv_getfsr(&fsr); te = (int)__fenv_get_te(fsr); + for (i = 0; i < FEX_NUM_EXC; i++) ! main_handlers[i].__mode = ((te & te_bit[i]) ? ! FEX_NOHANDLER : FEX_NONSTOP); ! handlers_initialized = 1; } ! ! return (main_handlers); ! } else { ptr = NULL; mutex_lock(&handlers_key_lock); + if (thr_getspecific(handlers_key, (void **)&ptr) != 0 && thr_keycreate(&handlers_key, free) != 0) { mutex_unlock(&handlers_key_lock); ! return (NULL); } + mutex_unlock(&handlers_key_lock); + if (!ptr) { ! if ((ptr = malloc(sizeof (fex_handler_t))) == NULL) ! return (NULL); ! if (thr_setspecific(handlers_key, (void *)ptr) != 0) { ! (void) free(ptr); ! return (NULL); } ! ! /* ! * initialize to FEX_NOHANDLER if trap is enabled, ! * FEX_NONSTOP if trap is disabled ! */ __fenv_getfsr(&fsr); te = (int)__fenv_get_te(fsr); + for (i = 0; i < FEX_NUM_EXC; i++) ! ptr[i].__mode = ((te & te_bit[i]) ? ! FEX_NOHANDLER : FEX_NONSTOP); } ! ! return (ptr); } } /* ! * Update the trap enable bits according to the selected modes ! */ void __fex_update_te() { struct fex_handler_data *thr_handlers; struct sigaction act, tmpact;
*** 816,837 **** if (!hdlr_installed && te) { act.sa_handler = __fex_hdlr; sigemptyset(&act.sa_mask); act.sa_flags = SA_SIGINFO; sigaction(SIGFPE, &act, &tmpact); ! if (tmpact.sa_handler != __fex_hdlr) ! { mutex_lock(&hdlr_lock); oact = tmpact; mutex_unlock(&hdlr_lock); } hdlr_installed = 1; } /* set the new trap enable bits (only if SIGFPE is not blocked) */ ! if (sigprocmask(0, NULL, &blocked) == 0 && ! !sigismember(&blocked, SIGFPE)) { __fenv_set_te(fsr, te); __fenv_setfsr(&fsr); } /* synchronize with libmtsk */ --- 883,905 ---- if (!hdlr_installed && te) { act.sa_handler = __fex_hdlr; sigemptyset(&act.sa_mask); act.sa_flags = SA_SIGINFO; sigaction(SIGFPE, &act, &tmpact); ! ! if (tmpact.sa_handler != __fex_hdlr) { mutex_lock(&hdlr_lock); oact = tmpact; mutex_unlock(&hdlr_lock); } + hdlr_installed = 1; } /* set the new trap enable bits (only if SIGFPE is not blocked) */ ! if (sigprocmask(0, NULL, &blocked) == 0 && !sigismember(&blocked, ! SIGFPE)) { __fenv_set_te(fsr, te); __fenv_setfsr(&fsr); } /* synchronize with libmtsk */