#include <stdio.h> #include <errno.h> #include <string.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/types.h> #include <sys/uio.h> #include <sys/resource.h> #include <sys/utsname.h> #include <xr/sMisc.h> #include <xr/Threads.h> #include <xr/ThreadsMsg.h> #include <xr/UIO.h> #include <xr/GC.h> #include "gc/gc←private.h" int SPCR←debugMessages = 1; int SPCR←ignoreErrors = 0; void SPCR←error(s) char *s; { if (SPCR←debugMessages) fprintf(stderr, "%s\n", s); if (!SPCR←ignoreErrors) abort(s); } void XR←Panic(s) char *s; { SPCR←error(s); } void SPCR←NotImplemented(s) char *s; { if (SPCR←debugMessages) fprintf(stderr, "%s not implemented in stubbed pcr\n", s); SPCR←error("unimplemented primitive\n"); } /* * Unix error return code */ int * XR←GetErrnoAddress() { extern int errno; return( &errno ); } /* Nobody actually looks at these. We save them just in case ... */ XR←HandlerProc SPCR←handler←proc; XR←Pointer SPCR←handler←data; void XR←RegisterHandler (proc, data) XR←HandlerProc proc; XR←Pointer data; { if( (proc != NIL) || (data == NIL) ) { SPCR←handler←proc = proc; } else { SPCR←handler←proc = (XR←HandlerProc) (((XR←MesaProc)(data))->mp←proc); } SPCR←handler←data = data; } XR←Fildes SPCR←map←descr(d) XR←Fildes d; { switch(d) { case -3: /* XR←MSG←STDOUT in standard PCR */ return(XR←MSG←STDOUT); case -2: /* XR←MSG←STDIN in standard PCR */ return(XR←MSG←STDIN); default: return(d); } } /* A slight change to the default behavior, to allow for standard PCR */ /* XR←MSG←STDOUT def. */ int XR←Write(fd, buf, nbyte) int fd; char * buf; int nbyte; { return(write(SPCR←map←descr(fd), buf, nbyte)); } int XR←WriteV(fd, iov, iovcnt) int fd; struct iovec *iov; int iovcnt; { return(writev(SPCR←map←descr(fd), iov, iovcnt)); } /* Ditto for XR←MSG←STDIN. */ int XR←Read(fd, buf, nbyte) int fd; char * buf; int nbyte; { return(read(SPCR←map←descr(fd), buf, nbyte)); } int XR←ReadV(fd, iov, iovcnt) int fd; struct iovec *iov; int iovcnt; { return(readv(SPCR←map←descr(fd), iov, iovcnt)); } # define BUFSZ 1024 void XR←Msg( descriptor, fmt, a0, a1, a2, a3, a4, a5, a6, a7 ) int descriptor; char *fmt; int a0, a1, a2, a3, a4, a5, a6, a7; { char buf[BUFSZ+1]; buf[BUFSZ] = 1; sprintf(buf, fmt, a0, a1, a2, a3, a4, a5, a6, a7); if (buf[BUFSZ] != 1) { SPCR←error("XR←Msg wrote past end of buffer"); } XR←Write(descriptor, buf, strlen(buf)); } void XR←FPrintF( descriptor, fmt, a0, a1, a2, a3, a4, a5, a6, a7 ) int descriptor; char *fmt; int a0, a1, a2, a3, a4, a5, a6, a7; { XR←Msg(descriptor, fmt, a0, a1, a2, a3, a4, a5, a6, a7); } char * XR←SPrintF( buf, fmt, a0, a1, a2, a3, a4, a5, a6, a7 ) char * buf; char *fmt; int a0, a1, a2, a3, a4, a5, a6, a7; { sprintf(buf, fmt, a0, a1, a2, a3, a4, a5, a6, a7); return(buf + strlen(buf)); } int XR←MsgWrite (buf, nbytes) char *buf; int nbytes; { return(XR←Write(XR←MSG←STDOUT, buf, nbytes) ); } #define DevNullOrFile(filename) ((filename) != 0 \ ? (filename) \ : "/dev/null") #define maxStrlenOfStrAndDevNull(s) ((s) != 0 \ ? strlen((s)) \ : (sizeof("/dev/null") - 1)) int XR←Spawn(cmd, in, out, err) char *cmd; char *in; /* NIL, "" => /dev/null */ char *out; char *err; { int len = strlen(cmd) + maxStrlenOfStrAndDevNull(in) + maxStrlenOfStrAndDevNull(out) + maxStrlenOfStrAndDevNull(err) + 11; /* 11 == strlen(" < ")+strlen(" > ")+strlen(" 2> ")+'\0' */ char *p = (char *)GC←malloc(len); sprintf(p, "%s < %s > %s 2> %s", cmd, DevNullOrFile(in), DevNullOrFile(out), DevNullOrFile(err)); return system(p); } void XR←GCollect() { GC←gcollect(); } unsigned XR←GCHeapSize() { return(GC←heapsize); } unsigned XR←GCTotalByteCount() { return(WORDS←TO←BYTES(GC←words←allocd←before←gc + GC←words←allocd)); } # define I←DONT←KNOW 17 unsigned XR←GCTotalObjectCount() { return(I←DONT←KNOW); } unsigned XR←GCCurrentByteCount() { return(I←DONT←KNOW); } unsigned XR←GCCurrentObjectCount() { return(I←DONT←KNOW); } static unsigned bytesAfterWhichToCollect; /* Not really, but we try to lie consistently ... */ unsigned XR←SetBytesAfterWhichToCollect(n) unsigned n; { unsigned old = bytesAfterWhichToCollect; bytesAfterWhichToCollect = n; return(old); } /* If p is a valid pointer to an object, return a pointer to the */ /* beginning of that object. Otherwise return NIL. */ /* If szp is nonNIL, save the objects size in bytes in *szp. */ /* If ptrfreep is nonNIL, set *ptrfreep to 0 or 1 depending on */ /* whether or not the object is pointer free. */ /* An object may be considered valid even though it is about to */ /* be garbage collected because it was inaccessible during the */ /* last mark phase. A nonNIL result does guarantee that the */ /* object can be read without generating a fault. */ XR←Pointer XR←PtrTest(p, szp, ptrfreep) void * p; /* May be any 32 bit integer */ long * szp; int * ptrfreep; { char * base = (char *)GC←base(p); struct hblk * h = HBLKPTR(base); hdr * hhdr = HDR(h); if (base == 0) return(0); if (szp != 0) *szp = (long)GC←size(base); if (ptrfreep != 0) { struct hblk * h = HBLKPTR(base); hdr * hhdr = HDR(h); if (hhdr -> hb←obj←kind == PTRFREE) { *ptrfreep = 1; } else { *ptrfreep = 0; } } return((XR←Pointer)base); } #undef XR←GetErrno #undef XR←SetErrno int XR←GetErrno() { return(errno); } int XR←SetErrno(x) int x; { errno = x; } XR←Pointer SPCR←freeMemPtr = (XR←Pointer)0x20000000; XR←Pointer XR←VMReserve (bytes) unsigned bytes; { XR←Pointer result = SPCR←freeMemPtr; unsigned ps = 4096; /* check if this is ok */ SPCR←freeMemPtr += (bytes + ps - 1) & ~(ps - 1); return(result); } /* Force the right GC routines to be inncluded in .o */ void SPCR←require() { GC←malloc(0); GC←realloc(0, 0); GC←free(0); GC←malloc←atomic(0); } bool XR←StackPushTest(nbytes) int nbytes; { char dummy; # define SLOP 10000 struct rlimit rl; if (getrlimit(RLIMIT←STACK, &rl) < 0) { SPCR←error("XR←StackPushTest"); } if ((char *)GC←stackbottom - &dummy + SLOP + nbytes >= rl.rlim←cur) { return(FALSE); } else { return(TRUE); } } /* the following are not (readily) available in solaris, so we stub them */ /* most of the code is taken from (or patterned after) ppcr's XR←UIOImpl.c */ int XR←GetRUsage() { return -ENOSYS; } /* this is a guess -- we'll see how it works */ int XR←GetDTableSize1(XR←FDKind kind) { switch( kind ) { case XR←FD←KIND←STD: return 32; default: return -EINVAL; } } int XR←GetDTableSize(void) { return XR←GetDTableSize1(XR←FD←KIND←STD); } int XR←GetHostID(void) { return -ENOSYS; } int XR←GetDomainName(char *name, int nameLen) { return -ENOMEM; } int XR←KillPG(int pgrp, int sig) { return -1; } int XR←GetPageSize(void) { return 4096; } int XR←GetHostName(char *name, int nameLen) { struct utsname utsn; uname(&utsn); strncpy( name, utsn.nodename, nameLen ); return 0; } struct XR←timeval { long tv←sec; /* seconds */ long tv←usec; /* and microseconds */ }; struct XR←timezone { int tz←minuteswest; /* minutes west of Greenwich */ int tz←dsttime; /* type of dst correction */ }; int XR←GetTimeOfDay(struct XR←timeval *xtp, struct XR←timezone *xtzp) { int ans = 0; int saverr = 0; struct timeval t; if ( xtp != NIL ) { ans = gettimeofday(&t); if ( ans != (-1) ) { xtp->tv←sec = t.tv←sec; xtp->tv←usec = t.tv←usec; } else { saverr = - errno; } } if( xtzp != NIL ) { xtzp->tz←minuteswest = timezone / 60; /* is in seconds */ xtzp->tz←dsttime = daylight; } return saverr; } typedef unsigned short XR←mode←t; typedef long XR←time←t; typedef int XR←size←t; typedef short XR←dev←t; typedef long XR←off←t; typedef unsigned long XR←ino←t; typedef unsigned short XR←uid←t; typedef unsigned short XR←gid←t; struct XR←stat { XR←dev←t xrst←dev; XR←ino←t xrst←ino; XR←mode←t xrst←mode; short xrst←nlink; XR←uid←t xrst←uid; XR←gid←t xrst←gid; XR←dev←t xrst←rdev; XR←off←t xrst←size; XR←time←t xrst←atime; int xrst←spare1; XR←time←t xrst←mtime; int xrst←spare2; XR←time←t xrst←ctime; int xrst←spare3; long xrst←blksize; long xrst←blocks; long xrst←spare4[2]; }; int XR←FStat(XR←Fildes fildes, struct XR←stat *buf) { struct stat sysstat; int ans; if( buf == NIL ) return -EFAULT; ans = fstat(fildes, &sysstat); if (ans == -1) return -errno; (void)ConvertStat( buf, &sysstat); return 0; } int XR←Stat(char *path, struct XR←stat *buf) { int ans; struct stat sysstat; if( buf == NIL ) return -EFAULT; ans = stat( path, &sysstat ); if (ans == -1) return -errno; (void)ConvertStat( buf, &sysstat); return 0; } int ConvertStat( struct XR←stat *xs, struct stat *ps) { if( (xs == NIL) || (ps == NIL) ) return; xs->xrst←mode = ps->st←mode; xs->xrst←ino = ps->st←ino; xs->xrst←dev = ps->st←dev; xs->xrst←nlink = ps->st←nlink; xs->xrst←uid = ps->st←uid; xs->xrst←gid = ps->st←gid; xs->xrst←size = ps->st←size; xs->xrst←atime = ps->st←atime; xs->xrst←mtime = ps->st←mtime; xs->xrst←ctime = ps->st←ctime; xs->xrst←blksize = 4096; /* hack, hack */ xs->xrst←blocks = xs->xrst←size / xs->xrst←blksize; /* hack, hack */ return 0; } /* having trouble with lseek - seems to return fildes as result */ /* when defined as XR←SYSCALL3(LSeek,lseek) */ int XR←LSeek(int fildes, int offset, int whence) { int res; res = lseek(fildes, offset, whence); return (res); }