0.7.6.7:
[sbcl.git] / src / runtime / osf1-os.c
1 /*
2  * This file (along with os.h) exports an OS-independent interface to
3  * the operating system VM facilities. Surprise surprise, this
4  * interface looks a lot like the Mach interface (but simpler in some
5  * places). For some operating systems, a subset of these functions
6  * will have to be emulated.
7  * 
8  * This is the OSF/1 version, based on the Linux version, itself based
9  * on the OSF1 version from CMUCL by Sean Hallgren.  Now _there's_ 
10  * a metacircularity for you ...
11  */
12
13 /*
14  * This software is part of the SBCL system. See the README file for
15  * more information.
16  *
17  * This software is derived from the CMU CL system, which was
18  * written at Carnegie Mellon University and released into the
19  * public domain. The software is in the public domain and is
20  * provided with absolutely no warranty. See the COPYING and CREDITS
21  * files for more information.
22  */
23
24 #include <stdio.h>
25 #include <sys/param.h>
26 #include <sys/file.h>
27 #include "./signal.h"
28 #include "os.h"
29 #include "arch.h"
30 #include "globals.h"
31 #include "interrupt.h"
32 #include "interr.h"
33 #include "lispregs.h"
34 #include "sbcl.h"
35 #include <sys/socket.h>
36 #include <sys/utsname.h>
37 #include <errno.h>
38 #include <sys/sysinfo.h>
39 #include <sys/proc.h>
40 #include <sys/mman.h>
41 #include <machine/hal_sysinfo.h>
42
43 #include <sys/types.h>
44 #include <signal.h>
45 #include <sys/time.h>
46 #include <sys/stat.h>
47 #include <unistd.h>
48
49 #include "validate.h"
50 size_t os_vm_page_size;
51
52 #if defined GENCGC
53 #include "gencgc.h"
54 #endif
55 \f
56
57 void os_init(void)
58 {
59     os_vm_page_size = getpagesize();
60 }
61
62
63 os_vm_address_t
64 os_validate(os_vm_address_t addr, os_vm_size_t len)
65 {
66     int flags = MAP_PRIVATE|MAP_ANONYMOUS;
67     if (addr) flags |= MAP_FIXED;
68     else  flags |= MAP_VARIABLE;
69
70     if((addr=mmap(addr,len,OS_VM_PROT_ALL,flags,-1,0)) == (os_vm_address_t) -1)
71         perror("mmap");
72     
73     return addr;
74 }
75
76 void
77 os_invalidate(os_vm_address_t addr, os_vm_size_t len)
78 {
79     if (munmap(addr,len) == -1) {
80         perror("munmap");
81     }
82 }
83
84 os_vm_address_t
85 os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
86 {
87     addr = mmap(addr, len,
88                 OS_VM_PROT_ALL,
89                 MAP_PRIVATE | MAP_FILE | MAP_FIXED,
90                 fd, (off_t) offset);
91
92     if (addr == MAP_FAILED) {
93         perror("mmap");
94         lose("unexpected mmap(..) failure");
95     }
96
97     return addr;
98 }
99
100 void
101 os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
102 {
103     if (mprotect(address, length, prot) == -1) {
104         perror("mprotect");
105     }
106 }
107
108 boolean
109 is_valid_lisp_addr(os_vm_address_t addr)
110 {
111     int ret;
112     os_vm_address_t newaddr;
113     newaddr=os_trunc_to_page(addr);
114     if((ret=mvalid(newaddr,newaddr-addr+4,OS_VM_PROT_ALL)) == 0)
115         return TRUE;
116     else if(errno==EINVAL)
117         perror("mvalid");
118     return FALSE;
119 }
120 \f
121 /*
122  * any OS-dependent special low-level handling for signals
123  */
124
125
126 static void
127 sigsegv_handler(int signal, siginfo_t *info, void* void_context)
128 {
129     os_context_t *context = arch_os_get_context(&void_context);
130
131     os_vm_address_t addr = arch_get_bad_addr(signal,info,context);
132     
133     if (addr != NULL &&         
134         *os_context_register_addr(context,reg_ALLOC) & (1L<<63)){
135         /* this is lifted from linux-os.c, so violates OOAO */
136         *os_context_register_addr(context,reg_ALLOC) -= (1L<<63);
137         interrupt_handle_pending(context);
138     } else if(((addr>=DYNAMIC_0_SPACE_END) && (addr<DYNAMIC_1_SPACE_START)) ||
139               ((addr>=DYNAMIC_1_SPACE_END) && (addr<CONTROL_STACK_START))){
140         /* there's empty gap between these spaces.  This clause needs
141            review if the spaces are ever juggled to make this untrue */
142         fprintf(stderr, "bad address 0x%p\n",addr);
143         lose("ran off end of dynamic space");
144     } else if (!interrupt_maybe_gc(signal, info, context)) {
145         if(!handle_control_stack_guard_triggered(context,addr))
146             interrupt_handle_now(signal, info, context);
147     }
148 }
149
150
151 void
152 os_install_interrupt_handlers(void)
153 {
154     undoably_install_low_level_interrupt_handler(SIG_MEMORY_FAULT,
155                                                  sigsegv_handler);
156 }
157