Print this page
5261 libm should stop using synonyms.h
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libm/common/m9x/fex_log.c
+++ new/usr/src/lib/libm/common/m9x/fex_log.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 -#pragma weak fex_get_log = __fex_get_log
31 -#pragma weak fex_set_log = __fex_set_log
32 -#pragma weak fex_get_log_depth = __fex_get_log_depth
33 -#pragma weak fex_set_log_depth = __fex_set_log_depth
34 -#pragma weak fex_log_entry = __fex_log_entry
30 +#pragma weak __fex_get_log = fex_get_log
31 +#pragma weak __fex_set_log = fex_set_log
32 +#pragma weak __fex_get_log_depth = fex_get_log_depth
33 +#pragma weak __fex_set_log_depth = fex_set_log_depth
34 +#pragma weak __fex_log_entry = fex_log_entry
35 35
36 -#include "fenv_synonyms.h"
37 36 #include <stdio.h>
38 37 #include <stdlib.h>
39 38 #include <unistd.h>
40 39 #include <string.h>
41 40 #include <signal.h>
42 41 #include <ucontext.h>
43 42 #include <sys/frame.h>
44 43 #include <fenv.h>
45 44 #include <sys/ieeefp.h>
46 45 #include <thread.h>
47 46 #include "fex_handler.h"
48 47
49 48 #if !defined(PC)
50 49 #if defined(REG_PC)
51 50 #define PC REG_PC
52 51 #else
53 52 #error Neither PC nor REG_PC is defined!
54 53 #endif
55 54 #endif
56 55
57 56 static FILE *log_fp = NULL;
58 57 static mutex_t log_lock = DEFAULTMUTEX;
59 58 static int log_depth = 100;
60 59
61 60 FILE *fex_get_log(void)
62 61 {
63 62 FILE *fp;
64 63
65 64 mutex_lock(&log_lock);
66 65 fp = log_fp;
67 66 mutex_unlock(&log_lock);
68 67 return fp;
69 68 }
70 69
71 70 int fex_set_log(FILE *fp)
72 71 {
73 72 mutex_lock(&log_lock);
74 73 log_fp = fp;
75 74 mutex_unlock(&log_lock);
76 75 __fex_update_te();
77 76 return 1;
78 77 }
79 78
80 79 int fex_get_log_depth(void)
81 80 {
82 81 int d;
83 82
84 83 mutex_lock(&log_lock);
85 84 d = log_depth;
86 85 mutex_unlock(&log_lock);
87 86 return d;
88 87 }
89 88
90 89 int fex_set_log_depth(int d)
91 90 {
92 91 if (d < 0)
93 92 return 0;
94 93 mutex_lock(&log_lock);
95 94 log_depth = d;
96 95 mutex_unlock(&log_lock);
97 96 return 1;
98 97 }
99 98
100 99 static struct exc_list {
101 100 struct exc_list *next;
102 101 char *addr;
103 102 unsigned long code;
104 103 int nstack;
105 104 char *stack[1]; /* actual length is max(1,nstack) */
106 105 } *list = NULL;
107 106
108 107 #ifdef __sparcv9
109 108 #define FRAMEP(X) (struct frame *)((char*)(X)+(((long)(X)&1)?2047:0))
110 109 #else
111 110 #define FRAMEP(X) (struct frame *)(X)
112 111 #endif
113 112
114 113 #ifdef _LP64
115 114 #define PDIG "16"
116 115 #else
117 116 #define PDIG "8"
118 117 #endif
119 118
120 119 /* look for a matching exc_list; return 1 if one is found,
121 120 otherwise add this one to the list and return 0 */
122 121 static int check_exc_list(char *addr, unsigned long code, char *stk,
123 122 struct frame *fp)
124 123 {
125 124 struct exc_list *l, *ll = NULL;
126 125 struct frame *f;
127 126 int i, n;
128 127
129 128 if (list) {
130 129 for (l = list; l; ll = l, l = l->next) {
131 130 if (l->addr != addr || l->code != code)
132 131 continue;
133 132 if (log_depth < 1 || l->nstack < 1)
134 133 return 1;
135 134 if (l->stack[0] != stk)
136 135 continue;
137 136 n = 1;
138 137 for (i = 1, f = fp; i < log_depth && i < l->nstack &&
139 138 f && f->fr_savpc; i++, f = FRAMEP(f->fr_savfp))
140 139 if (l->stack[i] != (char *)f->fr_savpc) {
141 140 n = 0;
142 141 break;
143 142 }
144 143 if (n)
145 144 return 1;
146 145 }
147 146 }
148 147
149 148 /* create a new exc_list structure and tack it on the list */
150 149 for (n = 1, f = fp; n < log_depth && f && f->fr_savpc;
151 150 n++, f = FRAMEP(f->fr_savfp)) ;
152 151 if ((l = (struct exc_list *)malloc(sizeof(struct exc_list) +
153 152 (n - 1) * sizeof(char *))) != NULL) {
154 153 l->next = NULL;
155 154 l->addr = addr;
156 155 l->code = code;
157 156 l->nstack = ((log_depth < 1)? 0 : n);
158 157 l->stack[0] = stk;
159 158 for (i = 1; i < n; i++) {
160 159 l->stack[i] = (char *)fp->fr_savpc;
161 160 fp = FRAMEP(fp->fr_savfp);
162 161 }
163 162 if (list)
164 163 ll->next = l;
165 164 else
166 165 list = l;
167 166 }
168 167 return 0;
169 168 }
170 169
171 170 /*
172 171 * Warning: cleverness ahead
173 172 *
174 173 * In the following code, the use of sprintf+write rather than fprintf
175 174 * to send output to the log file is intentional. The reason is that
176 175 * fprintf is not async-signal-safe. "But," you protest, "SIGFPE is
177 176 * not an asynchronous signal! It's always handled by the same thread
178 177 * that executed the fpop that provoked it." That's true, but a prob-
179 178 * lem arises because (i) base conversion in fprintf can cause a fp
180 179 * exception and (ii) my signal handler acquires a mutex lock before
181 180 * sending output to the log file (so that outputs for entries from
182 181 * different threads aren't interspersed). Therefore, if the code
183 182 * were to use fprintf, a deadlock could occur as follows:
184 183 *
185 184 * Thread A Thread B
186 185 *
187 186 * Incurs a fp exception, Calls fprintf,
188 187 * acquires log_lock acquires file rmutex lock
189 188 *
190 189 * Calls fprintf, Incurs a fp exception,
191 190 * waits for file rmutex lock waits for log_lock
192 191 *
193 192 * (I could just verify that fprintf doesn't hold the rmutex lock while
194 193 * it's doing the base conversion, but since efficiency is of little
195 194 * concern here, I opted for the safe and dumb route.)
196 195 */
197 196
198 197 static void print_stack(int fd, char *addr, struct frame *fp)
199 198 {
200 199 int i;
201 200 char *name, buf[30];
202 201
203 202 for (i = 0; i < log_depth && addr != NULL; i++) {
204 203 if (__fex_sym(addr, &name) != NULL) {
205 204 write(fd, buf, sprintf(buf, " 0x%0" PDIG "lx ",
206 205 (long)addr));
207 206 write(fd, name, strlen(name));
208 207 write(fd, "\n", 1);
209 208 if (!strcmp(name, "main"))
210 209 break;
211 210 } else {
212 211 write(fd, buf, sprintf(buf, " 0x%0" PDIG "lx\n",
213 212 (long)addr));
214 213 }
215 214 if (fp == NULL)
216 215 break;
217 216 addr = (char *)fp->fr_savpc;
218 217 fp = FRAMEP(fp->fr_savfp);
219 218 }
220 219 }
221 220
222 221 void fex_log_entry(const char *msg)
223 222 {
224 223 ucontext_t uc;
225 224 struct frame *fp;
226 225 char *stk;
227 226 int fd;
228 227
229 228 /* if logging is disabled, just return */
230 229 mutex_lock(&log_lock);
231 230 if (log_fp == NULL) {
232 231 mutex_unlock(&log_lock);
233 232 return;
234 233 }
235 234
236 235 /* get the frame pointer from the current context and
237 236 pop our own frame */
238 237 getcontext(&uc);
239 238 #if defined(__sparc) || defined(__amd64)
240 239 fp = FRAMEP(uc.uc_mcontext.gregs[REG_SP]);
241 240 #elif defined(__i386) /* !defined(__amd64) */
242 241 fp = FRAMEP(uc.uc_mcontext.gregs[EBP]);
243 242 #else
244 243 #error Unknown architecture
245 244 #endif
246 245 if (fp == NULL) {
247 246 mutex_unlock(&log_lock);
248 247 return;
249 248 }
250 249 stk = (char *)fp->fr_savpc;
251 250 fp = FRAMEP(fp->fr_savfp);
252 251
253 252 /* if we've already logged this message here, don't make an entry */
254 253 if (check_exc_list(stk, (unsigned long)msg, stk, fp)) {
255 254 mutex_unlock(&log_lock);
256 255 return;
257 256 }
258 257
259 258 /* make an entry */
260 259 fd = fileno(log_fp);
261 260 write(fd, "fex_log_entry: ", 15);
262 261 write(fd, msg, strlen(msg));
263 262 write(fd, "\n", 1);
264 263 __fex_sym_init();
265 264 print_stack(fd, stk, fp);
266 265 mutex_unlock(&log_lock);
267 266 }
268 267
269 268 static const char *exception[FEX_NUM_EXC] = {
270 269 "inexact result",
271 270 "division by zero",
272 271 "underflow",
273 272 "overflow",
274 273 "invalid operation (0/0)",
275 274 "invalid operation (inf/inf)",
276 275 "invalid operation (inf-inf)",
277 276 "invalid operation (0*inf)",
278 277 "invalid operation (sqrt)",
279 278 "invalid operation (snan)",
280 279 "invalid operation (int)",
281 280 "invalid operation (cmp)"
282 281 };
283 282
284 283 void
285 284 __fex_mklog(ucontext_t *uap, char *addr, int f, enum fex_exception e,
286 285 int m, void *p)
287 286 {
288 287 struct frame *fp;
289 288 char *stk, *name, buf[30];
290 289 int fd;
291 290
292 291 /* if logging is disabled, just return */
293 292 mutex_lock(&log_lock);
294 293 if (log_fp == NULL) {
295 294 mutex_unlock(&log_lock);
296 295 return;
297 296 }
298 297
299 298 /* get stack info */
300 299 #if defined(__sparc)
301 300 stk = (char*)uap->uc_mcontext.gregs[REG_PC];
302 301 fp = FRAMEP(uap->uc_mcontext.gregs[REG_SP]);
303 302 #elif defined(__amd64)
304 303 stk = (char*)uap->uc_mcontext.gregs[REG_PC];
305 304 fp = FRAMEP(uap->uc_mcontext.gregs[REG_RBP]);
306 305 #elif defined(__i386) /* !defined(__amd64) */
307 306 stk = (char*)uap->uc_mcontext.gregs[PC];
308 307 fp = FRAMEP(uap->uc_mcontext.gregs[EBP]);
309 308 #else
310 309 #error Unknown architecture
311 310 #endif
312 311
313 312 /* if the handling mode is the default and this exception's
314 313 flag is already raised, don't make an entry */
315 314 if (m == FEX_NONSTOP) {
316 315 switch (e) {
317 316 case fex_inexact:
318 317 if (f & FE_INEXACT) {
319 318 mutex_unlock(&log_lock);
320 319 return;
321 320 }
322 321 break;
323 322 case fex_underflow:
324 323 if (f & FE_UNDERFLOW) {
325 324 mutex_unlock(&log_lock);
326 325 return;
327 326 }
328 327 break;
329 328 case fex_overflow:
330 329 if (f & FE_OVERFLOW) {
331 330 mutex_unlock(&log_lock);
332 331 return;
333 332 }
334 333 break;
335 334 case fex_division:
336 335 if (f & FE_DIVBYZERO) {
337 336 mutex_unlock(&log_lock);
338 337 return;
339 338 }
340 339 break;
341 340 default:
342 341 if (f & FE_INVALID) {
343 342 mutex_unlock(&log_lock);
344 343 return;
345 344 }
346 345 break;
347 346 }
348 347 }
349 348
350 349 /* if we've already logged this exception at this address,
351 350 don't make an entry */
352 351 if (check_exc_list(addr, (unsigned long)e, stk, fp)) {
353 352 mutex_unlock(&log_lock);
354 353 return;
355 354 }
356 355
357 356 /* make an entry */
358 357 fd = fileno(log_fp);
359 358 write(fd, "Floating point ", 15);
360 359 write(fd, exception[e], strlen(exception[e]));
361 360 write(fd, buf, sprintf(buf, " at 0x%0" PDIG "lx", (long)addr));
362 361 __fex_sym_init();
363 362 if (__fex_sym(addr, &name) != NULL) {
364 363 write(fd, " ", 1);
365 364 write(fd, name, strlen(name));
366 365 }
367 366 switch (m) {
368 367 case FEX_NONSTOP:
369 368 write(fd, ", nonstop mode\n", 15);
370 369 break;
371 370
372 371 case FEX_ABORT:
373 372 write(fd, ", abort\n", 8);
374 373 break;
375 374
376 375 case FEX_NOHANDLER:
377 376 if (p == (void *)SIG_DFL) {
378 377 write(fd, ", handler: SIG_DFL\n", 19);
379 378 break;
380 379 }
381 380 else if (p == (void *)SIG_IGN) {
382 381 write(fd, ", handler: SIG_IGN\n", 19);
383 382 break;
384 383 }
385 384 /* fall through*/
386 385 default:
387 386 write(fd, ", handler: ", 11);
388 387 if (__fex_sym((char *)p, &name) != NULL) {
389 388 write(fd, name, strlen(name));
390 389 write(fd, "\n", 1);
391 390 } else {
392 391 write(fd, buf, sprintf(buf, "0x%0" PDIG "lx\n",
393 392 (long)p));
394 393 }
395 394 break;
396 395 }
397 396 print_stack(fd, stk, fp);
398 397 mutex_unlock(&log_lock);
399 398 }
↓ open down ↓ |
353 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX