From f4ef6a570b44b51d250028672fa84fd0ac693eab Mon Sep 17 00:00:00 2001 From: dtc <dtc> Date: Thu, 4 Sep 1997 08:46:02 +0000 Subject: [PATCH] Solaris OS dependent routines. --- lisp/solaris-os.c | 380 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 380 insertions(+) create mode 100644 lisp/solaris-os.c diff --git a/lisp/solaris-os.c b/lisp/solaris-os.c new file mode 100644 index 000000000..a6e274d79 --- /dev/null +++ b/lisp/solaris-os.c @@ -0,0 +1,380 @@ +/* + * $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/solaris-os.c,v 1.1 1997/09/04 08:46:02 dtc 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. + * + * This is an experimental Solaris version based on sunos-os.c but + * without the VM hack of unmapped pages for the GC trigger which + * caused trouble when system calls were passed unmapped pages. + * + */ + +#define DEBUG + +#include <stdio.h> + +#include <signal.h> +#include <sys/file.h> + +#include <unistd.h> +#include <errno.h> +#include <sys/param.h> +#define OS_PROTERR SEGV_ACCERR +#define OS_MAPERR SEGV_MAPERR +#define OS_HASERRNO(code) ((code)->si_errno != 0) +#define OS_ERRNO(code) ((code)->si_errno) + +#include "os.h" + +/* block size must be larger than the system page size */ +#define SPARSE_BLOCK_SIZE (1<<15) +#define SPARSE_SIZE_MASK (SPARSE_BLOCK_SIZE-1) + +#define PROT_DEFAULT OS_VM_PROT_ALL + +#define OFFSET_NONE ((os_vm_offset_t)(~0)) + +#define EMPTYFILE "/tmp/empty" +#define ZEROFILE "/dev/zero" + +#define INITIAL_MAX_SEGS 32 +#define GROW_MAX_SEGS 16 + +extern char *getenv(); + +/* ---------------------------------------------------------------- */ + +#define ADJ_OFFSET(off,adj) (((off)==OFFSET_NONE) ? OFFSET_NONE : ((off)+(adj))) + +long os_vm_page_size=(-1); +static long os_real_page_size=(-1); + +static int zero_fd=(-1), empty_fd=(-1); + +static os_vm_size_t real_page_size_difference=0; + +static void os_init_bailout(arg) +char *arg; +{ + char buf[500]; + sprintf(buf,"os_init: %s",arg); + perror(buf); + exit(1); +} + +void os_init() +{ + char *empty_file=getenv("CMUCL_EMPTYFILE"); + + if(empty_file==NULL) + empty_file=EMPTYFILE; + + empty_fd=open(empty_file,O_RDONLY|O_CREAT); + if(empty_fd<0) + os_init_bailout(empty_file); + unlink(empty_file); + + zero_fd=open(ZEROFILE,O_RDONLY); + if(zero_fd<0) + os_init_bailout(ZEROFILE); + + os_vm_page_size = os_real_page_size = sysconf(_SC_PAGESIZE); + + if(os_vm_page_size>OS_VM_DEFAULT_PAGESIZE){ + fprintf(stderr,"os_init: Pagesize too large (%d > %d)\n", + os_vm_page_size,OS_VM_DEFAULT_PAGESIZE); + exit(1); + }else{ + /* + * we do this because there are apparently dependencies on + * the pagesize being OS_VM_DEFAULT_PAGESIZE somewhere... + * but since the OS doesn't know we're using this restriction, + * we have to grovel around a bit to enforce it, thus anything + * that uses real_page_size_difference. + */ + real_page_size_difference=OS_VM_DEFAULT_PAGESIZE-os_vm_page_size; + os_vm_page_size=OS_VM_DEFAULT_PAGESIZE; + } +} + +/* ---------------------------------------------------------------- */ + +os_vm_address_t +os_validate(os_vm_address_t addr, os_vm_size_t len) +{ + int flags = MAP_PRIVATE|MAP_NORESERVE; + + if(addr) flags|=MAP_FIXED; + + if((addr=mmap(addr,len,OS_VM_PROT_ALL,flags,zero_fd,0)) == (os_vm_address_t) -1) + perror("mmap"); + + return addr; +} + +void +os_invalidate(os_vm_address_t addr, os_vm_size_t len) +{ + if(munmap(addr,len) == -1) + perror("munmap"); +} + +os_vm_address_t +os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len) +{ + if((addr=mmap(addr,len,OS_VM_PROT_ALL,MAP_PRIVATE|MAP_FIXED,fd, + (off_t) offset)) == (os_vm_address_t) -1) + perror("mmap"); + + return addr; +} + +void os_flush_icache(address, length) +os_vm_address_t address; +os_vm_size_t length; +{ + static int flushit = -1; + /* + * On some systems, iflush needs to be emulated in the kernel + * On those systems, it isn't necessary + * Call getenv() only once. + */ + if (flushit == -1) + flushit = getenv("CMUCL_NO_SPARC_IFLUSH") == 0; + + if (flushit) { + static int traceit = -1; + if (traceit == -1) + traceit = getenv("CMUCL_TRACE_SPARC_IFLUSH") != 0; + + if (traceit) + fprintf(stderr,";;;iflush %p - %x\n", address,length); + flush_icache(address,length); + } +} + +void +os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot) +{ + if(mprotect(address, length, prot) == -1) + perror("mprotect"); +} + +boolean valid_addr(test) +os_vm_address_t test; +{ + /* XXX needs implementing */ + return 1; +} + +/* ---------------------------------------------------------------- */ + +static boolean maybe_gc(HANDLER_ARGS) +{ + /* + * It's necessary to enable recursive SEGVs, since the handler is + * used for multiple things (e.g., both gc-trigger & faulting in pages). + * We check against recursive gc's though... + */ + + boolean did_gc; + static already_trying=0; + + if(already_trying) + return FALSE; + + SAVE_CONTEXT(); + +#ifdef POSIX_SIGS + sigprocmask(SIG_SETMASK, &context->uc_sigmask,0); +#else + sigsetmask(context->sc_mask); +#endif + + already_trying=TRUE; + did_gc=interrupt_maybe_gc(signal, code, context); + already_trying=FALSE; + + return did_gc; +} + +/* + * The primary point of catching segmentation violations is to allow + * read only memory to be re-mapped with more permissions when a write + * is attempted. this greatly decreases the residency of the program + * in swap space since read only areas don't take up room + * + * Running into the gc trigger page will also end up here... + */ +void segv_handler(HANDLER_ARGS) +{ + caddr_t addr = code->si_addr; + + SAVE_CONTEXT(); + + if(maybe_gc(signal, code, context)) + /* we just garbage collected */ + return; + else{ + /* a *real* protection fault */ + fprintf(stderr, + "segv_handler: Real protection violation: 0x%08x\n", + addr); + interrupt_handle_now(signal,code,context); + } +} + +void os_install_interrupt_handlers() +{ + interrupt_install_low_level_handler(SIGSEGV,segv_handler); +} + + +/* function defintions for register lvalues */ + +int * solaris_register_address(struct ucontext *context, int reg) +{ + if (reg == 0) { + static int zero; + + zero = 0; + + return &zero; + } else if (reg < 16) { + return &context->uc_mcontext.gregs[reg+3]; + } else if (reg < 32) { + int *sp = (int*) context->uc_mcontext.gregs[REG_SP]; + return &sp[reg-16]; + } else + return 0; +} +/* function defintions for backward compatibilty and static linking */ + +/* For now we put in some porting functions */ + +#ifndef SOLARIS25 +int +getdtablesize(void) +{ + return sysconf(_SC_OPEN_MAX); +} + +char * +getwd(char *path) +{ + return getcwd(path, MAXPATHLEN); +} + +int +getpagesize(void) +{ + return sysconf(_SC_PAGESIZE); +} + + +#include <sys/procfs.h> +/* Old rusage definition */ +struct rusage { + struct timeval ru_utime; /* user time used */ + struct timeval ru_stime; /* system time used */ + long ru_maxrss; +#define ru_first ru_ixrss + long ru_ixrss; /* XXX: 0 */ + long ru_idrss; /* XXX: sum of rm_asrss */ + long ru_isrss; /* XXX: 0 */ + long ru_minflt; /* any page faults not requiring I/O */ + long ru_majflt; /* any page faults requiring I/O */ + long ru_nswap; /* swaps */ + long ru_inblock; /* block input operations */ + long ru_oublock; /* block output operations */ + long ru_msgsnd; /* messages sent */ + long ru_msgrcv; /* messages received */ + long ru_nsignals; /* signals received */ + long ru_nvcsw; /* voluntary context switches */ + long ru_nivcsw; /* involuntary " */ +#define ru_last ru_nivcsw +}; + + +int +getrusage(int who, struct rusage *rp) +{ + memset(rp, 0, sizeof(struct rusage)); + return 0; +} + +int +setreuid() +{ + fprintf(stderr,"setreuid unimplemented\n"); + errno = ENOSYS; + return -1; +} + +int +setregid() +{ + fprintf(stderr,"setregid unimplemented\n"); + errno = ENOSYS; + return -1; +} + +int +gethostid() +{ + fprintf(stderr,"gethostid unimplemented\n"); + errno = ENOSYS; + return -1; +} + +int +killpg(int pgrp, int sig) +{ + if (pgrp < 0) { + errno = ESRCH; + return -1; + } + return kill(-pgrp, sig); +} +#endif + +int +sigblock(int mask) +{ + sigset_t old, new; + + sigemptyset(&new); + new.__sigbits[0] = mask; + + sigprocmask(SIG_BLOCK, &new, &old); + + return old.__sigbits[0]; +} + +#ifndef SOLARIS25 +int +wait3(int *status, int options, struct rusage *rp) +{ + if (rp) + memset(rp, 0, sizeof(struct rusage)); + return waitpid(-1, status, options); +} +#endif + +int +sigsetmask(int mask) +{ + sigset_t old, new; + + sigemptyset(&new); + new.__sigbits[0] = mask; + + sigprocmask(SIG_SETMASK, &new, &old); + + return old.__sigbits[0]; + +} -- GitLab