1 /* -*-C-*-
2 
3 Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
4     1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
5     2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Massachusetts
6     Institute of Technology
7 
8 This file is part of MIT/GNU Scheme.
9 
10 MIT/GNU Scheme is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or (at
13 your option) any later version.
14 
15 MIT/GNU Scheme is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with MIT/GNU Scheme; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
23 USA.
24 
25 */
26 
27 /* Signal Handlers */
28 
29 #ifndef SCM_UXSIG_H
30 #define SCM_UXSIG_H
31 
32 #ifndef HAVE_POSIX_SIGNALS
33 #  ifdef HAVE_SIGHOLD
34 #    define INSTALL_HANDLER UX_sigset
35 #    define NEED_HANDLER_TRANSACTION
36 #    define ENTER_HANDLER(signo)
37 #    define ABORT_HANDLER(signo, handler) UX_sigrelse (signo)
38 #    define EXIT_HANDLER(signo, handler)
39 #  else
40 #    define INSTALL_HANDLER UX_signal
41 #    define NEED_HANDLER_TRANSACTION
42 #    define ENTER_HANDLER(signo) UX_signal ((signo), SIG_IGN)
43 #    define ABORT_HANDLER UX_signal
44 #    define EXIT_HANDLER UX_signal
45 #  endif
46 #endif
47 
48 #if defined(CC_IS_NATIVE) && !defined(SIGNAL_HANDLERS_CAN_USE_SCHEME_STACK)
49 
50 struct signal_instance
51 {
52   int signo;
53   SIGINFO_T info;
54   SIGCONTEXT_ARG_T * pscp;
55 };
56 
57 #  define DEFUN_STD_HANDLER(name, statement)			\
58 								\
59 DEFUN_STD_HANDLER_ (name##_body, statement)			\
60 								\
61 void								\
62 name##_wrapper (void *context)					\
63 {								\
64   struct signal_instance *i = context;				\
65   (void) name##_body ((i->signo), (i->info), (i->pscp));	\
66 }								\
67 								\
68 Tsignal_handler_result						\
69 name (int signo, SIGINFO_T info, SIGCONTEXT_ARG_T * pscp)	\
70 {								\
71   struct signal_instance i;					\
72   (i.signo) = signo;						\
73   (i.info) = info;						\
74   (i.pscp) = pscp;						\
75   within_c_stack ((&name##_wrapper), (&i));			\
76   SIGNAL_HANDLER_RETURN ();					\
77 }
78 
79 #else
80 
81 #  define DEFUN_STD_HANDLER DEFUN_STD_HANDLER_
82 
83 #endif /* CC_SUPPORT_P && !SIGNAL_HANDLERS_CAN_USE_SCHEME_STACK */
84 
85 #ifndef NEED_HANDLER_TRANSACTION
86 
87 #define DEFUN_STD_HANDLER_(name, statement)				\
88 Tsignal_handler_result							\
89 name (int signo,							\
90       SIGINFO_T info,							\
91       SIGCONTEXT_ARG_T * pscp)						\
92 {									\
93   int STD_HANDLER_abortp;						\
94   DECLARE_SIGCONTEXT (scp, pscp);					\
95   record_signal_delivery (signo);					\
96   STD_HANDLER_abortp = (enter_interruption_extent ());			\
97   statement;								\
98   if (STD_HANDLER_abortp)						\
99     exit_interruption_extent ();					\
100   SIGNAL_HANDLER_RETURN ();						\
101 }
102 
103 #else /* NEED_HANDLER_TRANSACTION */
104 
105 struct handler_record
106 {
107   int signo;
108   Tsignal_handler handler;
109 };
110 
111 #define DEFUN_STD_HANDLER_(name, statement)				\
112 Tsignal_handler_result							\
113 name (int signo,							\
114       SIGINFO_T info,							\
115       SIGCONTEXT_ARG_T * pscp)						\
116 {									\
117   int STD_HANDLER_abortp;						\
118   DECLARE_SIGCONTEXT (scp, pscp);					\
119   ENTER_HANDLER (signo);						\
120   record_signal_delivery (signo);					\
121   STD_HANDLER_abortp = (enter_interruption_extent ());			\
122   transaction_begin ();							\
123   {									\
124     struct handler_record * record =					\
125       (dstack_alloc (sizeof (struct handler_record)));			\
126     (record -> signo) = signo;						\
127     (record -> handler) = name;						\
128     transaction_record_action (tat_abort, ta_abort_handler, record);	\
129   }									\
130   statement;								\
131   if (STD_HANDLER_abortp)						\
132     {									\
133       transaction_abort ();						\
134       exit_interruption_extent ();					\
135     }									\
136   transaction_commit ();						\
137   EXIT_HANDLER (signo, name);						\
138   SIGNAL_HANDLER_RETURN ();						\
139 }
140 
141 extern void ta_abort_handler (void *);
142 
143 #endif /* NEED_HANDLER_TRANSACTION */
144 
145 #ifndef DEBUG_SIGNAL_DELIVERY
146 #define record_signal_delivery(signo)
147 #endif
148 
149 #endif /* SCM_UXSIG_H */
150