ยปCore Development>Code coverage>Modules/fpectlmodule.c

Python code coverage for Modules/fpectlmodule.c

#countcontent
1n/a/*
2n/a ---------------------------------------------------------------------
3n/a / Copyright (c) 1996. \
4n/a | The Regents of the University of California. |
5n/a | All rights reserved. |
6n/a | |
7n/a | Permission to use, copy, modify, and distribute this software for |
8n/a | any purpose without fee is hereby granted, provided that this en- |
9n/a | tire notice is included in all copies of any software which is or |
10n/a | includes a copy or modification of this software and in all |
11n/a | copies of the supporting documentation for such software. |
12n/a | |
13n/a | This work was produced at the University of California, Lawrence |
14n/a | Livermore National Laboratory under contract no. W-7405-ENG-48 |
15n/a | between the U.S. Department of Energy and The Regents of the |
16n/a | University of California for the operation of UC LLNL. |
17n/a | |
18n/a | DISCLAIMER |
19n/a | |
20n/a | This software was prepared as an account of work sponsored by an |
21n/a | agency of the United States Government. Neither the United States |
22n/a | Government nor the University of California nor any of their em- |
23n/a | ployees, makes any warranty, express or implied, or assumes any |
24n/a | liability or responsibility for the accuracy, completeness, or |
25n/a | usefulness of any information, apparatus, product, or process |
26n/a | disclosed, or represents that its use would not infringe |
27n/a | privately-owned rights. Reference herein to any specific commer- |
28n/a | cial products, process, or service by trade name, trademark, |
29n/a | manufacturer, or otherwise, does not necessarily constitute or |
30n/a | imply its endorsement, recommendation, or favoring by the United |
31n/a | States Government or the University of California. The views and |
32n/a | opinions of authors expressed herein do not necessarily state or |
33n/a | reflect those of the United States Government or the University |
34n/a | of California, and shall not be used for advertising or product |
35n/a \ endorsement purposes. /
36n/a ---------------------------------------------------------------------
37n/a*/
38n/a
39n/a/*
40n/a Floating point exception control module.
41n/a
42n/a This Python module provides bare-bones control over floating point
43n/a units from several hardware manufacturers. Specifically, it allows
44n/a the user to turn on the generation of SIGFPE whenever any of the
45n/a three serious IEEE 754 exceptions (Division by Zero, Overflow,
46n/a Invalid Operation) occurs. We currently ignore Underflow and
47n/a Inexact Result exceptions, although those could certainly be added
48n/a if desired.
49n/a
50n/a The module also establishes a signal handler for SIGFPE during
51n/a initialization. This builds on code found in the Python
52n/a distribution at Include/pyfpe.h and Python/pyfpe.c. If those files
53n/a are not in your Python distribution, find them in a patch at
54n/a ftp://icf.llnl.gov/pub/python/busby/patches.961108.tgz.
55n/a
56n/a This module is only useful to you if it happens to include code
57n/a specific for your hardware and software environment. If you can
58n/a contribute OS-specific code for new platforms, or corrections for
59n/a the code provided, it will be greatly appreciated.
60n/a
61n/a ** Version 1.0: September 20, 1996. Lee Busby, LLNL.
62n/a */
63n/a
64n/a#ifdef __cplusplus
65n/aextern "C" {
66n/a#endif
67n/a
68n/a#include "Python.h"
69n/a#include <signal.h>
70n/a
71n/a#if defined(__FreeBSD__)
72n/a# include <ieeefp.h>
73n/a#endif
74n/a
75n/a#ifndef WANT_SIGFPE_HANDLER
76n/a/* Define locally if they are not defined in Python. This gives only
77n/a * the limited control to induce a core dump in case of an exception.
78n/a */
79n/a#include <setjmp.h>
80n/astatic jmp_buf PyFPE_jbuf;
81n/astatic int PyFPE_counter = 0;
82n/a#endif
83n/a
84n/atypedef void Sigfunc(int);
85n/astatic Sigfunc sigfpe_handler;
86n/astatic void fpe_reset(Sigfunc *);
87n/a
88n/astatic PyObject *fpe_error;
89n/a
90n/aPyMODINIT_FUNC PyInit_fpectl(void);
91n/astatic PyObject *turnon_sigfpe (PyObject *self,PyObject *args);
92n/astatic PyObject *turnoff_sigfpe (PyObject *self,PyObject *args);
93n/a
94n/astatic PyMethodDef fpectl_methods[] = {
95n/a {"turnon_sigfpe", (PyCFunction) turnon_sigfpe, METH_VARARGS},
96n/a {"turnoff_sigfpe", (PyCFunction) turnoff_sigfpe, METH_VARARGS},
97n/a {0,0}
98n/a};
99n/a
100n/astatic PyObject *turnon_sigfpe(PyObject *self,PyObject *args)
101n/a{
102n/a /* Do any architecture-specific one-time only initialization here. */
103n/a
104n/a fpe_reset(sigfpe_handler);
105n/a Py_RETURN_NONE;
106n/a}
107n/a
108n/astatic void fpe_reset(Sigfunc *handler)
109n/a{
110n/a /* Reset the exception handling machinery, and reset the signal
111n/a * handler for SIGFPE to the given handler.
112n/a */
113n/a
114n/a/*-- IRIX -----------------------------------------------------------------*/
115n/a#if defined(sgi)
116n/a /* See man page on handle_sigfpes -- must link with -lfpe
117n/a * My usage doesn't follow the man page exactly. Maybe somebody
118n/a * else can explain handle_sigfpes to me....
119n/a * cc -c -I/usr/local/python/include fpectlmodule.c
120n/a * ld -shared -o fpectlmodule.so fpectlmodule.o -lfpe
121n/a */
122n/a#include <sigfpe.h>
123n/a typedef void user_routine (unsigned[5], int[2]);
124n/a typedef void abort_routine (unsigned long);
125n/a handle_sigfpes(_OFF, 0,
126n/a (user_routine *)0,
127n/a _TURN_OFF_HANDLER_ON_ERROR,
128n/a NULL);
129n/a handle_sigfpes(_ON, _EN_OVERFL | _EN_DIVZERO | _EN_INVALID,
130n/a (user_routine *)0,
131n/a _ABORT_ON_ERROR,
132n/a NULL);
133n/a PyOS_setsig(SIGFPE, handler);
134n/a
135n/a/*-- SunOS and Solaris ----------------------------------------------------*/
136n/a#elif defined(sun)
137n/a /* References: ieee_handler, ieee_sun, ieee_functions, and ieee_flags
138n/a man pages (SunOS or Solaris)
139n/a cc -c -I/usr/local/python/include fpectlmodule.c
140n/a ld -G -o fpectlmodule.so -L/opt/SUNWspro/lib fpectlmodule.o -lsunmath -lm
141n/a */
142n/a#include <math.h>
143n/a#ifndef _SUNMATH_H
144n/a extern void nonstandard_arithmetic(void);
145n/a extern int ieee_flags(const char*, const char*, const char*, char **);
146n/a extern long ieee_handler(const char*, const char*, sigfpe_handler_type);
147n/a#endif
148n/a
149n/a char *mode="exception", *in="all", *out;
150n/a (void) nonstandard_arithmetic();
151n/a (void) ieee_flags("clearall",mode,in,&out);
152n/a (void) ieee_handler("set","common",(sigfpe_handler_type)handler);
153n/a PyOS_setsig(SIGFPE, handler);
154n/a
155n/a/*-- HPUX -----------------------------------------------------------------*/
156n/a#elif defined(__hppa) || defined(hppa)
157n/a /* References: fpsetmask man page */
158n/a /* cc -Aa +z -c -I/usr/local/python/include fpectlmodule.c */
159n/a /* ld -b -o fpectlmodule.sl fpectlmodule.o -lm */
160n/a#include <math.h>
161n/a fpsetdefaults();
162n/a PyOS_setsig(SIGFPE, handler);
163n/a
164n/a/*-- IBM AIX --------------------------------------------------------------*/
165n/a#elif defined(__AIX) || defined(_AIX)
166n/a /* References: fp_trap, fp_enable man pages */
167n/a#include <fptrap.h>
168n/a fp_trap(FP_TRAP_SYNC);
169n/a fp_enable(TRP_INVALID | TRP_DIV_BY_ZERO | TRP_OVERFLOW);
170n/a PyOS_setsig(SIGFPE, handler);
171n/a
172n/a/*-- DEC ALPHA LINUX ------------------------------------------------------*/
173n/a#elif defined(__alpha) && defined(linux)
174n/a#include <asm/fpu.h>
175n/a unsigned long fp_control =
176n/a IEEE_TRAP_ENABLE_INV | IEEE_TRAP_ENABLE_DZE | IEEE_TRAP_ENABLE_OVF;
177n/a ieee_set_fp_control(fp_control);
178n/a PyOS_setsig(SIGFPE, handler);
179n/a
180n/a/*-- Cray Unicos ----------------------------------------------------------*/
181n/a#elif defined(cray)
182n/a /* UNICOS delivers SIGFPE by default, but no matherr */
183n/a#ifdef HAS_LIBMSET
184n/a libmset(-1);
185n/a#endif
186n/a PyOS_setsig(SIGFPE, handler);
187n/a
188n/a/*-- FreeBSD ----------------------------------------------------------------*/
189n/a#elif defined(__FreeBSD__)
190n/a fpresetsticky(fpgetsticky());
191n/a fpsetmask(FP_X_INV | FP_X_DZ | FP_X_OFL);
192n/a PyOS_setsig(SIGFPE, handler);
193n/a
194n/a/*-- Linux ----------------------------------------------------------------*/
195n/a#elif defined(linux)
196n/a#ifdef __GLIBC__
197n/a#include <fpu_control.h>
198n/a#else
199n/a#include <i386/fpu_control.h>
200n/a#endif
201n/a#ifdef _FPU_SETCW
202n/a {
203n/a fpu_control_t cw = 0x1372;
204n/a _FPU_SETCW(cw);
205n/a }
206n/a#else
207n/a __setfpucw(0x1372);
208n/a#endif
209n/a PyOS_setsig(SIGFPE, handler);
210n/a
211n/a/*-- Microsoft Windows, NT ------------------------------------------------*/
212n/a#elif defined(_MSC_VER)
213n/a /* Reference: Visual C++ Books Online 4.2,
214n/a Run-Time Library Reference, _control87, _controlfp */
215n/a#include <float.h>
216n/a unsigned int cw = _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW;
217n/a (void)_controlfp(0, cw);
218n/a PyOS_setsig(SIGFPE, handler);
219n/a
220n/a/*-- Give Up --------------------------------------------------------------*/
221n/a#else
222n/a fputs("Operation not implemented\n", stderr);
223n/a#endif
224n/a
225n/a}
226n/a
227n/astatic PyObject *turnoff_sigfpe(PyObject *self,PyObject *args)
228n/a{
229n/a#ifdef __FreeBSD__
230n/a fpresetsticky(fpgetsticky());
231n/a fpsetmask(0);
232n/a#else
233n/a fputs("Operation not implemented\n", stderr);
234n/a#endif
235n/a Py_RETURN_NONE;
236n/a}
237n/a
238n/astatic void sigfpe_handler(int signo)
239n/a{
240n/a fpe_reset(sigfpe_handler);
241n/a if(PyFPE_counter) {
242n/a longjmp(PyFPE_jbuf, 1);
243n/a } else {
244n/a Py_FatalError("Unprotected floating point exception");
245n/a }
246n/a}
247n/a
248n/astatic struct PyModuleDef fpectlmodule = {
249n/a PyModuleDef_HEAD_INIT,
250n/a "fpectl",
251n/a NULL,
252n/a -1,
253n/a fpectl_methods,
254n/a NULL,
255n/a NULL,
256n/a NULL,
257n/a NULL
258n/a};
259n/a
260n/aPyMODINIT_FUNC PyInit_fpectl(void)
261n/a{
262n/a PyObject *m, *d;
263n/a m = PyModule_Create(&fpectlmodule);
264n/a if (m == NULL)
265n/a return NULL;
266n/a d = PyModule_GetDict(m);
267n/a fpe_error = PyErr_NewException("fpectl.error", NULL, NULL);
268n/a if (fpe_error != NULL)
269n/a PyDict_SetItemString(d, "error", fpe_error);
270n/a return m;
271n/a}
272n/a
273n/a#ifdef __cplusplus
274n/a}
275n/a#endif