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. */
*** 54,101 **** #endif static FILE *log_fp = NULL; static mutex_t log_lock = DEFAULTMUTEX; static int log_depth = 100; ! ! FILE *fex_get_log(void) { FILE *fp; mutex_lock(&log_lock); fp = log_fp; mutex_unlock(&log_lock); ! return fp; } ! int fex_set_log(FILE *fp) { mutex_lock(&log_lock); log_fp = fp; mutex_unlock(&log_lock); __fex_update_te(); ! return 1; } ! int fex_get_log_depth(void) { int d; mutex_lock(&log_lock); d = log_depth; mutex_unlock(&log_lock); ! return d; } ! int fex_set_log_depth(int d) { if (d < 0) ! return 0; mutex_lock(&log_lock); log_depth = d; mutex_unlock(&log_lock); ! return 1; } static struct exc_list { struct exc_list *next; char *addr; --- 55,106 ---- #endif static FILE *log_fp = NULL; static mutex_t log_lock = DEFAULTMUTEX; static int log_depth = 100; ! FILE * ! fex_get_log(void) { FILE *fp; mutex_lock(&log_lock); fp = log_fp; mutex_unlock(&log_lock); ! return (fp); } ! int ! fex_set_log(FILE *fp) { mutex_lock(&log_lock); log_fp = fp; mutex_unlock(&log_lock); __fex_update_te(); ! return (1); } ! int ! fex_get_log_depth(void) { int d; mutex_lock(&log_lock); d = log_depth; mutex_unlock(&log_lock); ! return (d); } ! int ! fex_set_log_depth(int d) { if (d < 0) ! return (0); ! mutex_lock(&log_lock); log_depth = d; mutex_unlock(&log_lock); ! return (1); } static struct exc_list { struct exc_list *next; char *addr;
*** 103,253 **** int nstack; char *stack[1]; /* actual length is max(1,nstack) */ } *list = NULL; #ifdef __sparcv9 ! #define FRAMEP(X) (struct frame *)((char*)(X)+(((long)(X)&1)?2047:0)) #else #define FRAMEP(X) (struct frame *)(X) #endif #ifdef _LP64 #define PDIG "16" #else #define PDIG "8" #endif ! /* look for a matching exc_list; return 1 if one is found, ! otherwise add this one to the list and return 0 */ ! static int check_exc_list(char *addr, unsigned long code, char *stk, ! struct frame *fp) { struct exc_list *l, *ll = NULL; struct frame *f; int i, n; if (list) { for (l = list; l; ll = l, l = l->next) { if (l->addr != addr || l->code != code) continue; if (log_depth < 1 || l->nstack < 1) ! return 1; if (l->stack[0] != stk) continue; n = 1; for (i = 1, f = fp; i < log_depth && i < l->nstack && f && f->fr_savpc; i++, f = FRAMEP(f->fr_savfp)) if (l->stack[i] != (char *)f->fr_savpc) { n = 0; break; } if (n) ! return 1; } } /* create a new exc_list structure and tack it on the list */ for (n = 1, f = fp; n < log_depth && f && f->fr_savpc; ! n++, f = FRAMEP(f->fr_savfp)) ; ! if ((l = (struct exc_list *)malloc(sizeof(struct exc_list) + ! (n - 1) * sizeof(char *))) != NULL) { l->next = NULL; l->addr = addr; l->code = code; ! l->nstack = ((log_depth < 1)? 0 : n); l->stack[0] = stk; for (i = 1; i < n; i++) { l->stack[i] = (char *)fp->fr_savpc; fp = FRAMEP(fp->fr_savfp); } if (list) ll->next = l; else list = l; } ! return 0; } /* ! * Warning: cleverness ahead ! * ! * In the following code, the use of sprintf+write rather than fprintf ! * to send output to the log file is intentional. The reason is that ! * fprintf is not async-signal-safe. "But," you protest, "SIGFPE is ! * not an asynchronous signal! It's always handled by the same thread ! * that executed the fpop that provoked it." That's true, but a prob- ! * lem arises because (i) base conversion in fprintf can cause a fp ! * exception and (ii) my signal handler acquires a mutex lock before ! * sending output to the log file (so that outputs for entries from ! * different threads aren't interspersed). Therefore, if the code ! * were to use fprintf, a deadlock could occur as follows: ! * ! * Thread A Thread B ! * ! * Incurs a fp exception, Calls fprintf, ! * acquires log_lock acquires file rmutex lock ! * ! * Calls fprintf, Incurs a fp exception, ! * waits for file rmutex lock waits for log_lock ! * ! * (I could just verify that fprintf doesn't hold the rmutex lock while ! * it's doing the base conversion, but since efficiency is of little ! * concern here, I opted for the safe and dumb route.) ! */ ! ! static void print_stack(int fd, char *addr, struct frame *fp) { int i; char *name, buf[30]; for (i = 0; i < log_depth && addr != NULL; i++) { if (__fex_sym(addr, &name) != NULL) { write(fd, buf, sprintf(buf, " 0x%0" PDIG "lx ", (long)addr)); write(fd, name, strlen(name)); write(fd, "\n", 1); ! if (!strcmp(name, "main")) break; } else { write(fd, buf, sprintf(buf, " 0x%0" PDIG "lx\n", (long)addr)); } if (fp == NULL) break; addr = (char *)fp->fr_savpc; fp = FRAMEP(fp->fr_savfp); } } ! void fex_log_entry(const char *msg) { ucontext_t uc; struct frame *fp; char *stk; int fd; /* if logging is disabled, just return */ mutex_lock(&log_lock); if (log_fp == NULL) { mutex_unlock(&log_lock); return; } ! /* get the frame pointer from the current context and ! pop our own frame */ getcontext(&uc); #if defined(__sparc) || defined(__amd64) fp = FRAMEP(uc.uc_mcontext.gregs[REG_SP]); #elif defined(__i386) /* !defined(__amd64) */ fp = FRAMEP(uc.uc_mcontext.gregs[EBP]); #else #error Unknown architecture #endif if (fp == NULL) { mutex_unlock(&log_lock); return; } stk = (char *)fp->fr_savpc; fp = FRAMEP(fp->fr_savfp); /* if we've already logged this message here, don't make an entry */ if (check_exc_list(stk, (unsigned long)msg, stk, fp)) { --- 108,280 ---- int nstack; char *stack[1]; /* actual length is max(1,nstack) */ } *list = NULL; #ifdef __sparcv9 ! #define FRAMEP(X) (struct frame *)((char *)(X) + (((long)(X) & \ ! 1) ? 2047 : 0)) #else #define FRAMEP(X) (struct frame *)(X) #endif #ifdef _LP64 #define PDIG "16" #else #define PDIG "8" #endif ! /* ! * look for a matching exc_list; return 1 if one is found, ! * otherwise add this one to the list and return 0 ! */ ! static int ! check_exc_list(char *addr, unsigned long code, char *stk, struct frame *fp) { struct exc_list *l, *ll = NULL; struct frame *f; int i, n; if (list) { for (l = list; l; ll = l, l = l->next) { if (l->addr != addr || l->code != code) continue; + if (log_depth < 1 || l->nstack < 1) ! return (1); ! if (l->stack[0] != stk) continue; + n = 1; + for (i = 1, f = fp; i < log_depth && i < l->nstack && f && f->fr_savpc; i++, f = FRAMEP(f->fr_savfp)) if (l->stack[i] != (char *)f->fr_savpc) { n = 0; break; } + if (n) ! return (1); } } /* create a new exc_list structure and tack it on the list */ for (n = 1, f = fp; n < log_depth && f && f->fr_savpc; ! n++, f = FRAMEP(f->fr_savfp)) ! ; ! ! if ((l = (struct exc_list *)malloc(sizeof (struct exc_list) + (n - 1) * ! sizeof (char *))) != NULL) { l->next = NULL; l->addr = addr; l->code = code; ! l->nstack = ((log_depth < 1) ? 0 : n); l->stack[0] = stk; + for (i = 1; i < n; i++) { l->stack[i] = (char *)fp->fr_savpc; fp = FRAMEP(fp->fr_savfp); } + if (list) ll->next = l; else list = l; } ! ! return (0); } /* ! * Warning: cleverness ahead ! * ! * In the following code, the use of sprintf+write rather than fprintf ! * to send output to the log file is intentional. The reason is that ! * fprintf is not async-signal-safe. "But," you protest, "SIGFPE is ! * not an asynchronous signal! It's always handled by the same thread ! * that executed the fpop that provoked it." That's true, but a prob- ! * lem arises because (i) base conversion in fprintf can cause a fp ! * exception and (ii) my signal handler acquires a mutex lock before ! * sending output to the log file (so that outputs for entries from ! * different threads aren't interspersed). Therefore, if the code ! * were to use fprintf, a deadlock could occur as follows: ! * ! * Thread A Thread B ! * ! * Incurs a fp exception, Calls fprintf, ! * acquires log_lock acquires file rmutex lock ! * ! * Calls fprintf, Incurs a fp exception, ! * waits for file rmutex lock waits for log_lock ! * ! * (I could just verify that fprintf doesn't hold the rmutex lock while ! * it's doing the base conversion, but since efficiency is of little ! * concern here, I opted for the safe and dumb route.) ! */ ! static void ! print_stack(int fd, char *addr, struct frame *fp) { int i; char *name, buf[30]; for (i = 0; i < log_depth && addr != NULL; i++) { if (__fex_sym(addr, &name) != NULL) { write(fd, buf, sprintf(buf, " 0x%0" PDIG "lx ", (long)addr)); write(fd, name, strlen(name)); write(fd, "\n", 1); ! ! if (strcmp(name, "main") == 0) break; } else { write(fd, buf, sprintf(buf, " 0x%0" PDIG "lx\n", (long)addr)); } + if (fp == NULL) break; + addr = (char *)fp->fr_savpc; fp = FRAMEP(fp->fr_savfp); } } ! void ! fex_log_entry(const char *msg) { ucontext_t uc; struct frame *fp; char *stk; int fd; /* if logging is disabled, just return */ mutex_lock(&log_lock); + if (log_fp == NULL) { mutex_unlock(&log_lock); return; } ! /* ! * get the frame pointer from the current context and ! * pop our own frame ! */ getcontext(&uc); #if defined(__sparc) || defined(__amd64) fp = FRAMEP(uc.uc_mcontext.gregs[REG_SP]); #elif defined(__i386) /* !defined(__amd64) */ fp = FRAMEP(uc.uc_mcontext.gregs[EBP]); #else #error Unknown architecture #endif + if (fp == NULL) { mutex_unlock(&log_lock); return; } + stk = (char *)fp->fr_savpc; fp = FRAMEP(fp->fr_savfp); /* if we've already logged this message here, don't make an entry */ if (check_exc_list(stk, (unsigned long)msg, stk, fp)) {
*** 264,355 **** print_stack(fd, stk, fp); mutex_unlock(&log_lock); } static const char *exception[FEX_NUM_EXC] = { ! "inexact result", ! "division by zero", ! "underflow", ! "overflow", ! "invalid operation (0/0)", ! "invalid operation (inf/inf)", ! "invalid operation (inf-inf)", ! "invalid operation (0*inf)", ! "invalid operation (sqrt)", ! "invalid operation (snan)", ! "invalid operation (int)", ! "invalid operation (cmp)" }; void ! __fex_mklog(ucontext_t *uap, char *addr, int f, enum fex_exception e, ! int m, void *p) { struct frame *fp; char *stk, *name, buf[30]; int fd; /* if logging is disabled, just return */ mutex_lock(&log_lock); if (log_fp == NULL) { mutex_unlock(&log_lock); return; } /* get stack info */ #if defined(__sparc) ! stk = (char*)uap->uc_mcontext.gregs[REG_PC]; fp = FRAMEP(uap->uc_mcontext.gregs[REG_SP]); #elif defined(__amd64) ! stk = (char*)uap->uc_mcontext.gregs[REG_PC]; fp = FRAMEP(uap->uc_mcontext.gregs[REG_RBP]); #elif defined(__i386) /* !defined(__amd64) */ ! stk = (char*)uap->uc_mcontext.gregs[PC]; fp = FRAMEP(uap->uc_mcontext.gregs[EBP]); #else #error Unknown architecture #endif ! /* if the handling mode is the default and this exception's ! flag is already raised, don't make an entry */ if (m == FEX_NONSTOP) { switch (e) { case fex_inexact: if (f & FE_INEXACT) { mutex_unlock(&log_lock); return; } break; case fex_underflow: if (f & FE_UNDERFLOW) { mutex_unlock(&log_lock); return; } break; case fex_overflow: if (f & FE_OVERFLOW) { mutex_unlock(&log_lock); return; } break; case fex_division: if (f & FE_DIVBYZERO) { mutex_unlock(&log_lock); return; } break; default: if (f & FE_INVALID) { mutex_unlock(&log_lock); return; } break; } } ! /* if we've already logged this exception at this address, ! don't make an entry */ if (check_exc_list(addr, (unsigned long)e, stk, fp)) { mutex_unlock(&log_lock); return; } --- 291,390 ---- print_stack(fd, stk, fp); mutex_unlock(&log_lock); } static const char *exception[FEX_NUM_EXC] = { ! "inexact result", "division by zero", "underflow", "overflow", ! "invalid operation (0/0)", "invalid operation (inf/inf)", ! "invalid operation (inf-inf)", "invalid operation (0*inf)", ! "invalid operation (sqrt)", "invalid operation (snan)", ! "invalid operation (int)", "invalid operation (cmp)" }; void ! __fex_mklog(ucontext_t *uap, char *addr, int f, enum fex_exception e, int m, ! void *p) { struct frame *fp; char *stk, *name, buf[30]; int fd; /* if logging is disabled, just return */ mutex_lock(&log_lock); + if (log_fp == NULL) { mutex_unlock(&log_lock); return; } /* get stack info */ #if defined(__sparc) ! stk = (char *)uap->uc_mcontext.gregs[REG_PC]; fp = FRAMEP(uap->uc_mcontext.gregs[REG_SP]); #elif defined(__amd64) ! stk = (char *)uap->uc_mcontext.gregs[REG_PC]; fp = FRAMEP(uap->uc_mcontext.gregs[REG_RBP]); #elif defined(__i386) /* !defined(__amd64) */ ! stk = (char *)uap->uc_mcontext.gregs[PC]; fp = FRAMEP(uap->uc_mcontext.gregs[EBP]); #else #error Unknown architecture #endif ! /* ! * if the handling mode is the default and this exception's ! * flag is already raised, don't make an entry ! */ if (m == FEX_NONSTOP) { switch (e) { case fex_inexact: + if (f & FE_INEXACT) { mutex_unlock(&log_lock); return; } + break; case fex_underflow: + if (f & FE_UNDERFLOW) { mutex_unlock(&log_lock); return; } + break; case fex_overflow: + if (f & FE_OVERFLOW) { mutex_unlock(&log_lock); return; } + break; case fex_division: + if (f & FE_DIVBYZERO) { mutex_unlock(&log_lock); return; } + break; default: + if (f & FE_INVALID) { mutex_unlock(&log_lock); return; } + break; } } ! /* ! * if we've already logged this exception at this address, ! * don't make an entry ! */ if (check_exc_list(addr, (unsigned long)e, stk, fp)) { mutex_unlock(&log_lock); return; }
*** 357,398 **** fd = fileno(log_fp); write(fd, "Floating point ", 15); write(fd, exception[e], strlen(exception[e])); write(fd, buf, sprintf(buf, " at 0x%0" PDIG "lx", (long)addr)); __fex_sym_init(); if (__fex_sym(addr, &name) != NULL) { write(fd, " ", 1); write(fd, name, strlen(name)); } switch (m) { case FEX_NONSTOP: write(fd, ", nonstop mode\n", 15); break; case FEX_ABORT: write(fd, ", abort\n", 8); break; case FEX_NOHANDLER: if (p == (void *)SIG_DFL) { write(fd, ", handler: SIG_DFL\n", 19); break; ! } ! else if (p == (void *)SIG_IGN) { write(fd, ", handler: SIG_IGN\n", 19); break; } ! /* fall through*/ default: write(fd, ", handler: ", 11); if (__fex_sym((char *)p, &name) != NULL) { write(fd, name, strlen(name)); write(fd, "\n", 1); } else { write(fd, buf, sprintf(buf, "0x%0" PDIG "lx\n", (long)p)); } break; } print_stack(fd, stk, fp); mutex_unlock(&log_lock); } --- 392,439 ---- fd = fileno(log_fp); write(fd, "Floating point ", 15); write(fd, exception[e], strlen(exception[e])); write(fd, buf, sprintf(buf, " at 0x%0" PDIG "lx", (long)addr)); __fex_sym_init(); + if (__fex_sym(addr, &name) != NULL) { write(fd, " ", 1); write(fd, name, strlen(name)); } + switch (m) { case FEX_NONSTOP: write(fd, ", nonstop mode\n", 15); break; case FEX_ABORT: write(fd, ", abort\n", 8); break; case FEX_NOHANDLER: + if (p == (void *)SIG_DFL) { write(fd, ", handler: SIG_DFL\n", 19); break; ! } else if (p == (void *)SIG_IGN) { write(fd, ", handler: SIG_IGN\n", 19); break; } ! ! /* FALLTHROUGH */ default: write(fd, ", handler: ", 11); + if (__fex_sym((char *)p, &name) != NULL) { write(fd, name, strlen(name)); write(fd, "\n", 1); } else { write(fd, buf, sprintf(buf, "0x%0" PDIG "lx\n", (long)p)); } + break; } + print_stack(fd, stk, fp); mutex_unlock(&log_lock); }