Commit c159b7a7 authored by hallgren's avatar hallgren
Browse files

Initial revision

parent 55bee36e
/*
* $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/hpux-os.c,v 1.1 1993/07/27 16:02:04 hallgren Exp $
*
* OS-dependent routines. This file (along with os.h) exports an
* OS-independent interface to the operating system VM facilities.
* Suprisingly, this interface looks a lot like the Mach interface
* (but simpler in some places). For some operating systems, a subset
* of these functions will have to be emulated.
*
*/
/* Assumptions these routines are based on:
os_validate: Not called with NULL for an addr.
os_invalidate: Never called.
os_map: Files are only mapped at the beginning of one of the areas passed
to os_validate.
os_protect: Only called on an entire region when giving permissions and only
called from some point in a segment to the end of the segment
when removing them.
Only called with all protections or no protections.
os_zero: Only ever zeroed from some point in a segment to the end of the
segment.
os_allocate_at: Calls to here are disjoint from those around it (the others
in os-common.c) since it calls os_validate and the others (in
os-common.c) use malloc, etc.
Note that os_validate does not actually allocate memory until it has to map
the particular section in.
*/
/* #define DEBUG */
#include <stdio.h>
#include <assert.h>
#include <signal.h>
#include <sys/file.h>
#include <unistd.h>
#include "os.h"
#include <sys/resource.h>
#include "interrupt.h"
#include <netdb.h>
os_vm_size_t os_vm_page_size=(-1);
#define MAX_SEGMENTS 20
#define ALLOC_SIZE 0x10000
static struct segment {
os_vm_address_t base;
os_vm_size_t len;
os_vm_address_t valid;
os_vm_address_t protected;
} segments[MAX_SEGMENTS];
void
os_init()
{
int i;
os_vm_page_size=sysconf(_SC_PAGE_SIZE);
for(i=0;i<MAX_SEGMENTS;i++)
segments[i].len=0;
}
os_vm_address_t
os_validate(os_vm_address_t addr, os_vm_size_t len)
{
int fd,i;
caddr_t ret;
addr=os_trunc_to_page(addr);
len=os_round_up_size_to_page(len);
#ifdef DEBUG
printf("os_validate: addr: 0x%X, len: 0x%X, end: 0x%X\n",addr,len,addr+len);
#endif
assert(addr!=NULL);
assert(len!=0);
for(i=0;i<MAX_SEGMENTS;i++)
if(segments[i].len==0) break;
assert(i!=MAX_SEGMENTS);
segments[i].base=addr;
segments[i].len=len;
segments[i].valid=addr;
segments[i].protected=addr+len;
return addr;
}
void
os_invalidate(os_vm_address_t addr, os_vm_size_t len)
{
assert(FALSE);
}
os_vm_address_t
os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
{
int i;
addr=os_trunc_to_page(addr);
len=os_round_up_size_to_page(len);
if(mmap(addr,len,OS_VM_PROT_ALL,MAP_FILE|MAP_FIXED|MAP_PRIVATE,fd,
(off_t)offset) == (os_vm_address_t)-1) {
perror("mmap");
return NULL;
}
for(i=0;i<MAX_SEGMENTS;i++)
if(segments[i].len!=0 && segments[i].base==addr) break;
assert(i!=MAX_SEGMENTS);
assert(segments[i].valid==addr);
segments[i].valid=addr+len;
#ifdef DEBUG
printf("os_map: addr: 0x%X, len: 0x%X, end: 0x%X\n",addr,len,addr+len);
#endif
return addr;
}
void
os_flush_icache(os_vm_address_t address, os_vm_size_t length)
{
sanctify_for_execution(address,length);
}
void
os_protect(os_vm_address_t addr, os_vm_size_t len, os_vm_prot_t prot)
{
int i;
addr=os_trunc_to_page(addr);
len=os_round_up_size_to_page(len);
for(i=0;i<MAX_SEGMENTS;i++)
if(segments[i].base<=addr && addr<segments[i].base+segments[i].len)
break;
assert(i!=MAX_SEGMENTS);
if(prot) {
assert(segments[i].base==addr && segments[i].len==len);
segments[i].protected=addr+len;
} else {
assert(segments[i].protected==addr+len);
segments[i].protected=addr;
}
if(addr<segments[i].valid)
if(mprotect(addr,segments[i].valid-addr,prot) == -1) {
perror("mprotect");
printf("segments[i].base: 0x%X\n",segments[i].base);
printf("segments[i].len: 0x%X\n",segments[i].len);
printf("segments[i].valid: 0x%X\n",segments[i].valid);
printf("addr: 0x%X, segments[i].valid-addr: 0x%X\n",addr,
segments[i].valid-addr);
printf("prot: 0x%X, len 0x%X\n",prot,len);
assert(FALSE);
}
#ifdef DEBUG
printf("os_protect: addr: 0x%X, len: 0x%X, end: 0x%X, prot 0x%X\n",
addr,len,addr+len,prot);
#endif
}
boolean
valid_addr(os_vm_address_t addr)
{
int i;
for(i=0;i<MAX_SEGMENTS;i++)
if(segments[i].base<=addr && addr<segments[i].base+segments[i].len)
return TRUE;
return FALSE;
}
void
segv_handler(int signal, int code, struct sigcontext *context)
{
int i;
os_vm_address_t addr,nvalid;
sigsetmask(BLOCKABLE);
addr=(os_vm_address_t)context->sc_sl.sl_ss.ss_cr21; /* verify this!!! */
for(i=0;i<MAX_SEGMENTS;i++)
if(segments[i].len!=0 && segments[i].base<=addr &&
addr<segments[i].base+segments[i].len)
break;
if(i==MAX_SEGMENTS || addr<segments[i].valid)
interrupt_handle_now(signal,code,context);
else if(segments[i].protected<=addr) {
if(!interrupt_maybe_gc(signal,code,context))
interrupt_handle_now(signal,code,context);
} else {
nvalid=((os_vm_address_t)(((long)(addr+ALLOC_SIZE))&~((long)(ALLOC_SIZE-1))));
if(nvalid>segments[i].protected) nvalid=segments[i].protected;
#ifdef DEBUG
printf("Mapping: addr: 0x%08x, old: 0x%08x, new: 0x%08x\n",
addr,segments[i].valid,nvalid);
#endif
if(mmap(segments[i].valid,nvalid-segments[i].valid,
OS_VM_PROT_ALL,MAP_ANONYMOUS|MAP_FIXED|MAP_PRIVATE,-1,0) ==
(os_vm_address_t)-1) {
perror("mmap");
printf("segments[i].base: 0x%X\n",segments[i].base);
printf("segments[i].len: 0x%X\n",segments[i].len);
printf("segments[i].valid: 0x%X\n",segments[i].valid);
printf("segments[i].protected: 0x%X\n",segments[i].protected);
printf("nvalid: 0x%X\n",nvalid);
printf("nvalid-segments[i].valid: 0x%X\n",nvalid-segments[i].valid);
assert(FALSE);
}
segments[i].valid=nvalid;
}
}
void
sigbus_handler(int signal, int code, struct sigcontext *context)
{
#ifdef DEBUG
printf("Bus Error at 0x%X\n",context->sc_sl.sl_ss.ss_cr21);
#endif
if(!interrupt_maybe_gc(signal, code, context))
interrupt_handle_now(signal, code, context);
}
void
os_install_interrupt_handlers()
{
interrupt_install_low_level_handler(SIGSEGV,segv_handler);
interrupt_install_low_level_handler(SIGBUS,sigbus_handler);
}
void
os_zero(os_vm_address_t addr,os_vm_size_t length)
{
os_vm_address_t block_start;
os_vm_size_t block_size;
int i;
#ifdef DEBUG
fprintf(stderr,"os_zero: addr: 0x%08x, len: 0x%08x, end: 0x%X\n",addr,
length,addr+length);
#endif
block_start=os_round_up_to_page(addr);
length-=block_start-addr;
block_size=os_trunc_size_to_page(length);
if(block_start>addr)
bzero((char *)addr,block_start-addr);
if(block_size<length)
assert(FALSE);
if (block_size != 0) {
/* Now deallocate and allocate the block so that it */
/* faults in zero-filled. */
for(i=0;i<MAX_SEGMENTS;i++)
if(segments[i].base<=block_start &&
block_start<segments[i].base+segments[i].len)
break;
assert(i!=MAX_SEGMENTS);
assert(block_start+block_size==segments[i].base+segments[i].len);
if(segments[i].valid>block_start) {
if(munmap(block_start,segments[i].valid-block_start)==-1) {
perror("munmap");
return;
}
segments[i].valid=block_start;
}
}
}
os_vm_address_t
os_allocate(os_vm_size_t len)
{
return (os_vm_address_t) malloc(len);
}
os_vm_address_t
os_allocate_at(os_vm_address_t addr, os_vm_size_t len)
{
return os_validate(addr, len);
}
void
os_deallocate(os_vm_address_t addr,os_vm_size_t len)
{
free(addr);
}
os_vm_address_t
os_reallocate(os_vm_address_t addr, os_vm_size_t old_len,
os_vm_size_t len)
{
addr=(os_vm_address_t) realloc(addr,len);
assert(addr!=NULL);
return addr;
}
void
getrusage(int who,struct rusage *rusage)
{
bzero(rusage,sizeof(struct rusage));
}
int
getdtablesize(void)
{
struct rlimit rlp;
assert(getrlimit(RLIMIT_NOFILE,&rlp)==0);
return rlp.rlim_cur;
}
unsigned long
gethostid(void)
{
char hostname[256];
struct hostent *hostent;
static unsigned long addr=NULL;
if(addr) return addr;
if(gethostname(hostname, sizeof(hostname)) == -1) {
perror("gethostname");
return 0;
}
hostent = gethostbyname(hostname);
if(hostent == NULL) {
perror("gethostbyname");
return 0;
}
addr = ((unsigned char *)(hostent->h_addr))[0] << 24 |
((unsigned char *)(hostent->h_addr))[1] << 16 |
((unsigned char *)(hostent->h_addr))[2] << 8 |
((unsigned char *)(hostent->h_addr))[3];
return addr;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment