diff options
| -rw-r--r-- | NetBSD/386/include/emu.h | 10 | ||||
| -rw-r--r-- | NetBSD/power/include/emu.h | 8 | ||||
| -rw-r--r-- | README.md | 4 | ||||
| -rw-r--r-- | emu/NetBSD/asm-386.S | 50 | ||||
| -rw-r--r-- | emu/NetBSD/asm-power.S | 31 | ||||
| -rw-r--r-- | emu/NetBSD/mkfile | 3 | ||||
| -rw-r--r-- | emu/NetBSD/os.c | 300 | ||||
| -rw-r--r-- | emu/port/alloc.c | 4 | ||||
| -rw-r--r-- | emu/port/kproc-pthreads.c | 13 | ||||
| -rw-r--r-- | emu/port/mkdevc | 2 |
10 files changed, 61 insertions, 364 deletions
diff --git a/NetBSD/386/include/emu.h b/NetBSD/386/include/emu.h index 5e03489b..07e3fad7 100644 --- a/NetBSD/386/include/emu.h +++ b/NetBSD/386/include/emu.h @@ -15,16 +15,8 @@ struct FPU #define KSTACK (32 * 1024) -static __inline Proc *getup(void) { - Proc *p; - __asm__( "movl %%esp, %%eax\n\t" - : "=a" (p) - ); - return *(Proc **)((unsigned long)p & ~(KSTACK - 1)); -}; - +extern Proc* getup(void); #define up (getup()) typedef sigjmp_buf osjmpbuf; #define ossetjmp(buf) sigsetjmp(buf, 1) - diff --git a/NetBSD/power/include/emu.h b/NetBSD/power/include/emu.h index 83af30d8..7d160b26 100644 --- a/NetBSD/power/include/emu.h +++ b/NetBSD/power/include/emu.h @@ -15,14 +15,8 @@ struct FPU #define KSTACK (32 * 1024) -static __inline Proc *getup(void) { - Proc *p; - __asm__( "mr %0, 1" : "=r" (p)); - return *(Proc **)((unsigned long)p & ~(KSTACK - 1)); -}; - +extern Proc* getup(void); #define up (getup()) typedef sigjmp_buf osjmpbuf; #define ossetjmp(buf) sigsetjmp(buf, 1) - @@ -1,7 +1,7 @@ Inferno® is a distributed operating system, originally developed at Bell Labs, but now developed and maintained by Vita Nuova® as Free Software. Applications written in Inferno's concurrent programming language, Limbo, are compiled to its portable virtual machine code (Dis), to run anywhere on a network in the portable environment that Inferno provides. Unusually, that environment looks and acts like a complete operating system.
-Inferno represents services and resrouces in a file-like name hiearchy. Programs access them using only the file operations open, read/write, and close. `Files' are not just stored data, but represent devices, network and protocol interfaces, dynamic data sources, and services. The approach unifies and provides basic naming, structuring, and access control mechanisms for all system resources. A single file-service protocol (the same as Plan 9's 9P) makes all those resources available for import or export throughout the network in a uniform way, independent of location. An application simply attaches the resources it needs to its own per-process name hierarchy ('name space'). +Inferno represents services and resources in a file-like name hierarchy. Programs access them using only the file operations open, read/write, and close. `Files' are not just stored data, but represent devices, network and protocol interfaces, dynamic data sources, and services. The approach unifies and provides basic naming, structuring, and access control mechanisms for all system resources. A single file-service protocol (the same as Plan 9's 9P) makes all those resources available for import or export throughout the network in a uniform way, independent of location. An application simply attaches the resources it needs to its own per-process name hierarchy ('name space'). -Inferno can run 'native' on various ARM, PowerPC, SPARC and x86 platforms but also 'hosted', under an existing operating system (including AIX, FreeBSD, Irix, Linux, MacOS X, Plan 9, and Solaris), again on various processor types.
+Inferno can run 'native' on various ARM, PowerPC, SPARC and x86 platforms but also 'hosted', under an existing operating system (including AIX, FreeBSD, IRIX, Linux, MacOS X, Plan 9, and Solaris), again on various processor types.
This Bitbucket project includes source for the basic applications, Inferno itself (hosted and native), all supporting software, including the native compiler suite, essential executables and supporting files.
diff --git a/emu/NetBSD/asm-386.S b/emu/NetBSD/asm-386.S index d21c03bb..85ff3c6c 100644 --- a/emu/NetBSD/asm-386.S +++ b/emu/NetBSD/asm-386.S @@ -2,56 +2,6 @@ #include <sys/syscall.h> /* - * executeonnewstack(void *tos, void (*tramp)(void *arg), void *arg) - */ - - .type executeonnewstack,@function - .global executeonnewstack -executeonnewstack: - pushl %ebp - movl %esp, %ebp - pushl %esi - - movl 8(%ebp), %esi /* get tos */ - subl $4, %esi - movl 16(%ebp), %eax - movl %eax, (%esi) /* stash arg on new stack */ - subl $4, %esi - movl 12(%ebp), %eax - movl %eax, (%esi) /* stash tramp on new stack */ - mov %esi, %esp /* swap stacks pronto */ - popl %eax /* recover the tramp address */ - call *%eax /* and jump to it (ho ho) */ - - /* if we return here, tramp didn't do its job */ - - addl $8, %esp /* clean up for pose value */ - - leal SYS_exit, %eax - int $0x80 - -/* - * unlockandexit(int *key) - * - * NB: the return status may be rubbish if the stack is reused - * between the unlock and the system call, but this should - * not matter since no task is waiting for the result - */ - - .type unlockandexit,@function - .global unlockandexit -unlockandexit: - pushl %ebp - movl %esp, %ebp - - movl 8(%ebp), %esi /* get the key address */ - pushl $0 /* exit status 0 */ - movl $0, %eax /* unlock the stack allocator */ - movl %eax, (%esi) - leal SYS_exit, %eax /* call exit */ - int $0x80 - -/* * umult(ulong m1, ulong m2, ulong *hi) */ diff --git a/emu/NetBSD/asm-power.S b/emu/NetBSD/asm-power.S index da40e825..32418e01 100644 --- a/emu/NetBSD/asm-power.S +++ b/emu/NetBSD/asm-power.S @@ -58,34 +58,3 @@ ENTRY_NOPROFILE(_tas) sync blr END(_tas) - -/* - * void - * executeonnewstack(void *tos, void (*tramp)(void *arg), void *arg) - */ -ENTRY_NOPROFILE(executeonnewstack) - mr %r1,%r3 /* change stacks */ - stwu %lr,-16(%r1) /* save lr to aid the traceback */ - li %r0,0 - stw %r0,20(%r1) - mr %r3,%r5 - mtctr %r4 - bctrl /* tramp(arg) */ - br - END(executeonnewstack) - -/* - * void unlockandexit(int *key) - * - * NB: the return status may be garbaged if the stack is reused - * between the unlock and the system call, but this should - * not matter since no task is waiting for the result - */ -ENTRY_NOPROFILE(unlockandexit) - li %r0,0x0 - stw %r0,0(%r3) /* unlock */ - li %r0,1 /* sys exit; 234 is exit group */ - li %r3,0 /* exit status */ - sc - br - END(unlockandexit) diff --git a/emu/NetBSD/mkfile b/emu/NetBSD/mkfile index ce001d96..17516997 100644 --- a/emu/NetBSD/mkfile +++ b/emu/NetBSD/mkfile @@ -23,6 +23,7 @@ OBJ=\ asm-$OBJTYPE.$O\ os.$O\ segflush-$OBJTYPE.$O\ + kproc-pthreads.$O\ $CONF.root.$O\ lock.$O\ $DEVS\ @@ -31,7 +32,7 @@ OBJ=\ HFILES=\ CFLAGS='-DROOT="'$ROOT'"' -DEMU -I. -I../port -I$ROOT/$SYSTARG/$OBJTYPE/include -I$ROOT/include -I$ROOT/libinterp $CTHREADFLAGS $CFLAGS $EMUOPTIONS -SYSLIBS= ${X11LIBS} -lossaudio -lm +SYSLIBS= ${X11LIBS} -lossaudio -lm -lpthread KERNDATE=`{$NDATE} default:V: $O.$CONF diff --git a/emu/NetBSD/os.c b/emu/NetBSD/os.c index b6ffab99..8ffce24e 100644 --- a/emu/NetBSD/os.c +++ b/emu/NetBSD/os.c @@ -13,6 +13,8 @@ #include "fns.h" #include "error.h" +#include "raise.h" + /* For dynamic linking init/fini code that needs malloc */ void (*coherence)(void) = nofence; @@ -21,16 +23,9 @@ enum { DELETE = 0x7f, CTRLC = 'C'-'@', - NSTACKSPERALLOC = 16, - X11STACK= 256*1024 }; char *hosttype = "NetBSD"; -static void *stackalloc(Proc *p, void **tos); -static void stackfreeandexit(void *stack); - -void executeonnewstack(void *tos, void (*tramp)(void *arg), void *arg); -void unlockandexit(ulong *key); extern int dflag; @@ -38,163 +33,49 @@ int gidnobody = -1; int uidnobody = -1; static struct termios tinit; -void -pexit(char *msg, int t) -{ - Osenv *e; - void *kstack; - - lock(&procs.l); - if(up->prev) - up->prev->next = up->next; - else - procs.head = up->next; - - if(up->next) - up->next->prev = up->prev; - else - procs.tail = up->prev; - unlock(&procs.l); - - if(0) - print("pexit: %s: %s\n", up->text, msg); - - e = up->env; - if(e != nil) { - closefgrp(e->fgrp); - closepgrp(e->pgrp); - closeegrp(e->egrp); - closesigs(e->sigs); - } - kstack = up->kstack; - free(up->prog); - free(up); - if(kstack != nil) - stackfreeandexit(kstack); -} - -int -tramp(void *arg) -{ - Proc *p; - p = arg; - p->pid = p->sigid = getpid(); - (*p->func)(p->arg); - pexit("{Tramp}", 0); - return 0; -} - -void -kproc(char *name, void (*func)(void*), void *arg, int flags) -{ - int pid; - Proc *p; - Pgrp *pg; - Fgrp *fg; - Egrp *eg; - void *tos; - - p = newproc(); - if(0) - print("start %s:%.8lx\n", name, p); - if(p == nil) { - print("kproc(%s): no memory", name); - panic("kproc: no memory"); - } - - if(flags & KPDUPPG) { - pg = up->env->pgrp; - incref(&pg->r); - p->env->pgrp = pg; - } - if(flags & KPDUPFDG) { - fg = up->env->fgrp; - incref(&fg->r); - p->env->fgrp = fg; - } - if(flags & KPDUPENVG) { - eg = up->env->egrp; - incref(&eg->r); - p->env->egrp = eg; - } - - p->env->uid = up->env->uid; - p->env->gid = up->env->gid; - kstrdup(&p->env->user, up->env->user); - - strcpy(p->text, name); - - p->func = func; - p->arg = arg; - - if(flags & KPX11){ - p->kstack = nil; /* never freed; also up not defined */ - tos = (char*)mallocz(X11STACK, 0) + X11STACK - sizeof(void*); - }else - p->kstack = stackalloc(p, &tos); - - lock(&procs.l); - if(procs.tail != nil) { - p->prev = procs.tail; - procs.tail->next = p; - } - else { - procs.head = p; - p->prev = nil; - } - procs.tail = p; - unlock(&procs.l); - - if (__clone(tramp, tos, /*CLONE_PTRACE|*/CLONE_VM|CLONE_FS|CLONE_FILES|SIGCHLD, p) <= 0) { - fprint(2, "emu: clone failed: %s\n", strerror(errno)); - panic("kproc: clone failed"); - } -} - -/* - * TO DO: - * To get pc on trap, use sigaction instead of signal and - * examine its siginfo structure - */ - -/* static void -diserr(char *s, int pc) +sysfault(char *what, void *addr) { - char buf[ERRMAX]; + char buf[64]; - snprint(buf, sizeof(buf), "%s: pc=0x%lux", s, pc); + snprint(buf, sizeof(buf), "sys: %s%#p", what, addr); disfault(nil, buf); } -*/ static void -trapILL(int signo) +trapILL(int signo, siginfo_t *si, void *a) { USED(signo); - disfault(nil, "Illegal instruction"); + USED(a); + sysfault("illegal instruction pc=", si->si_addr); } -static void -trapBUS(int signo) +static int +isnilref(siginfo_t *si) { - USED(signo); - disfault(nil, "Bus error"); + return si != 0 && (si->si_addr == (void*)~(uintptr_t)0 || (uintptr_t)si->si_addr < 512); } static void -trapSEGV(int signo) +trapmemref(int signo, siginfo_t *si, void *a) { - USED(signo); - disfault(nil, "Segmentation violation"); + USED(a); /* ucontext_t*, could fetch pc in machine-dependent way */ + if(isnilref(si)) + disfault(nil, exNilref); + else if(signo == SIGBUS) + sysfault("bad address addr=", si->si_addr); /* eg, misaligned */ + else + sysfault("segmentation violation addr=", si->si_addr); } static void -trapFPE(int signo) +trapFPE(int signo, siginfo_t *si, void *a) { char buf[64]; + USED(signo); - snprint(buf, sizeof(buf), "sys: fp: exception status=%.4lux", getfsr()); + USED(a); + snprint(buf, sizeof(buf), "sys: fp: exception status=%.4lux pc=%#p", getfsr(), si->si_addr); disfault(nil, buf); } @@ -215,37 +96,6 @@ trapUSR1(int signo) disfault(nil, Eintr); /* Should never happen */ } -/* called to wake up kproc blocked on a syscall */ -void -oshostintr(Proc *p) -{ - kill(p->sigid, SIGUSR1); -} - -static void -trapUSR2(int signo) -{ - USED(signo); - /* we've done our work of interrupting sigsuspend */ -} - -void -osblock(void) -{ - sigset_t mask; - - sigprocmask(SIG_SETMASK, NULL, &mask); - sigdelset(&mask, SIGUSR2); - sigsuspend(&mask); -} - -void -osready(Proc *p) -{ - if(kill(p->sigid, SIGUSR2) < 0) - fprint(2, "emu: osready failed: pid %d: %s\n", p->sigid, strerror(errno)); -} - void oslongjmp(void *regs, osjmpbuf env, int val) { @@ -301,12 +151,9 @@ osreboot(char *file, char **argv) void libinit(char *imod) { - struct termios t; struct sigaction act; - sigset_t mask; struct passwd *pw; Proc *p; - void *tos; char sys[64]; setsid(); @@ -323,18 +170,10 @@ libinit(char *imod) if(dflag == 0) termset(); - memset(&act, 0 , sizeof(act)); + memset(&act, 0, sizeof(act)); act.sa_handler = trapUSR1; sigaction(SIGUSR1, &act, nil); - sigemptyset(&mask); - sigaddset(&mask, SIGUSR2); - sigprocmask(SIG_BLOCK, &mask, NULL); - - memset(&act, 0 , sizeof(act)); - act.sa_handler = trapUSR2; - sigaction(SIGUSR2, &act, nil); - act.sa_handler = SIG_IGN; sigaction(SIGCHLD, &act, nil); @@ -349,18 +188,23 @@ libinit(char *imod) signal(SIGINT, cleanexit); if(sflag == 0) { - act.sa_handler = trapBUS; - sigaction(SIGBUS, &act, nil); - act.sa_handler = trapILL; + act.sa_flags = SA_SIGINFO; + + act.sa_sigaction = trapILL; sigaction(SIGILL, &act, nil); - act.sa_handler = trapSEGV; - sigaction(SIGSEGV, &act, nil); - act.sa_handler = trapFPE; + + act.sa_sigaction = trapFPE; sigaction(SIGFPE, &act, nil); + + act.sa_sigaction = trapmemref; + sigaction(SIGBUS, &act, nil); + sigaction(SIGSEGV, &act, nil); + + act.sa_flags = 0; } p = newproc(); - p->kstack = stackalloc(p, &tos); + kprocinit(p); pw = getpwuid(getuid()); if(pw != nil) @@ -371,7 +215,7 @@ libinit(char *imod) p->env->uid = getuid(); p->env->gid = getgid(); - executeonnewstack(tos, emuinit, imod); + emuinit(imod); } int @@ -457,73 +301,3 @@ limbosleep(ulong milsec) { return osmillisleep(milsec); } - -void -osyield(void) -{ - sched_yield(); -} - -void -ospause(void) -{ - for(;;) - pause(); -} - -void -oslopri(void) -{ - setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS,0)+4); -} - -static struct { - Lock l; - void *free; -} stacklist; - -static void -_stackfree(void *stack) -{ - *((void **)stack) = stacklist.free; - stacklist.free = stack; -} - -static void -stackfreeandexit(void *stack) -{ - lock(&stacklist.l); - _stackfree(stack); - unlockandexit(&stacklist.l.val); -} - -static void * -stackalloc(Proc *p, void **tos) -{ - void *rv; - lock(&stacklist.l); - if (stacklist.free == 0) { - int x; - /* - * obtain some more by using sbrk() - */ - void *more = sbrk(KSTACK * (NSTACKSPERALLOC + 1)); - if (more == 0) - panic("stackalloc: no more stacks"); - /* - * align to KSTACK - */ - more = (void *)((((unsigned long)more) + (KSTACK - 1)) & ~(KSTACK - 1)); - /* - * free all the new stacks onto the freelist - */ - for (x = 0; x < NSTACKSPERALLOC; x++) - _stackfree((char *)more + KSTACK * x); - } - rv = stacklist.free; - stacklist.free = *(void **)rv; - unlock(&stacklist.l); - *tos = rv + KSTACK - sizeof(void *); - *(Proc **)rv = p; - return rv; -} diff --git a/emu/port/alloc.c b/emu/port/alloc.c index 333f4fa3..8b623de0 100644 --- a/emu/port/alloc.c +++ b/emu/port/alloc.c @@ -75,7 +75,11 @@ enum { /* tracing */ enum { +#ifdef __NetBSD__ + Npadlong = 4, /* XXX: preserve 16-byte alignment */ +#else Npadlong = 2, +#endif MallocOffset = 0, ReallocOffset = 1 }; diff --git a/emu/port/kproc-pthreads.c b/emu/port/kproc-pthreads.c index 32053794..c6caded6 100644 --- a/emu/port/kproc-pthreads.c +++ b/emu/port/kproc-pthreads.c @@ -12,6 +12,13 @@ #include <errno.h> #include <semaphore.h> +#ifdef __NetBSD__ +#include <sched.h> +#define pthread_yield() (sched_yield()) +#define PTHREAD_STACK_MIN ((size_t)sysconf(_SC_THREAD_STACK_MIN)) +#endif + + typedef struct Osdep Osdep; struct Osdep { sem_t sem; @@ -115,6 +122,12 @@ kproc(char *name, void (*func)(void*), void *arg, int flags) panic("kproc: no memory"); os->self = 0; /* set by tramp */ sem_init(&os->sem, 0, 0); +#if defined(__NetBSD__) && defined(__powerpc__) + { /* XXX: Work around a problem on macppc with kernel semaphores. */ + int val; + sem_getvalue(&os->sem, &val); + } +#endif p->os = os; if(flags & KPDUPPG) { diff --git a/emu/port/mkdevc b/emu/port/mkdevc index 825c76b0..6b8c6a7d 100644 --- a/emu/port/mkdevc +++ b/emu/port/mkdevc @@ -10,7 +10,7 @@ BEGIN{ /^#/{ next; } -collect && /^[^ \t]/{ +collect && /^[^ \t]/{ collect = 0; } collect && section ~ "dev"{ |
