Skip to content
Snippets Groups Projects
Commit c159b7a7 authored by hallgren's avatar hallgren
Browse files

Initial revision

parent 55bee36e
No related branches found
No related tags found
No related merge requests found
/*
* $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;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment