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 /* Interrupt manipulation utilities. */
28 
29 /* Interrupt bits -- scanned from LSB (1) to MSB (16) */
30 
31 #define INT_Stack_Overflow	0x0001UL /* Local interrupt */
32 #define INT_Global_GC		0x0002UL
33 #define INT_GC			0x0004UL /* Local interrupt */
34 #define INT_Global_1		0x0008UL
35 #define INT_Character		0x0010UL /* Local interrupt */
36 #define INT_AFTER_GC		0x0020UL /* Local interrupt */
37 #define INT_Timer		0x0040UL /* Local interrupt */
38 #define INT_Global_3		0x0080UL
39 #define INT_Suspend		0x0100UL /* Local interrupt */
40 
41 /* Descartes profiling interrupts */
42 
43 #define INT_IPPB_Flush		0x0200UL /* Local interrupt */
44 #define INT_IPPB_Extend		0x0400UL /* Local interrupt */
45 #define INT_PCBPB_Flush		0x0800UL /* Local interrupt */
46 #define INT_PCBPB_Extend	0x1000UL /* Local interrupt */
47 #define INT_HCBPB_Flush		0x2000UL /* Local interrupt */
48 #define INT_HCBPB_Extend	0x4000UL /* Local interrupt */
49 
50 #define INT_Step_CC		0x8000UL
51 
52 #define INT_Global_Mask (INT_Global_GC | INT_Global_1 | INT_Global_3)
53 
54 #define Global_GC_Level		0x1UL
55 #define Global_1_Level		0x3UL
56 #define Global_3_Level		0x7UL
57 #define MAX_INTERRUPT_NUMBER	0xFUL	/* 2^15 = INT_Step_CC */
58 
59 #define INT_Mask		((1UL << (MAX_INTERRUPT_NUMBER + 1)) - 1)
60 
61 /* Utility macros. */
62 
63 #define PENDING_INTERRUPTS() (GET_INT_MASK & GET_INT_CODE)
64 #define PENDING_INTERRUPTS_P ((PENDING_INTERRUPTS ()) != 0)
65 #define INTERRUPT_QUEUED_P(mask) ((GET_INT_CODE & (mask)) != 0)
66 #define INTERRUPT_ENABLED_P(mask) ((GET_INT_MASK & (mask)) != 0)
67 #define INTERRUPT_PENDING_P(mask) (((PENDING_INTERRUPTS ()) & (mask)) != 0)
68 
69 #define COMPILER_SETUP_INTERRUPT() do					\
70 {									\
71   SET_MEMTOP								\
72     (((PENDING_INTERRUPTS ()) != 0)					\
73      ? memory_block_start						\
74      : (GC_ENABLED_P ())						\
75      ? heap_alloc_limit							\
76      : heap_end);							\
77   SET_STACK_GUARD							\
78     ((INTERRUPT_ENABLED_P (INT_Stack_Overflow))				\
79      ? stack_guard							\
80      : STACK_TOP);							\
81 } while (0)
82 
83 #define SET_INTERRUPT_MASK(mask) do					\
84 {									\
85   GRAB_INTERRUPT_REGISTERS ();						\
86   SET_INT_MASK (mask);							\
87   COMPILER_SETUP_INTERRUPT ();						\
88   RELEASE_INTERRUPT_REGISTERS ();					\
89 } while (0)
90 
91 #define REQUEST_INTERRUPT(code) do					\
92 {									\
93   GRAB_INTERRUPT_REGISTERS ();						\
94   SET_INT_CODE (GET_INT_CODE | (code));					\
95   COMPILER_SETUP_INTERRUPT ();						\
96   RELEASE_INTERRUPT_REGISTERS ();					\
97 } while (0)
98 
99 #define CLEAR_INTERRUPT_NOLOCK(code) do					\
100 {									\
101   SET_INT_CODE (GET_INT_CODE &~ (code));				\
102   COMPILER_SETUP_INTERRUPT ();						\
103 } while (0)
104 
105 #define CLEAR_INTERRUPT(code) do					\
106 {									\
107   GRAB_INTERRUPT_REGISTERS ();						\
108   CLEAR_INTERRUPT_NOLOCK (code);					\
109   RELEASE_INTERRUPT_REGISTERS ();					\
110 } while (0)
111 
112 #define INITIALIZE_INTERRUPTS(mask) do					\
113 {									\
114   GRAB_INTERRUPT_REGISTERS ();						\
115   SET_INT_MASK (mask);							\
116   SET_INT_CODE (0);							\
117   COMPILER_SETUP_INTERRUPT ();						\
118   RELEASE_INTERRUPT_REGISTERS ();					\
119 } while (0)
120 
121 #if defined(__OS2__) || defined(__WIN32__)
122    extern void OS_grab_interrupt_registers (void);
123    extern void OS_release_interrupt_registers (void);
124 #  define GRAB_INTERRUPT_REGISTERS() OS_grab_interrupt_registers ()
125 #  define RELEASE_INTERRUPT_REGISTERS() OS_release_interrupt_registers ()
126 #else
127 #  define GRAB_INTERRUPT_REGISTERS()
128 #  define RELEASE_INTERRUPT_REGISTERS()
129 #endif
130