af10b8ef80d0e6fd0a9544a8bf27a60760bae127
[projects/cmucl/cmucl.git] / src / lisp / osf1-os.c
1 /*
2  * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/osf1-os.c,v 1.7 2011/09/01 05:18:26 rtoy Exp $
3  *
4  * OS-dependent routines.  This file (along with os.h) exports an
5  * OS-independent interface to the operating system VM facilities.
6  * Suprisingly, this interface looks a lot like the Mach interface
7  * (but simpler in some places).  For some operating systems, a subset
8  * of these functions will have to be emulated.
9  *
10  * This is the OSF1 version.  By Sean Hallgren.
11  *
12  */
13
14 #include <stdio.h>
15 #include <sys/file.h>
16 #include <errno.h>
17 #include <signal.h>
18 #include "os.h"
19 #include "arch.h"
20 #include "interrupt.h"
21 #include "lispregs.h"
22 #include <sys/types.h>
23 #include <sys/sysinfo.h>
24 #include <sys/proc.h>
25
26 vm_size_t os_vm_page_size;
27
28 void
29 os_init0(const char *argv[], const char *envp[])
30 {}
31
32 void
33 os_init(const char *argv[], const char *envp[])
34 {
35     int buf[2] = { SSIN_UACPROC, UAC_SIGBUS | UAC_NOPRINT };
36     int error;
37
38     os_vm_page_size = OS_VM_DEFAULT_PAGESIZE;
39     if (setsysinfo(SSI_NVPAIRS, buf, 1, NULL, NULL) == -1)
40         perror("setsysinfo");
41 }
42
43 os_vm_address_t os_validate(os_vm_address_t addr, os_vm_size_t len)
44 {
45     int flags = MAP_PRIVATE | MAP_ANONYMOUS;
46
47     if (addr)
48         flags |= MAP_FIXED;
49     else
50         flags |= MAP_VARIABLE;
51
52     if ((addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0)) ==
53         (os_vm_address_t) - 1)
54         perror("mmap");
55
56     return addr;
57 }
58
59 void
60 os_invalidate(os_vm_address_t addr, os_vm_size_t len)
61 {
62     if (munmap(addr, len) == -1)
63         perror("munmap");
64 }
65
66 os_vm_address_t
67 os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
68 {
69     if (
70         (addr =
71          mmap(addr, len, OS_VM_PROT_ALL, MAP_PRIVATE | MAP_FILE | MAP_FIXED, fd,
72               (off_t) offset)) == (os_vm_address_t) - 1)
73         perror("mmap");
74
75     return addr;
76 }
77
78 void
79 os_flush_icache(os_vm_address_t address, os_vm_size_t length)
80 {
81 }
82
83 void
84 os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
85 {
86     if (mprotect(address, length, prot) == -1)
87         perror("mprotect");
88 }
89
90 boolean valid_addr(os_vm_address_t addr)
91 {
92     int ret;
93     os_vm_address_t newaddr;
94
95     newaddr = os_trunc_to_page(addr);
96     if ((ret = mvalid(newaddr, newaddr - addr + 4, OS_VM_PROT_ALL)) == 0)
97         return TRUE;
98     else if (errno == EINVAL)
99         perror("mvalid");
100     return FALSE;
101 }
102
103 static void
104 sigbus_handler(int signal, int code, struct sigcontext *context)
105 {
106     context->sc_pc -= 4;        /* pc is +4 on bus error!?!!? */
107     if (arch_get_bad_addr(signal, code, context) &&
108         context->sc_regs[reg_ALLOC] & 2) {
109         context->sc_regs[reg_ALLOC] -= 2;
110         interrupt_handle_pending(context);
111     } else
112         interrupt_handle_now(signal, code, context);
113 }
114
115 static void
116 sigsegv_handler(int signal, int code, struct sigcontext *context)
117 {
118     if (!interrupt_maybe_gc(signal, code, context))
119         interrupt_handle_now(signal, code, context);
120 }
121
122 void
123 os_install_interrupt_handlers(void)
124 {
125     interrupt_install_low_level_handler(SIGSEGV, sigsegv_handler);
126     interrupt_install_low_level_handler(SIGBUS, sigbus_handler);
127 }