Clean up RCS ids
[projects/cmucl/cmucl.git] / src / lisp / hpux-os.c
CommitLineData
c159b7a7 1/*
c159b7a7 2 *
3 * OS-dependent routines. This file (along with os.h) exports an
4 * OS-independent interface to the operating system VM facilities.
5 * Suprisingly, this interface looks a lot like the Mach interface
6 * (but simpler in some places). For some operating systems, a subset
7 * of these functions will have to be emulated.
8 *
9 */
10
11/* Assumptions these routines are based on:
12os_validate: Not called with NULL for an addr.
13os_invalidate: Never called.
14os_map: Files are only mapped at the beginning of one of the areas passed
15 to os_validate.
16os_protect: Only called on an entire region when giving permissions and only
17 called from some point in a segment to the end of the segment
18 when removing them.
19 Only called with all protections or no protections.
20os_zero: Only ever zeroed from some point in a segment to the end of the
21 segment.
22os_allocate_at: Calls to here are disjoint from those around it (the others
23 in os-common.c) since it calls os_validate and the others (in
24 os-common.c) use malloc, etc.
25Note that os_validate does not actually allocate memory until it has to map
26the particular section in.
27*/
28
29/* #define DEBUG */
30
31#include <stdio.h>
32#include <assert.h>
33#include <signal.h>
34#include <sys/file.h>
35#include <unistd.h>
36#include "os.h"
37#include <sys/resource.h>
38#include "interrupt.h"
39#include <netdb.h>
871a4202 40#include <sys/times.h>
7e3a6be6 41#include <errno.h>
c159b7a7 42
9a8c1c2f 43os_vm_size_t os_vm_page_size = (-1);
c159b7a7 44
45#define MAX_SEGMENTS 20
9a8c1c2f 46#define ALLOC_SIZE 0x10000
c159b7a7 47static struct segment {
9a8c1c2f 48 os_vm_address_t base;
49 os_vm_size_t len;
50 os_vm_address_t valid;
51 os_vm_address_t protected;
c159b7a7 52} segments[MAX_SEGMENTS];
53
54void
dafb9e03 55os_init0(const char *argv[], const char *envp[])
56{}
57
58void
0f0aed07 59os_init(const char *argv[], const char *envp[])
c159b7a7 60{
9a8c1c2f 61 int i;
62
63 os_vm_page_size = sysconf(_SC_PAGE_SIZE);
64 for (i = 0; i < MAX_SEGMENTS; i++)
65 segments[i].len = 0;
c159b7a7 66}
67
68
9a8c1c2f 69os_vm_address_t os_validate(os_vm_address_t addr, os_vm_size_t len)
c159b7a7 70{
9a8c1c2f 71 int fd, i;
72 caddr_t ret;
c159b7a7 73
9a8c1c2f 74 addr = os_trunc_to_page(addr);
75 len = os_round_up_size_to_page(len);
c159b7a7 76
77#ifdef DEBUG
9a8c1c2f 78 printf("os_validate: addr: 0x%X, len: 0x%X, end: 0x%X\n", addr, len,
79 addr + len);
80#endif
81 assert(addr != NULL);
82 assert(len != 0);
c159b7a7 83
9a8c1c2f 84 for (i = 0; i < MAX_SEGMENTS; i++)
85 if (segments[i].len == 0)
86 break;
c159b7a7 87
9a8c1c2f 88 assert(i != MAX_SEGMENTS);
c159b7a7 89
9a8c1c2f 90 segments[i].base = addr;
91 segments[i].len = len;
92 segments[i].valid = addr;
93 segments[i].protected = addr + len;
94 return addr;
c159b7a7 95}
96
97void
98os_invalidate(os_vm_address_t addr, os_vm_size_t len)
99{
9a8c1c2f 100 assert(FALSE);
c159b7a7 101}
102
103os_vm_address_t
104os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
105{
9a8c1c2f 106 int i;
c159b7a7 107
9a8c1c2f 108 addr = os_trunc_to_page(addr);
109 len = os_round_up_size_to_page(len);
c159b7a7 110
9a8c1c2f 111 if (mmap(addr, len, OS_VM_PROT_ALL, MAP_FILE | MAP_FIXED | MAP_PRIVATE, fd,
112 (off_t) offset) == (os_vm_address_t) - 1) {
113 perror("mmap");
114 return NULL;
115 }
c159b7a7 116
9a8c1c2f 117 for (i = 0; i < MAX_SEGMENTS; i++)
118 if (segments[i].len != 0 && segments[i].base == addr)
119 break;
c159b7a7 120
9a8c1c2f 121 assert(i != MAX_SEGMENTS);
122 assert(segments[i].valid == addr);
c159b7a7 123
9a8c1c2f 124 segments[i].valid = addr + len;
c159b7a7 125#ifdef DEBUG
9a8c1c2f 126 printf("os_map: addr: 0x%X, len: 0x%X, end: 0x%X\n", addr, len, addr + len);
c159b7a7 127#endif
9a8c1c2f 128 return addr;
c159b7a7 129}
130
131void
132os_flush_icache(os_vm_address_t address, os_vm_size_t length)
133{
9a8c1c2f 134 sanctify_for_execution(address, length);
c159b7a7 135}
136
137void
138os_protect(os_vm_address_t addr, os_vm_size_t len, os_vm_prot_t prot)
139{
9a8c1c2f 140 int i;
141
142 addr = os_trunc_to_page(addr);
143 len = os_round_up_size_to_page(len);
144
145 for (i = 0; i < MAX_SEGMENTS; i++)
146 if (segments[i].base <= addr
147 && addr < segments[i].base + segments[i].len) break;
148
149 assert(i != MAX_SEGMENTS);
150
151 if (prot) {
152 assert(segments[i].base == addr && segments[i].len == len);
153 segments[i].protected = addr + len;
154 } else {
155 assert(segments[i].protected == addr + len);
156 segments[i].protected = addr;
c159b7a7 157 }
9a8c1c2f 158
159 if (addr < segments[i].valid)
160 if (mprotect(addr, segments[i].valid - addr, prot) == -1) {
161 perror("mprotect");
162 printf("segments[i].base: 0x%X\n", segments[i].base);
163 printf("segments[i].len: 0x%X\n", segments[i].len);
164 printf("segments[i].valid: 0x%X\n", segments[i].valid);
165 printf("addr: 0x%X, segments[i].valid-addr: 0x%X\n", addr,
166 segments[i].valid - addr);
167 printf("prot: 0x%X, len 0x%X\n", prot, len);
168 assert(FALSE);
169 }
c159b7a7 170#ifdef DEBUG
9a8c1c2f 171 printf("os_protect: addr: 0x%X, len: 0x%X, end: 0x%X, prot 0x%X\n",
172 addr, len, addr + len, prot);
c159b7a7 173#endif
174}
175
9a8c1c2f 176boolean valid_addr(os_vm_address_t addr)
c159b7a7 177{
9a8c1c2f 178 int i;
c159b7a7 179
9a8c1c2f 180 for (i = 0; i < MAX_SEGMENTS; i++)
181 if (segments[i].base <= addr
182 && addr < segments[i].base + segments[i].len) return TRUE;
183 return FALSE;
c159b7a7 184}
185
186void
187segv_handler(int signal, int code, struct sigcontext *context)
188{
9a8c1c2f 189 int i;
190 os_vm_address_t addr, nvalid;
191
192 sigsetmask(BLOCKABLE);
193
194 addr = (os_vm_address_t) context->sc_sl.sl_ss.ss_cr21; /* verify this!!! */
195 for (i = 0; i < MAX_SEGMENTS; i++)
196 if (segments[i].len != 0 && segments[i].base <= addr &&
197 addr < segments[i].base + segments[i].len)
198 break;
199 if (i == MAX_SEGMENTS || addr < segments[i].valid)
200 interrupt_handle_now(signal, code, context);
201 else if (segments[i].protected <= addr) {
202 if (!interrupt_maybe_gc(signal, code, context))
203 interrupt_handle_now(signal, code, context);
204 } else {
205 nvalid =
206 ((os_vm_address_t)
207 (((long) (addr + ALLOC_SIZE)) & ~((long) (ALLOC_SIZE - 1))));
208 if (nvalid > segments[i].protected)
209 nvalid = segments[i].protected;
c159b7a7 210
211#ifdef DEBUG
9a8c1c2f 212 printf("Mapping: addr: 0x%08x, old: 0x%08x, new: 0x%08x\n",
213 addr, segments[i].valid, nvalid);
c159b7a7 214#endif
215
9a8c1c2f 216 if (mmap(segments[i].valid, nvalid - segments[i].valid,
217 OS_VM_PROT_ALL, MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, -1,
218 0) == (os_vm_address_t) - 1) {
219 perror("mmap");
220 printf("segments[i].base: 0x%X\n", segments[i].base);
221 printf("segments[i].len: 0x%X\n", segments[i].len);
222 printf("segments[i].valid: 0x%X\n", segments[i].valid);
223 printf("segments[i].protected: 0x%X\n", segments[i].protected);
224 printf("nvalid: 0x%X\n", nvalid);
225 printf("nvalid-segments[i].valid: 0x%X\n",
226 nvalid - segments[i].valid);
227 assert(FALSE);
228 }
229 segments[i].valid = nvalid;
c159b7a7 230 }
c159b7a7 231}
232
233void
234sigbus_handler(int signal, int code, struct sigcontext *context)
235{
236#ifdef DEBUG
9a8c1c2f 237 printf("Bus Error at 0x%X\n", context->sc_sl.sl_ss.ss_cr21);
c159b7a7 238#endif
239
9a8c1c2f 240 if (!interrupt_maybe_gc(signal, code, context))
241 interrupt_handle_now(signal, code, context);
c159b7a7 242}
243
244void
b8d0dfaf 245os_install_interrupt_handlers(void)
c159b7a7 246{
9a8c1c2f 247 interrupt_install_low_level_handler(SIGSEGV, segv_handler);
248 interrupt_install_low_level_handler(SIGBUS, sigbus_handler);
c159b7a7 249}
250
251void
9a8c1c2f 252os_zero(os_vm_address_t addr, os_vm_size_t length)
c159b7a7 253{
254 os_vm_address_t block_start;
255 os_vm_size_t block_size;
256 int i;
257
34b793ce 258#ifdef PRINTNOISE
9a8c1c2f 259 fprintf(stderr, "os_zero: addr: 0x%08x, len: 0x%08x, end: 0x%X\n", addr,
260 length, addr + length);
c159b7a7 261#endif
262
9a8c1c2f 263 block_start = os_round_up_to_page(addr);
264
265 length -= block_start - addr;
266 block_size = os_trunc_size_to_page(length);
c159b7a7 267
9a8c1c2f 268 if (block_start > addr)
269 memset((char *) addr, 0, block_start - addr);
270 if (block_size < length)
271 assert(FALSE);
c159b7a7 272
c159b7a7 273 if (block_size != 0) {
274 /* Now deallocate and allocate the block so that it */
275 /* faults in zero-filled. */
276
9a8c1c2f 277 for (i = 0; i < MAX_SEGMENTS; i++)
278 if (segments[i].base <= block_start &&
279 block_start < segments[i].base + segments[i].len)
280 break;
281 assert(i != MAX_SEGMENTS);
282 assert(block_start + block_size == segments[i].base + segments[i].len);
283
284 if (segments[i].valid > block_start) {
285 if (munmap(block_start, segments[i].valid - block_start) == -1) {
286 perror("munmap");
287 return;
288 }
289 segments[i].valid = block_start;
c159b7a7 290 }
291 }
292}
293
9a8c1c2f 294os_vm_address_t os_allocate(os_vm_size_t len)
c159b7a7 295{
9a8c1c2f 296 return (os_vm_address_t) malloc(len);
c159b7a7 297}
298
9a8c1c2f 299os_vm_address_t os_allocate_at(os_vm_address_t addr, os_vm_size_t len)
c159b7a7 300{
9a8c1c2f 301 return os_validate(addr, len);
c159b7a7 302}
303
304void
9a8c1c2f 305os_deallocate(os_vm_address_t addr, os_vm_size_t len)
c159b7a7 306{
9a8c1c2f 307 free(addr);
c159b7a7 308}
309
310os_vm_address_t
9a8c1c2f 311os_reallocate(os_vm_address_t addr, os_vm_size_t old_len, os_vm_size_t len)
c159b7a7 312{
9a8c1c2f 313 addr = (os_vm_address_t) realloc(addr, len);
314 assert(addr != NULL);
315 return addr;
c159b7a7 316}
317
9a8c1c2f 318int
319getrusage(int who, struct rusage *rusage)
c159b7a7 320{
9a8c1c2f 321 static long ticks_per_sec = 0;
322 static long usec_per_tick = 0;
323 struct tms buf;
324 clock_t uticks, sticks;
325
326 memset(rusage, 0, sizeof(struct rusage));
327
328 if (ticks_per_sec == 0) {
329 ticks_per_sec = sysconf(_SC_CLK_TCK);
330 usec_per_tick = 1000000 / ticks_per_sec;
331 }
332
333 if (times(&buf) == -1)
334 return -1;
335
336 if (who == RUSAGE_SELF) {
337 uticks = buf.tms_utime;
338 sticks = buf.tms_stime;
339 } else if (who == RUSAGE_CHILDREN) {
340 uticks = buf.tms_utime;
341 sticks = buf.tms_stime;
342 } else {
343 errno = EINVAL;
344 return -1;
345 }
346
347 rusage->ru_utime.tv_sec = uticks / ticks_per_sec;
348 rusage->ru_utime.tv_usec = (uticks % ticks_per_sec) * usec_per_tick;
349 rusage->ru_stime.tv_sec = sticks / ticks_per_sec;
350 rusage->ru_stime.tv_usec = (sticks % ticks_per_sec) * usec_per_tick;
351
352 return 0;
c159b7a7 353}
354
355int
356getdtablesize(void)
357{
9a8c1c2f 358 struct rlimit rlp;
359
360 assert(getrlimit(RLIMIT_NOFILE, &rlp) == 0);
361 return rlp.rlim_cur;
c159b7a7 362}
363
364unsigned long
365gethostid(void)
366{
9a8c1c2f 367 char hostname[256];
368 struct hostent *hostent;
369 static unsigned long addr = NULL;
c159b7a7 370
9a8c1c2f 371 if (addr)
372 return addr;
c159b7a7 373
9a8c1c2f 374 if (gethostname(hostname, sizeof(hostname)) == -1) {
375 perror("gethostname");
376 return 0;
377 }
c159b7a7 378
9a8c1c2f 379 hostent = gethostbyname(hostname);
380 if (hostent == NULL) {
381 perror("gethostbyname");
382 return 0;
383 }
c159b7a7 384
9a8c1c2f 385 addr = ((unsigned char *) (hostent->h_addr))[0] << 24 |
386 ((unsigned char *) (hostent->h_addr))[1] << 16 |
387 ((unsigned char *) (hostent->h_addr))[2] << 8 |
388 ((unsigned char *) (hostent->h_addr))[3];
c159b7a7 389
9a8c1c2f 390 return addr;
c159b7a7 391}
679e7f08 392
393int
394getpagesize(void)
395{
9a8c1c2f 396 return os_vm_page_size;
679e7f08 397}