From 37da2899f40661e3e9631e497da8dc59b971cbd0 Mon Sep 17 00:00:00 2001 From: "Charles.Forsyth" Date: Fri, 22 Dec 2006 17:07:39 +0000 Subject: 20060303a --- emu/Plan9/os.c | 422 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 422 insertions(+) create mode 100644 emu/Plan9/os.c (limited to 'emu/Plan9/os.c') diff --git a/emu/Plan9/os.c b/emu/Plan9/os.c new file mode 100644 index 00000000..d681ec67 --- /dev/null +++ b/emu/Plan9/os.c @@ -0,0 +1,422 @@ +#include "dat.h" +#include "fns.h" +#include "error.h" + +enum +{ + KSTACK = 16*1024, + DELETE = 0x7F, +}; + +Proc **Xup; + +extern void killrefresh(void); +extern void tramp(char*, void (*)(void*), void*); + +extern int usenewwin; + +int *ustack; /* address on unshared stack: see vstack in asm*.s */ +extern int dflag; +char *hosttype = "Plan9"; +char *cputype; + +void +osblock(void) +{ + rendezvous(up, nil); +} + +void +osready(Proc *p) +{ + rendezvous(p, nil); +} + +void +pexit(char *msg, int) +{ + Osenv *e; + + USED(msg); + + 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); + +/* 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); + } + free(e->user); + free(up->prog); + up->prog = nil; + up->type = Moribund; + longjmp(up->privstack, 1); +} + +int +kproc(char *name, void (*func)(void*), void *arg, int flags) +{ + int pid; + Proc *p; + Pgrp *pg; + Fgrp *fg; + Egrp *eg; + + p = newproc(); + if(p == nil) + panic("kproc: no memory"); + p->kstack = mallocz(KSTACK, 0); + if(p->kstack == nil) + 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; + + 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); + + /* + * switch back to the unshared stack to do the fork + * only the parent returns from kproc + */ + up->kid = p; + up->kidsp = p->kstack; + pid = setjmp(up->sharestack); + if(pid == 0) + longjmp(up->privstack, 1); + return pid; +} + +void +traphandler(void *reg, char *msg) +{ + int intwait; + + intwait = up->intwait; + up->intwait = 0; + /* Ignore pipe writes from devcmd */ + if(strstr(msg, "write on closed pipe") != nil) + noted(NCONT); + + if(sflag) { + if(intwait && strcmp(msg, Eintr) == 0) + noted(NCONT); + else + noted(NDFLT); + } + if(intwait == 0) + disfault(reg, msg); + noted(NCONT); +} + +int +readfile(char *path, char *buf, int n) +{ + int fd; + + fd = open(path, OREAD); + if(fd >= 0) { + n = read(fd, buf, n-1); + if(n > 0) /* both calls to readfile() have a ``default'' */ + buf[n] = '\0'; + close(fd); + return n; + } + return 0; +} + +static void +dobinds(void) +{ + char dir[MAXROOT+9]; + + snprint(dir, sizeof(dir), "%s/net", rootdir); + bind("/net", dir, MREPL); + + snprint(dir, sizeof(dir), "%s/net.alt", rootdir); + bind("/net.alt", dir, MREPL); + + snprint(dir, sizeof(dir), "%s/dev", rootdir); + bind("#t", dir, MAFTER); + bind("#A", dir, MAFTER); +} + +void +libinit(char *imod) +{ + char *sp; + Proc *xup, *p; + int fd, n, pid; + char nbuf[64]; + + xup = nil; + Xup = &xup; + + /* + * setup personality + */ + if(readfile("/dev/user", nbuf, sizeof nbuf)) + kstrdup(&eve, nbuf); + if(readfile("/dev/sysname", nbuf, sizeof nbuf)) + kstrdup(&ossysname, nbuf); + if(readfile("/env/cputype", nbuf, sizeof nbuf)) + kstrdup(&cputype, nbuf); + + /* + * guess at a safe stack for vstack + */ + ustack = &fd; + + rfork(RFNAMEG|RFREND); + + if(!dflag){ + fd = open("/dev/consctl", OWRITE); + if(fd < 0) + fprint(2, "libinit: open /dev/consctl: %r\n"); + n = write(fd, "rawon", 5); + if(n != 5) + fprint(2, "keyboard rawon (n=%d, %r)\n", n); + } + + osmillisec(); /* set the epoch */ + dobinds(); + + notify(traphandler); + + /* + * dummy up a up and stack so the first proc + * calls emuinit after setting up his private jmp_buf + */ + p = newproc(); + p->kstack = mallocz(KSTACK, 0); + if(p == nil || p->kstack == nil) + panic("libinit: no memory"); + sp = p->kstack; + p->func = emuinit; + p->arg = imod; + + /* + * set up a stack for forking kids on separate stacks. + * longjmp back here from kproc. + */ + while(setjmp(p->privstack)){ + if(up->type == Moribund){ + free(up->kstack); + free(up); + _exits(""); + } + p = up->kid; + sp = up->kidsp; + up->kid = nil; + switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){ + case 0: + /* + * send the kid around the loop to set up his private jmp_buf + */ + break; + default: + /* + * parent just returns to his shared stack in kproc + */ + longjmp(up->sharestack, pid); + panic("longjmp failed"); + } + } + + /* + * you get here only once per Proc + * go to the shared memory stack + */ + up = p; + up->pid = up->sigid = getpid(); + tramp(sp+KSTACK, up->func, up->arg); + panic("tramp returned"); +} + +void +oshostintr(Proc *p) +{ + postnote(PNPROC, p->sigid, Eintr); +} + +void +oslongjmp(void *regs, osjmpbuf env, int val) +{ + if(regs != nil) + notejmp(regs, env, val); + else + longjmp(env, val); +} + +void +osreboot(char*, char**) +{ +} + +void +cleanexit(int x) +{ + USED(x); + killrefresh(); + postnote(PNGROUP, getpid(), "interrupt"); + exits("interrupt"); +} + +int +readkbd(void) +{ + int n; + char buf[1]; + + n = read(0, buf, sizeof(buf)); + if(n < 0) + fprint(2, "emu: keyboard read error: %r\n"); + if(n <= 0) + pexit("keyboard", 0); + switch(buf[0]) { + case DELETE: + cleanexit(0); + case '\r': + buf[0] = '\n'; + } + return buf[0]; +} + +static vlong +b2v(uchar *p) +{ + int i; + vlong v; + + v = 0; + for(i=0; i= 0){ + fprint(fd, "pri 8"); + close(fd); + } +} -- cgit v1.2.3