ref: 79c64a79a248c31733d4ec0ff9fe1a1e57a58f51
dir: /emu/Plan9/os.c/
#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 kproc1(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 kproc(char *name, void (*func)(void*), void *arg, int flags) { kproc1(name, func, arg, flags); } 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<sizeof(uvlong); i++) v = (v<<8)|p[i]; return v; } vlong nsec(void) { int n; static int nsecfd = -1; uchar buf[sizeof(uvlong)]; if(nsecfd < 0){ nsecfd = open("/dev/bintime", OREAD|OCEXEC); /* never closed */ if(nsecfd<0){ fprint(2,"can't open /dev/bintime: %r\n"); return 0; } } n = read(nsecfd, buf, sizeof(buf)); if(n!=sizeof(buf)) { fprint(2,"read err on /dev/bintime: %r\n"); return 0; } return b2v(buf); } long osmillisec(void) { static vlong nsec0 = 0; if(nsec0 == 0){ nsec0 = nsec(); return 0; } return (nsec()-nsec0)/1000000; } /* * Return the time since the epoch in microseconds * The epoch is defined at 1 Jan 1970 */ vlong osusectime(void) { return nsec()/1000; } int osmillisleep(ulong milsec) { sleep(milsec); return 0; } int limbosleep(ulong milsec) { return osmillisleep(milsec); } void osyield(void) { sleep(0); } void ospause(void) { for(;;) sleep(1000000); } void oslopri(void) { int fd; char buf[32]; snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid()); if((fd = open(buf, OWRITE)) >= 0){ fprint(fd, "pri 8"); close(fd); } }