#include <9pm/u.h> #include <9pm/libc.h> #include "dat.h" #include "fns.h" static int ndev; Dev *devtab[32]; void adddev(Dev *d) { int i; for(i=0; devtab[i]; i++) if(devtab[i]==d) return; if(ndev >= nelem(devtab)-1) pm_panic("too many devs"); devtab[ndev++] = d; devtab[ndev] = nil; (*d->reset)(); } long copyproc(Proc *p, int flag) { Proc *xp; ulong arg; long ret; xp = up; up = p; arg = RFPROC|flag; ret = sysrfork(&arg); up = xp; return ret; } Proc* findproc(long pid) { int s; Proc *p; if(pid==0){ s = procindex(1); if(s==-1 || (p=procalloc.arena[s])==nil) panic("findproc"); pid = copyproc(p, RFNOTEG|RFCFDG); } s = procindex(pid); if(s==-1 || (p=procalloc.arena[s])==nil || !canlock(&p->nascent)) return nil; return p; } /* * The first proc never runs. It exists only to be cloned. */ void userinit(void) { Proc *p; p = newproc(); p->pgrp = newpgrp(); p->egrp = smalloc(sizeof(Egrp)); p->egrp->ref.ref = 1; p->fgrp = dupfgrp(nil); p->rgrp = newrgrp(); p->procmode = 0640; kstrdup(&p->text, "adam"); kstrdup(&p->user, eve); p->state = Nascent; lock(&p->nascent); up = p; } Systab systab[Nsyscall] = { { sysr1, "", "Sysr1" }, { sysbind, "ssl", "Bind" }, { syschdir, "s", "Chdir" }, { sysclose, "l", "Close" }, { sysdup, "ll", "Dup" }, { sysalarm, "l", "Alarm" }, { sysexec, "sS", "Exec" }, { sysexits, "s", "Exits" }, { sysfauth, "ls", "Fauth" }, { sysopen, "sl", "Open" }, { syssleep, "l", "Sleep" }, { sysrfork, "l", "Rfork" }, { syspipe, "f", "Pipe" }, { syscreate, "sll", "Create" }, { sysfd2path, "lb", "Fd2path" }, { sysfd2path, "lb", "Fd2syspath" }, { sysremove, "s", "Remove" }, { sysnoted, "l", "Noted" }, { sysrendezvous, "ll", "Rendez" }, { sysunmount, "ns", "Unmount" }, { sysseek, "Vlvl", "Seek" }, { sysfversion, "llb", "Fversion" }, { syserrstr, "b", "Errstr" }, { sysstat, "sb", "Stat" }, { sysfstat, "lb", "Fstat" }, { syswstat, "sb", "Wstat" }, { sysfwstat, "lb", "Fwstat" }, { sysmount, "llsls", "Mount" }, { sysawait, "b", "Await" }, { syspread, "lbv", "Pread" }, { syspwrite, "lbv", "Pwrite" }, { syspassfd, "ll", "Passfd" }, { syspassdir, "s", "Passdir" }, }; static char Eaddr[] = "invalid address in system call"; void validargs(ulong *arg, void *vs, void *ve, char *fmt) { char *p; ulong *a, *b, *c, *s, *e; ulong n; if(fmt == nil) error("bad fmt for system call (bug)"); s = vs; e = ve; for(p=fmt; *p; p++){ switch(*p){ default: error("unknown fmt char (bug)"); case 'l': /* integer */ arg++; break; case 'n': /* possibly null string pointer */ if(*arg == ~0){ *arg = 0; break; } /* fall through */ case 's': /* string pointer */ *arg += (ulong)s; a = (ulong*)(*arg++); if(a < s || a >= e || memchr(a, 0, (uchar*)e-(uchar*)a) == nil) error(Eaddr); break; case 'S': /* pointer to zero-terminated array of string pointers */ *arg += (ulong)s; a = (ulong*)(*arg++); if(a < s || ((ulong)a&(sizeof(ulong)-1))) error(Eaddr); for(b=a; b= e || memchr(c, 0, (uchar*)e-(uchar*)c) == nil) error(Eaddr); } if(b >= e) error(Eaddr); break; case 'V': /* pointer to vlong */ case 'f': /* pointer to two integers */ *arg += (ulong)s; a = (ulong*)(*arg++); if(a < s || a+2 > e) error(Eaddr); break; case 'v': /* vlong */ arg += 2; break; case 'b': /* buffer: pointer followed by length */ *arg += (ulong)s; a = (ulong*)(*arg++); n = *arg++; if(a < s || (uchar*)a+n > (uchar*)e) error(Eaddr); break; } } } /* * These don't have any effect on whether we can get preempted * for another process, of course, but they do change our behavior * when spinning for a test-and-set lock: if we are spl hi, we call * ossched to yield the processor after glaring for a little while. * Probably this is a kludge and what we should really do is always yield. */ int splhi(void) { int s; s = M->spl; M->spl = 1; return s; } int spllo(void) { int s; s = M->spl; M->spl = 0; return s; } int islo(void) { return M->spl==0; } void splx(int s) { M->spl = s; }