/[cmucl]/src/lisp/FreeBSD-os.c
ViewVC logotype

Contents of /src/lisp/FreeBSD-os.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.18 - (show annotations)
Mon Jul 30 06:44:19 2007 UTC (6 years, 8 months ago) by cshapiro
Branch: MAIN
Changes since 1.17: +13 -8 lines
File MIME type: text/plain
Use errno wrapper functions on FreeBSD so we fetch a thread specific
errno value instead of the global errno value.
1 /*
2 * FreeBSD-os.c. Maybe could be just BSD-os.c
3 * From osf1-os.c,v 1.1 94/03/27 15:30:51 hallgren Exp $
4 *
5 * OS-dependent routines. This file (along with os.h) exports an
6 * OS-independent interface to the operating system VM facilities.
7 * Suprisingly, this interface looks a lot like the Mach interface
8 * (but simpler in some places). For some operating systems, a subset
9 * of these functions will have to be emulated.
10 *
11 * This is the OSF1 version. By Sean Hallgren.
12 * Much hacked by Paul Werkowski
13 * GENCGC support by Douglas Crosher, 1996, 1997.
14 *
15 * $Header: /tiger/var/lib/cvsroots/cmucl/src/lisp/FreeBSD-os.c,v 1.18 2007/07/30 06:44:19 cshapiro Exp $
16 *
17 */
18
19 #include "os.h"
20 #include <sys/file.h>
21 #include <errno.h>
22 #include "./signal.h"
23 #include "arch.h"
24 #include "globals.h"
25 #include "interrupt.h"
26 #include "lispregs.h"
27 #include "internals.h"
28
29 #include <signal.h>
30 /* #include <sys/sysinfo.h> */
31 #include <sys/proc.h>
32 #include <dlfcn.h>
33 #include "validate.h"
34
35 #if defined GENCGC
36 #include "gencgc.h"
37 #endif
38
39 vm_size_t os_vm_page_size;
40
41
42 void
43 os_init(void)
44 {
45 os_vm_page_size = getpagesize();
46 }
47
48 int
49 os_get_errno(void)
50 {
51 return errno;
52 }
53
54 int
55 os_set_errno(int value)
56 {
57 return errno = value;
58 }
59
60 int *
61 sc_reg(ucontext_t *context, int offset)
62 {
63 switch (offset) {
64 case 0:
65 return &context->uc_mcontext.mc_eax;
66 case 2:
67 return &context->uc_mcontext.mc_ecx;
68 case 4:
69 return &context->uc_mcontext.mc_edx;
70 case 6:
71 return &context->uc_mcontext.mc_ebx;
72 case 8:
73 return &context->uc_mcontext.mc_esp;
74 case 10:
75 return &context->uc_mcontext.mc_ebp;
76 case 12:
77 return &context->uc_mcontext.mc_esi;
78 case 14:
79 return &context->uc_mcontext.mc_edi;
80 }
81
82 return (int *) 0;
83 }
84
85 os_vm_address_t os_validate(os_vm_address_t addr, os_vm_size_t len)
86 {
87 int flags = MAP_PRIVATE | MAP_ANON;
88
89 if (addr)
90 flags |= MAP_FIXED;
91
92 addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0);
93
94 if (addr == (os_vm_address_t) - 1) {
95 perror("mmap");
96 return NULL;
97 }
98
99 return addr;
100 }
101
102 void
103 os_invalidate(os_vm_address_t addr, os_vm_size_t len)
104 {
105 if (munmap(addr, len) == -1)
106 perror("munmap");
107 }
108
109 os_vm_address_t
110 os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
111 {
112 addr = mmap(addr, len, OS_VM_PROT_ALL,
113 MAP_PRIVATE | MAP_FILE | MAP_FIXED, fd, (off_t) offset);
114
115 if (addr == (os_vm_address_t) - 1)
116 perror("mmap");
117
118 return addr;
119 }
120
121 void
122 os_flush_icache(os_vm_address_t address, os_vm_size_t length)
123 {
124 }
125
126 void
127 os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
128 {
129 if (mprotect(address, length, prot) == -1)
130 perror("mprotect");
131 }
132
133
134
135 static boolean
136 in_range_p(os_vm_address_t a, lispobj sbeg, size_t slen)
137 {
138 char *beg = (char *) sbeg;
139 char *end = (char *) sbeg + slen;
140 char *adr = (char *) a;
141
142 return adr >= beg && adr < end;
143 }
144
145 boolean valid_addr(os_vm_address_t addr)
146 {
147 os_vm_address_t newaddr;
148
149 newaddr = os_trunc_to_page(addr);
150
151 if (in_range_p(addr, READ_ONLY_SPACE_START, READ_ONLY_SPACE_SIZE)
152 || in_range_p(addr, STATIC_SPACE_START, STATIC_SPACE_SIZE)
153 || in_range_p(addr, DYNAMIC_0_SPACE_START, dynamic_space_size)
154 #ifndef GENCGC
155 || in_range_p(addr, DYNAMIC_1_SPACE_START, dynamic_space_size)
156 #endif
157 || in_range_p(addr, CONTROL_STACK_START, CONTROL_STACK_SIZE)
158 || in_range_p(addr, BINDING_STACK_START, BINDING_STACK_SIZE))
159 return TRUE;
160 return FALSE;
161 }
162
163
164 static void
165 sigbus_handler(int signal, siginfo_t *info, ucontext_t *context)
166 {
167 int page_index;
168
169 #ifdef RED_ZONE_HIT
170 if (os_control_stack_overflow(info->si_addr, context))
171 return;
172 #endif
173
174 #if defined GENCGC
175 if (info->si_code == BUS_PAGE_FAULT) {
176 page_index = find_page_index(info->si_addr);
177
178 /* Check if the fault is within the dynamic space. */
179 if (page_index != -1) {
180 /* Un-protect the page */
181
182 /* The page should have been marked write protected */
183 if (!PAGE_WRITE_PROTECTED(page_index))
184 fprintf(stderr,
185 "*** Sigbus in page not marked as write protected\n");
186
187 os_protect(page_address(page_index), 4096, OS_VM_PROT_ALL);
188 page_table[page_index].flags &= ~PAGE_WRITE_PROTECTED_MASK;
189 page_table[page_index].flags |= PAGE_WRITE_PROTECT_CLEARED_MASK;
190
191 return;
192 }
193 }
194 #endif /* GENCGC */
195
196 interrupt_handle_now(signal, info, context);
197 }
198
199 static void
200 sigsegv_handler(int signal, siginfo_t *info, ucontext_t *context)
201 {
202 interrupt_handle_now(signal, info, context);
203 }
204
205 void
206 os_install_interrupt_handlers(void)
207 {
208 interrupt_install_low_level_handler
209 (SIGSEGV, (void (*)(HANDLER_ARGS)) sigsegv_handler);
210 interrupt_install_low_level_handler
211 (SIGBUS, (void (*)(HANDLER_ARGS)) sigbus_handler);
212 }
213
214 void *
215 os_dlsym(const char *sym_name, lispobj lib_list)
216 {
217 if (lib_list != NIL) {
218 lispobj lib_list_head;
219
220 for (lib_list_head = lib_list;
221 lib_list_head != NIL; lib_list_head = CONS(lib_list_head)->cdr) {
222 struct cons *lib_cons = CONS(CONS(lib_list_head)->car);
223 struct sap *dlhandle = (struct sap *) PTR(lib_cons->car);
224 void *sym_addr = dlsym((void *) dlhandle->pointer, sym_name);
225
226 if (sym_addr)
227 return sym_addr;
228 }
229 }
230
231 return dlsym(RTLD_DEFAULT, sym_name);
232 }

  ViewVC Help
Powered by ViewVC 1.1.5