1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
|
Index: src/code/float-trap.lisp
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/code/float-trap.lisp,v
retrieving revision 1.19
diff -u -r1.19 float-trap.lisp
--- src/code/float-trap.lisp 6 Oct 2005 19:43:00 -0000 1.19
+++ src/code/float-trap.lisp 26 Jan 2006 20:43:33 -0000
@@ -153,10 +153,28 @@
`(not (zerop (logand ,(dpb (float-trap-mask traps) float-traps-byte 0)
(floating-point-modes)))))
+;;; SIGFPE code to floating-point error
+#+freebsd
+(defparameter *sigfpe-code-error-alist*
+ (list (cons sb!unix::fpe-intovf 'floating-point-overflow)
+ (cons sb!unix::fpe-intdiv 'division-by-zero)
+ (cons sb!unix::fpe-fltdiv 'division-by-zero)
+ (cons sb!unix::fpe-fltovf 'floating-point-overflow)
+ (cons sb!unix::fpe-fltund 'floating-point-underflow)
+ (cons sb!unix::fpe-fltres 'floating-point-inexact)
+ (cons sb!unix::fpe-fltinv 'floating-point-invalid-operation)
+ (cons sb!unix::fpe-fltsub 'floating-point-exception)))
+
;;; Signal the appropriate condition when we get a floating-point error.
(defun sigfpe-handler (signal info context)
- (declare (ignore signal info))
+ (declare (ignore signal #!-freebsd info))
+ #!+freebsd
+ (declare (type system-area-pointer info))
(declare (type system-area-pointer context))
+ #!+freebsd
+ (let ((code (sb!unix::siginfo-code info)))
+ (error (or (cdr (assoc code *sigfpe-code-error-alist*))
+ 'floating-point-exception)))
(let* ((modes (context-floating-point-modes
(sb!alien:sap-alien context (* os-context-t))))
(traps (logand (ldb float-exceptions-byte modes)
Index: src/code/target-signal.lisp
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/code/target-signal.lisp,v
retrieving revision 1.33
diff -u -r1.33 target-signal.lisp
--- src/code/target-signal.lisp 17 Oct 2005 09:18:47 -0000 1.33
+++ src/code/target-signal.lisp 26 Jan 2006 20:43:33 -0000
@@ -164,6 +164,10 @@
;;;; etc.
+;;; extract si_code from siginfo_t
+(sb!alien:define-alien-routine ("siginfo_code" siginfo-code) sb!alien:int
+ (info system-area-pointer))
+
;;; CMU CL comment:
;;; Magically converted by the compiler into a break instruction.
(defun receive-pending-interrupt ()
Index: src/runtime/interrupt.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/interrupt.c,v
retrieving revision 1.109
diff -u -r1.109 interrupt.c
--- src/runtime/interrupt.c 5 Jan 2006 14:13:14 -0000 1.109
+++ src/runtime/interrupt.c 26 Jan 2006 20:43:33 -0000
@@ -454,7 +454,7 @@
check_interrupts_enabled_or_lose(context);
#endif
-#ifdef LISP_FEATURE_LINUX
+#if defined(LISP_FEATURE_LINUX) || defined(__FreeBSD__)
/* Under Linux on some architectures, we appear to have to restore
the FPU control word from the context, as after the signal is
delivered we appear to have a null FPU control word. */
@@ -644,7 +644,7 @@
os_context_t *context = arch_os_get_context(&void_context);
struct thread *thread=arch_os_get_current_thread();
struct interrupt_data *data=thread->interrupt_data;
-#ifdef LISP_FEATURE_LINUX
+#if defined(LISP_FEATURE_LINUX) || defined(__FreeBSD__)
os_restore_fp_control(context);
#endif
if(maybe_defer_handler(interrupt_handle_now,data,signal,info,context))
@@ -661,7 +661,7 @@
{
os_context_t *context = (os_context_t*)void_context;
-#ifdef LISP_FEATURE_LINUX
+#if defined(LISP_FEATURE_LINUX) || defined(__FreeBSD__)
os_restore_fp_control(context);
#endif
check_blockables_blocked_or_lose();
@@ -679,7 +679,7 @@
os_context_t *context = arch_os_get_context(&void_context);
struct thread *thread=arch_os_get_current_thread();
struct interrupt_data *data=thread->interrupt_data;
-#ifdef LISP_FEATURE_LINUX
+#if defined(LISP_FEATURE_LINUX) || defined(__FreeBSD__)
os_restore_fp_control(context);
#endif
if(maybe_defer_handler(low_level_interrupt_handle_now,data,
@@ -1276,3 +1276,9 @@
SHOW("returning from interrupt_init()");
#endif
}
+
+int
+siginfo_code(siginfo_t *info)
+{
+ return info->si_code;
+}
Index: src/runtime/x86-arch.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/x86-arch.c,v
retrieving revision 1.36
diff -u -r1.36 x86-arch.c
--- src/runtime/x86-arch.c 3 Jan 2006 09:52:38 -0000 1.36
+++ src/runtime/x86-arch.c 26 Jan 2006 20:43:33 -0000
@@ -248,7 +248,7 @@
single-stepping (as far as I can tell) this is somewhat moot,
but it might be worth either moving this code up or deleting
the single-stepping code entirely. -- CSR, 2002-07-15 */
-#ifdef LISP_FEATURE_LINUX
+#if defined(LISP_FEATURE_LINUX) || defined(__FreeBSD__)
os_restore_fp_control(context);
#endif
Index: src/runtime/x86-bsd-os.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/src/runtime/x86-bsd-os.c,v
retrieving revision 1.7
diff -u -r1.7 x86-bsd-os.c
--- src/runtime/x86-bsd-os.c 14 Jul 2005 15:41:21 -0000 1.7
+++ src/runtime/x86-bsd-os.c 26 Jan 2006 20:43:33 -0000
@@ -85,6 +85,52 @@
#endif /* __NetBSD__ */
+#ifdef __FreeBSD__
+#if __FreeBSD_version >= 500000
+/*
+ * FreeBSD 5.0 or later initializes FPU control word for signal
+ * handler.
+ */
+#include <machine/npx.h>
+
+static __inline__ void
+fldcw(unsigned short cw)
+{
+ __asm__ __volatile__ ("fldcw %0" : : "m" (cw));
+}
+
+void
+os_restore_fp_control(os_context_t *context)
+{
+ union savefpu *addr;
+
+ addr = (union savefpu *)context->uc_mcontext.mc_fpstate;
+ switch (context->uc_mcontext.mc_fpformat) {
+ case _MC_FPFMT_387:
+ /* FPU state is saved by fnsave */
+ fldcw((unsigned short)addr->sv_87.sv_env.en_cw);
+ break;
+ case _MC_FPFMT_XMM:
+ /* FPU/SSE state is saved by fxsave */
+ fldcw(addr->sv_xmm.sv_env.en_cw);
+ break;
+ default:
+ /* No FPU state is saved. */
+ break;
+ }
+}
+#else /* __FreeBSD_version < 500000 */
+/*
+ * FreeBSD befoer 5.0 does not touch FPU control word for signal
+ * handler.
+ */
+void
+os_restore_fp_control(os_context_t *context)
+{
+ /* DO NOTHING */
+}
+#endif /* __FreeBSD_version */
+#endif /* __FreeBSD__ */
/* FIXME: If this can be a no-op on BSD/x86, then it
* deserves a more precise name.
Index: tools-for-build/grovel-headers.c
===================================================================
RCS file: /cvsroot/sbcl/sbcl/tools-for-build/grovel-headers.c,v
retrieving revision 1.12
diff -u -r1.12 grovel-headers.c
--- tools-for-build/grovel-headers.c 16 Jan 2006 15:39:58 -0000 1.12
+++ tools-for-build/grovel-headers.c 26 Jan 2006 20:43:33 -0000
@@ -234,6 +234,16 @@
defsignal("sigxcpu", SIGXCPU);
defsignal("sigxfsz", SIGXFSZ);
#endif
+#ifdef __FreeBSD__
+ defconstant("fpe-intovf", FPE_INTOVF);
+ defconstant("fpe-intdiv", FPE_INTDIV);
+ defconstant("fpe-fltdiv", FPE_FLTDIV);
+ defconstant("fpe-fltovf", FPE_FLTOVF);
+ defconstant("fpe-fltund", FPE_FLTUND);
+ defconstant("fpe-fltres", FPE_FLTRES);
+ defconstant("fpe-fltinv", FPE_FLTINV);
+ defconstant("fpe-fltsub", FPE_FLTSUB);
+#endif
#endif // _WIN32
return 0;
}
|