2 * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/hpux-os.c,v 1.11 2011/09/01 05:18:26 rtoy Exp $
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.
12 /* Assumptions these routines are based on:
13 os_validate: Not called with NULL for an addr.
14 os_invalidate: Never called.
15 os_map: Files are only mapped at the beginning of one of the areas passed
17 os_protect: Only called on an entire region when giving permissions and only
18 called from some point in a segment to the end of the segment
20 Only called with all protections or no protections.
21 os_zero: Only ever zeroed from some point in a segment to the end of the
23 os_allocate_at: Calls to here are disjoint from those around it (the others
24 in os-common.c) since it calls os_validate and the others (in
25 os-common.c) use malloc, etc.
26 Note that os_validate does not actually allocate memory until it has to map
27 the particular section in.
38 #include <sys/resource.h>
39 #include "interrupt.h"
41 #include <sys/times.h>
44 os_vm_size_t os_vm_page_size = (-1);
46 #define MAX_SEGMENTS 20
47 #define ALLOC_SIZE 0x10000
48 static struct segment {
51 os_vm_address_t valid;
52 os_vm_address_t protected;
53 } segments[MAX_SEGMENTS];
56 os_init0(const char *argv[], const char *envp[])
60 os_init(const char *argv[], const char *envp[])
64 os_vm_page_size = sysconf(_SC_PAGE_SIZE);
65 for (i = 0; i < MAX_SEGMENTS; i++)
70 os_vm_address_t os_validate(os_vm_address_t addr, os_vm_size_t len)
75 addr = os_trunc_to_page(addr);
76 len = os_round_up_size_to_page(len);
79 printf("os_validate: addr: 0x%X, len: 0x%X, end: 0x%X\n", addr, len,
85 for (i = 0; i < MAX_SEGMENTS; i++)
86 if (segments[i].len == 0)
89 assert(i != MAX_SEGMENTS);
91 segments[i].base = addr;
92 segments[i].len = len;
93 segments[i].valid = addr;
94 segments[i].protected = addr + len;
99 os_invalidate(os_vm_address_t addr, os_vm_size_t len)
105 os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
109 addr = os_trunc_to_page(addr);
110 len = os_round_up_size_to_page(len);
112 if (mmap(addr, len, OS_VM_PROT_ALL, MAP_FILE | MAP_FIXED | MAP_PRIVATE, fd,
113 (off_t) offset) == (os_vm_address_t) - 1) {
118 for (i = 0; i < MAX_SEGMENTS; i++)
119 if (segments[i].len != 0 && segments[i].base == addr)
122 assert(i != MAX_SEGMENTS);
123 assert(segments[i].valid == addr);
125 segments[i].valid = addr + len;
127 printf("os_map: addr: 0x%X, len: 0x%X, end: 0x%X\n", addr, len, addr + len);
133 os_flush_icache(os_vm_address_t address, os_vm_size_t length)
135 sanctify_for_execution(address, length);
139 os_protect(os_vm_address_t addr, os_vm_size_t len, os_vm_prot_t prot)
143 addr = os_trunc_to_page(addr);
144 len = os_round_up_size_to_page(len);
146 for (i = 0; i < MAX_SEGMENTS; i++)
147 if (segments[i].base <= addr
148 && addr < segments[i].base + segments[i].len) break;
150 assert(i != MAX_SEGMENTS);
153 assert(segments[i].base == addr && segments[i].len == len);
154 segments[i].protected = addr + len;
156 assert(segments[i].protected == addr + len);
157 segments[i].protected = addr;
160 if (addr < segments[i].valid)
161 if (mprotect(addr, segments[i].valid - addr, prot) == -1) {
163 printf("segments[i].base: 0x%X\n", segments[i].base);
164 printf("segments[i].len: 0x%X\n", segments[i].len);
165 printf("segments[i].valid: 0x%X\n", segments[i].valid);
166 printf("addr: 0x%X, segments[i].valid-addr: 0x%X\n", addr,
167 segments[i].valid - addr);
168 printf("prot: 0x%X, len 0x%X\n", prot, len);
172 printf("os_protect: addr: 0x%X, len: 0x%X, end: 0x%X, prot 0x%X\n",
173 addr, len, addr + len, prot);
177 boolean valid_addr(os_vm_address_t addr)
181 for (i = 0; i < MAX_SEGMENTS; i++)
182 if (segments[i].base <= addr
183 && addr < segments[i].base + segments[i].len) return TRUE;
188 segv_handler(int signal, int code, struct sigcontext *context)
191 os_vm_address_t addr, nvalid;
193 sigsetmask(BLOCKABLE);
195 addr = (os_vm_address_t) context->sc_sl.sl_ss.ss_cr21; /* verify this!!! */
196 for (i = 0; i < MAX_SEGMENTS; i++)
197 if (segments[i].len != 0 && segments[i].base <= addr &&
198 addr < segments[i].base + segments[i].len)
200 if (i == MAX_SEGMENTS || addr < segments[i].valid)
201 interrupt_handle_now(signal, code, context);
202 else if (segments[i].protected <= addr) {
203 if (!interrupt_maybe_gc(signal, code, context))
204 interrupt_handle_now(signal, code, context);
208 (((long) (addr + ALLOC_SIZE)) & ~((long) (ALLOC_SIZE - 1))));
209 if (nvalid > segments[i].protected)
210 nvalid = segments[i].protected;
213 printf("Mapping: addr: 0x%08x, old: 0x%08x, new: 0x%08x\n",
214 addr, segments[i].valid, nvalid);
217 if (mmap(segments[i].valid, nvalid - segments[i].valid,
218 OS_VM_PROT_ALL, MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, -1,
219 0) == (os_vm_address_t) - 1) {
221 printf("segments[i].base: 0x%X\n", segments[i].base);
222 printf("segments[i].len: 0x%X\n", segments[i].len);
223 printf("segments[i].valid: 0x%X\n", segments[i].valid);
224 printf("segments[i].protected: 0x%X\n", segments[i].protected);
225 printf("nvalid: 0x%X\n", nvalid);
226 printf("nvalid-segments[i].valid: 0x%X\n",
227 nvalid - segments[i].valid);
230 segments[i].valid = nvalid;
235 sigbus_handler(int signal, int code, struct sigcontext *context)
238 printf("Bus Error at 0x%X\n", context->sc_sl.sl_ss.ss_cr21);
241 if (!interrupt_maybe_gc(signal, code, context))
242 interrupt_handle_now(signal, code, context);
246 os_install_interrupt_handlers(void)
248 interrupt_install_low_level_handler(SIGSEGV, segv_handler);
249 interrupt_install_low_level_handler(SIGBUS, sigbus_handler);
253 os_zero(os_vm_address_t addr, os_vm_size_t length)
255 os_vm_address_t block_start;
256 os_vm_size_t block_size;
260 fprintf(stderr, "os_zero: addr: 0x%08x, len: 0x%08x, end: 0x%X\n", addr,
261 length, addr + length);
264 block_start = os_round_up_to_page(addr);
266 length -= block_start - addr;
267 block_size = os_trunc_size_to_page(length);
269 if (block_start > addr)
270 memset((char *) addr, 0, block_start - addr);
271 if (block_size < length)
274 if (block_size != 0) {
275 /* Now deallocate and allocate the block so that it */
276 /* faults in zero-filled. */
278 for (i = 0; i < MAX_SEGMENTS; i++)
279 if (segments[i].base <= block_start &&
280 block_start < segments[i].base + segments[i].len)
282 assert(i != MAX_SEGMENTS);
283 assert(block_start + block_size == segments[i].base + segments[i].len);
285 if (segments[i].valid > block_start) {
286 if (munmap(block_start, segments[i].valid - block_start) == -1) {
290 segments[i].valid = block_start;
295 os_vm_address_t os_allocate(os_vm_size_t len)
297 return (os_vm_address_t) malloc(len);
300 os_vm_address_t os_allocate_at(os_vm_address_t addr, os_vm_size_t len)
302 return os_validate(addr, len);
306 os_deallocate(os_vm_address_t addr, os_vm_size_t len)
312 os_reallocate(os_vm_address_t addr, os_vm_size_t old_len, os_vm_size_t len)
314 addr = (os_vm_address_t) realloc(addr, len);
315 assert(addr != NULL);
320 getrusage(int who, struct rusage *rusage)
322 static long ticks_per_sec = 0;
323 static long usec_per_tick = 0;
325 clock_t uticks, sticks;
327 memset(rusage, 0, sizeof(struct rusage));
329 if (ticks_per_sec == 0) {
330 ticks_per_sec = sysconf(_SC_CLK_TCK);
331 usec_per_tick = 1000000 / ticks_per_sec;
334 if (times(&buf) == -1)
337 if (who == RUSAGE_SELF) {
338 uticks = buf.tms_utime;
339 sticks = buf.tms_stime;
340 } else if (who == RUSAGE_CHILDREN) {
341 uticks = buf.tms_utime;
342 sticks = buf.tms_stime;
348 rusage->ru_utime.tv_sec = uticks / ticks_per_sec;
349 rusage->ru_utime.tv_usec = (uticks % ticks_per_sec) * usec_per_tick;
350 rusage->ru_stime.tv_sec = sticks / ticks_per_sec;
351 rusage->ru_stime.tv_usec = (sticks % ticks_per_sec) * usec_per_tick;
361 assert(getrlimit(RLIMIT_NOFILE, &rlp) == 0);
369 struct hostent *hostent;
370 static unsigned long addr = NULL;
375 if (gethostname(hostname, sizeof(hostname)) == -1) {
376 perror("gethostname");
380 hostent = gethostbyname(hostname);
381 if (hostent == NULL) {
382 perror("gethostbyname");
386 addr = ((unsigned char *) (hostent->h_addr))[0] << 24 |
387 ((unsigned char *) (hostent->h_addr))[1] << 16 |
388 ((unsigned char *) (hostent->h_addr))[2] << 8 |
389 ((unsigned char *) (hostent->h_addr))[3];
397 return os_vm_page_size;