/wrap 20000000775 inferno inf 1141890616 0 /wrap/src 20000000775 inferno inf 1141890616 0 /wrap/src/1141890616 20000000775 inferno inf 1141890616 0 /wrap/src/1141890616/package 664 inferno inf 1141890616 0 /wrap/src/1141890616/desc 664 inferno inf 1141890616 4 src /wrap/src/1141890616/proto 664 inferno inf 1141890616 453 emu port devcons.c main.c MacOSX asm-386.s deveia.c emu-386 mkfile mkfile-386 mkfile-power NOTE NOTICE os-mach.c os.c mkfile lib9 getcallerpc-MacOSX-386.s mkfile-MacOSX sbrk-MacOSX.c libdraw mkfile-MacOSX libinterp dlm-MacOSX.c load.c libmath FPcontrol-MacOSX.c mkfile mkfile-MacOSX limbo mkfile-MacOSX mkfiles mkfile-MacOSX-386 mkfile-MacOSX-power mkhost-MacOSX utils iar MacOSX.c mkfile srclist MacOSX.c /wrap/src/1141890616/md5sum 664 inferno inf 1141890616 2079 /emu 00000000000000000000000000000000 /emu/MacOSX 00000000000000000000000000000000 /emu/MacOSX/NOTE 02879186624a43665252a09b7f67e0d7 /emu/MacOSX/NOTICE ce065be66797e8a231cd8690d5820f41 /emu/MacOSX/asm-386.s 50366c74185c71428a208f98c01887c8 /emu/MacOSX/deveia.c 4a23ceb465365ae69b1b5057d28952c8 /emu/MacOSX/emu-386 e5dab3c884949529f0e1732ab432b016 /emu/MacOSX/mkfile 76175936eec899e36639a62bd2b616c0 /emu/MacOSX/mkfile-386 2a419741b4b58aa8b93cdc2a51a9ef07 /emu/MacOSX/mkfile-power b8fc34762291eb61f513a9ee0588bcf5 /emu/MacOSX/os-mach.c 59aa039455a9398969d99653b028dfd3 /emu/MacOSX/os.c dadd25f0fe7ff851b0d60b09532ef77b /emu/mkfile 7cce6fa744ff317a71c47794b1d75e79 /emu/port 00000000000000000000000000000000 /emu/port/devcons.c 402348d12f9f12f720a22781ebd36dcd /emu/port/main.c 31558a920c23bb885dd73f8f0fb1ba77 /lib9 00000000000000000000000000000000 /lib9/getcallerpc-MacOSX-386.s 347f8177b14fcf89909cd60f97aade76 /lib9/mkfile-MacOSX b948272bae83103fffbc7e70be354cde /lib9/sbrk-MacOSX.c fce061f4d6667e1728c5e6e69c77427a /libdraw 00000000000000000000000000000000 /libdraw/mkfile-MacOSX 16fc59d2cc2358409c06f71fc67267cf /libinterp 00000000000000000000000000000000 /libinterp/dlm-MacOSX.c 2e0ebad1f391b751f403c764acae0037 /libinterp/load.c d2527a0c033c8692ecd1aa6e0329ab3c /libmath 00000000000000000000000000000000 /libmath/FPcontrol-MacOSX.c f4d0b09575f7ae5befe00ee19cbb0e65 /libmath/mkfile 92aa0484dcf47c8e813096ca5f6fe3ed /libmath/mkfile-MacOSX dc2758d9b5342a6e375b2359f32124ec /limbo 00000000000000000000000000000000 /limbo/mkfile-MacOSX d931caf0d6d532c18e31c311a4071894 /mkfiles 00000000000000000000000000000000 /mkfiles/mkfile-MacOSX-386 414b7dde332152fef3a828a46a4fcea5 /mkfiles/mkfile-MacOSX-power 5f4eb876b3cddad2cff5fb12cb6c9261 /mkfiles/mkhost-MacOSX c894c8eef8e766dd669b1f861498c10c /utils 00000000000000000000000000000000 /utils/iar 00000000000000000000000000000000 /utils/iar/MacOSX.c 01867b8f2ff869d854b33ed8262b0390 /utils/mkfile 10e2f7b261e40cb70520a6ff352277e7 /utils/srclist 00000000000000000000000000000000 /utils/srclist/MacOSX.c 5152171b40a0630826eff6e5e1cc04ec /emu 20000000775 inferno inf 1141360866 0 /emu/port 20000000775 inferno inf 1141698841 0 /emu/port/devcons.c 664 inferno inf 1141832295 11070 #include "dat.h" #include "fns.h" #include "error.h" #include "version.h" #include "mp.h" #include "libsec.h" #include "keyboard.h" extern int cflag; extern int exdebug; extern int keepbroken; enum { Qdir, Qcons, Qconsctl, Qdrivers, Qhostowner, Qhoststdin, Qhoststdout, Qhoststderr, Qjit, Qkeyboard, Qkprint, Qmemory, Qmsec, Qnotquiterandom, Qnull, Qpin, Qrandom, Qscancode, Qsysctl, Qsysname, Qtime, Quser }; Dirtab contab[] = { ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, "cons", {Qcons}, 0, 0666, "consctl", {Qconsctl}, 0, 0222, "drivers", {Qdrivers}, 0, 0444, "hostowner", {Qhostowner}, 0, 0644, "hoststdin", {Qhoststdin}, 0, 0444, "hoststdout", {Qhoststdout}, 0, 0222, "hoststderr", {Qhoststderr}, 0, 0222, "jit", {Qjit}, 0, 0666, "keyboard", {Qkeyboard}, 0, 0666, "kprint", {Qkprint}, 0, 0444, "memory", {Qmemory}, 0, 0444, "msec", {Qmsec}, NUMSIZE, 0444, "notquiterandom", {Qnotquiterandom}, 0, 0444, "null", {Qnull}, 0, 0666, "pin", {Qpin}, 0, 0666, "random", {Qrandom}, 0, 0444, "scancode", {Qscancode}, 0, 0444, "sysctl", {Qsysctl}, 0, 0644, "sysname", {Qsysname}, 0, 0644, "time", {Qtime}, 0, 0644, "user", {Quser}, 0, 0644, }; Queue* gkscanq; /* Graphics keyboard raw scancodes */ char* gkscanid; /* name of raw scan format (if defined) */ Queue* gkbdq; /* Graphics keyboard unprocessed input */ Queue* kbdq; /* Console window unprocessed keyboard input */ Queue* lineq; /* processed console input */ char *ossysname; static struct { RWlock l; Queue* q; } kprintq; vlong timeoffset; extern int dflag; static int sysconwrite(void*, ulong); extern char** rebootargv; static struct { QLock q; QLock gq; /* separate lock for the graphical input */ int raw; /* true if we shouldn't process input */ Ref ctl; /* number of opens to the control file */ Ref ptr; /* number of opens to the ptr file */ int scan; /* true if reading raw scancodes */ int x; /* index into line */ char line[1024]; /* current input line */ Rune c; int count; } kbd; void kbdslave(void *a) { char b; USED(a); for(;;) { b = readkbd(); if(kbd.raw == 0) write(1, &b, 1); qproduce(kbdq, &b, 1); } pexit("kbdslave", 0); } void gkbdputc(Queue *q, int ch) { int n; Rune r; static uchar kc[5*UTFmax]; static int nk, collecting = 0; char buf[UTFmax]; r = ch; if(r == Latin) { collecting = 1; nk = 0; return; } if(collecting) { int c; nk += runetochar((char*)&kc[nk], &r); c = latin1(kc, nk); if(c < -1) /* need more keystrokes */ return; collecting = 0; if(c == -1) { /* invalid sequence */ qproduce(q, kc, nk); return; } r = (Rune)c; } n = runetochar(buf, &r); if(n == 0) return; /* if(!isdbgkey(r)) */ qproduce(q, buf, n); } void consinit(void) { kbdq = qopen(512, 0, 0, 0); if(kbdq == 0) panic("no memory"); lineq = qopen(512, 0, 0, 0); if(lineq == 0) panic("no memory"); gkbdq = qopen(512, 0, 0, 0); if(gkbdq == 0) panic("no memory"); randominit(); } /* * return true if current user is eve */ int iseve(void) { return strcmp(eve, up->env->user) == 0; } static Chan* consattach(char *spec) { static int kp; if (kp == 0 && !dflag) { kproc("kbd", kbdslave, 0, 0); kp = 1; } return devattach('c', spec); } static Walkqid* conswalk(Chan *c, Chan *nc, char **name, int nname) { return devwalk(c, nc, name, nname, contab, nelem(contab), devgen); } static int consstat(Chan *c, uchar *db, int n) { return devstat(c, db, n, contab, nelem(contab), devgen); } static Chan* consopen(Chan *c, int omode) { c = devopen(c, omode, contab, nelem(contab), devgen); switch((ulong)c->qid.path) { case Qconsctl: incref(&kbd.ctl); break; case Qscancode: qlock(&kbd.gq); if(gkscanq || !gkscanid) { qunlock(&kbd.q); c->flag &= ~COPEN; if(gkscanq) error(Einuse); else error(Ebadarg); } gkscanq = qopen(256, 0, nil, nil); qunlock(&kbd.gq); break; case Qkprint: wlock(&kprintq.l); if(kprintq.q != nil){ wunlock(&kprintq.l); c->flag &= ~COPEN; error(Einuse); } kprintq.q = qopen(32*1024, 0, 0, 0); if(kprintq.q == nil){ wunlock(&kprintq.l); c->flag &= ~COPEN; error(Enomem); } qnoblock(kprintq.q, 1); wunlock(&kprintq.l); break; } return c; } static void consclose(Chan *c) { if((c->flag & COPEN) == 0) return; switch((ulong)c->qid.path) { case Qconsctl: if(decref(&kbd.ctl) == 0) kbd.raw = 0; break; case Qscancode: qlock(&kbd.gq); if(gkscanq) { qfree(gkscanq); gkscanq = 0; } qunlock(&kbd.gq); break; case Qkprint: wlock(&kprintq.l); qfree(kprintq.q); kprintq.q = nil; wunlock(&kprintq.l); break; } } static long consread(Chan *c, void *va, long count, vlong offset) { int i, n, ch, eol; char *p, buf[64]; if(c->qid.type & QTDIR) return devdirread(c, va, count, contab, nelem(contab), devgen); switch((ulong)c->qid.path) { default: error(Egreg); case Qsysctl: return readstr(offset, va, count, VERSION); case Qsysname: if(ossysname == nil) return 0; return readstr(offset, va, count, ossysname); case Qrandom: return randomread(va, count); case Qnotquiterandom: genrandom(va, count); return count; case Qpin: p = "pin set"; if(up->env->pgrp->pin == Nopin) p = "no pin"; return readstr(offset, va, count, p); case Qhostowner: return readstr(offset, va, count, eve); case Qhoststdin: return read(0, va, count); /* should be pread */ case Quser: return readstr(offset, va, count, up->env->user); case Qjit: snprint(buf, sizeof(buf), "%d", cflag); return readstr(offset, va, count, buf); case Qtime: snprint(buf, sizeof(buf), "%.lld", timeoffset + osusectime()); return readstr(offset, va, count, buf); case Qdrivers: p = malloc(READSTR); if(p == nil) error(Enomem); n = 0; for(i = 0; devtab[i] != nil; i++) n += snprint(p+n, READSTR-n, "#%C %s\n", devtab[i]->dc, devtab[i]->name); n = readstr(offset, va, count, p); free(p); return n; case Qmemory: return poolread(va, count, offset); case Qnull: return 0; case Qmsec: return readnum(offset, va, count, osmillisec(), NUMSIZE); case Qcons: qlock(&kbd.q); if(waserror()){ qunlock(&kbd.q); nexterror(); } if(dflag) error(Enonexist); while(!qcanread(lineq)) { qread(kbdq, &kbd.line[kbd.x], 1); ch = kbd.line[kbd.x]; if(kbd.raw){ qiwrite(lineq, &kbd.line[kbd.x], 1); continue; } eol = 0; switch(ch) { case '\b': if(kbd.x) kbd.x--; break; case 0x15: kbd.x = 0; break; case '\n': case 0x04: eol = 1; default: kbd.line[kbd.x++] = ch; break; } if(kbd.x == sizeof(kbd.line) || eol){ if(ch == 0x04) kbd.x--; qwrite(lineq, kbd.line, kbd.x); kbd.x = 0; } } n = qread(lineq, va, count); qunlock(&kbd.q); poperror(); return n; case Qscancode: if(offset == 0) return readstr(0, va, count, gkscanid); else return qread(gkscanq, va, count); case Qkeyboard: return qread(gkbdq, va, count); case Qkprint: rlock(&kprintq.l); if(waserror()){ runlock(&kprintq.l); nexterror(); } n = qread(kprintq.q, va, count); poperror(); runlock(&kprintq.l); return n; } } static long conswrite(Chan *c, void *va, long count, vlong offset) { char buf[128]; int x; USED(offset); if(c->qid.type & QTDIR) error(Eperm); switch((ulong)c->qid.path) { default: error(Egreg); case Qcons: if(canrlock(&kprintq.l)){ if(kprintq.q != nil){ if(waserror()){ runlock(&kprintq.l); nexterror(); } qwrite(kprintq.q, va, count); poperror(); runlock(&kprintq.l); return count; } runlock(&kprintq.l); } return write(1, va, count); case Qsysctl: return sysconwrite(va, count); case Qconsctl: if(count >= sizeof(buf)) count = sizeof(buf)-1; strncpy(buf, va, count); buf[count] = 0; if(strncmp(buf, "rawon", 5) == 0) { kbd.raw = 1; return count; } else if(strncmp(buf, "rawoff", 6) == 0) { kbd.raw = 0; return count; } error(Ebadctl); case Qkeyboard: for(x=0; xenv->pgrp->pin != Nopin) error("pin already set"); if(count >= sizeof(buf)) count = sizeof(buf)-1; strncpy(buf, va, count); buf[count] = '\0'; up->env->pgrp->pin = atoi(buf); return count; case Qtime: if(count >= sizeof(buf)) count = sizeof(buf)-1; strncpy(buf, va, count); buf[count] = '\0'; timeoffset = strtoll(buf, 0, 0)-osusectime(); return count; case Quser: if(count >= sizeof(buf)) error(Ebadarg); strncpy(buf, va, count); buf[count] = '\0'; if(count > 0 && buf[count-1] == '\n') buf[--count] = '\0'; if(count == 0) error(Ebadarg); if(strcmp(up->env->user, eve) != 0) error(Eperm); setid(buf, 0); return count; case Qhostowner: if(count >= sizeof(buf)) error(Ebadarg); strncpy(buf, va, count); buf[count] = '\0'; if(count > 0 && buf[count-1] == '\n') buf[--count] = '\0'; if(count == 0) error(Ebadarg); if(strcmp(up->env->user, eve) != 0) error(Eperm); kstrdup(&eve, buf); return count; case Qhoststdout: return write(1, va, count); case Qhoststderr: return write(2, va, count); case Qjit: if(count >= sizeof(buf)) count = sizeof(buf)-1; strncpy(buf, va, count); buf[count] = '\0'; x = atoi(buf); if (x < 0 || x > 9) error(Ebadarg); cflag = x; return count; case Qsysname: if(count >= sizeof(buf)) count = sizeof(buf)-1; strncpy(buf, va, count); buf[count] = '\0'; kstrdup(&ossysname, buf); return count; } return 0; } static int sysconwrite(void *va, ulong count) { Cmdbuf *cb; int e; cb = parsecmd(va, count); if(waserror()){ free(cb); nexterror(); } if(cb->nf == 0) error(Enoctl); if(strcmp(cb->f[0], "reboot") == 0){ osreboot(rebootargv[0], rebootargv); error("reboot not supported"); }else if(strcmp(cb->f[0], "halt") == 0){ if(cb->nf > 1) e = atoi(cb->f[1]); else e = 0; cleanexit(e); /* XXX ignored for the time being (and should be a string anyway) */ }else if(strcmp(cb->f[0], "broken") == 0) keepbroken = 1; else if(strcmp(cb->f[0], "nobroken") == 0) keepbroken = 0; else if(strcmp(cb->f[0], "exdebug") == 0) exdebug = !exdebug; else error(Enoctl); poperror(); free(cb); return count; } Dev consdevtab = { 'c', "cons", consinit, consattach, conswalk, consstat, consopen, devcreate, consclose, consread, devbread, conswrite, devbwrite, devremove, devwstat }; static ulong randn; static void seedrand(void) { randomread((void*)&randn, sizeof(randn)); } int nrand(int n) { if(randn == 0) seedrand(); randn = randn*1103515245 + 12345 + osusectime(); return (randn>>16) % n; } int rand(void) { nrand(1); return randn; } ulong truerand(void) { ulong x; randomread(&x, sizeof(x)); return x; } QLock grandomlk; void _genrandomqlock(void) { qlock(&grandomlk); } void _genrandomqunlock(void) { qunlock(&grandomlk); } /emu/port/main.c 664 inferno inf 1141832591 7391 #include "dat.h" #include "fns.h" #include "error.h" #include "interp.h" #include "kernel.h" #include "draw.h" #include "version.h" int rebootargc = 0; char** rebootargv; static char *imod = "/dis/emuinit.dis"; extern char* hosttype; extern char* tkfont; /* for libtk/utils.c */ extern int tkstylus; /* libinterp/tk.c */ extern int mflag; int dflag; int vflag; int vflag; Procs procs; char *eve; int Xsize = 640; int Ysize = 480; int sflag; int qflag; int xtblbit; int globfs; ulong displaychan; extern char *cputype; static void usage(void) { fprint(2, "Usage: emu [options...] [file.dis [args...]]\n" "\t-gXxY\n" "\t-c[0-9]\n" "\t-b\n" "\t-d file.dis\n" "\t-s\n" "\t-v\n" "\t-p=maxsize\n" "\t-f\n" "\t-r\n" "\t-7\n" "\t-G\n" "\t-C\n" "\t-S\n"); exits("usage"); } static void envusage(void) { fprint(2, "emu: bad option in EMU environment variable (%s)\n", getenv("EMU")); usage(); } static int isnum(char *p) { if (*p == 0) return 0; while (*p) { if (*p < '0' || *p > '9') return 0; p++; } return 1; } static int geom(char *val) { char *p; int x, y; if (val == '\0' || (*val < '0' || *val > '9')) return 0; x = strtoul(val, &p, 0); if(x >= 64) Xsize = x; if (*p++ != 'x' || !isnum(p)) return 0; y = strtoul(p, &p, 0); if(y >= 48) Ysize = y; if (*p != '\0') return 0; return 1; } static void poolopt(char *str) { char *var; int n; ulong x; var = str; while(*str && *str != '=') str++; if(*str != '=' || str[1] == '\0') usage(); *str++ = '\0'; n = strlen(str); x = atoi(str); switch(str[n - 1]){ case 'k': case 'K': x *= 1024; break; case 'm': case 'M': x *= 1024*1024; break; } if(poolsetsize(var, x) == 0) usage(); } static void option(int argc, char *argv[], void (*badusage)(void)) { char *cp; ARGBEGIN { default: badusage(); case 'g': /* Window geometry */ if (geom(EARGF(badusage())) == 0) badusage(); break; case 'b': /* jit array bounds checking */ bflag = 1; break; case 'c': /* Compile on the fly */ cp = EARGF(badusage()); if (!isnum(cp)) badusage(); cflag = atoi(cp); if(cflag < 0|| cflag > 9) usage(); break; case 'I': /* (temporary option) run without cons */ dflag++; break; case 'd': /* run as a daemon */ dflag++; imod = EARGF(badusage()); break; case 's': /* No trap handling */ sflag++; break; case 'm': /* gc mark and sweep */ cp = EARGF(badusage()); if (!isnum(cp)) badusage(); mflag = atoi(cp); if(mflag < 0|| mflag > 9) usage(); break; case 'p': /* pool option */ poolopt(EARGF(badusage())); break; case 'f': /* Set font path */ tkfont = EARGF(badusage()); break; case 'r': /* Set inferno root */ strncpy(rootdir, EARGF(badusage()), sizeof(rootdir)-1); break; case '7': /* use 7 bit colormap in X */ xtblbit = 1; break; case 'G': /* allow global access to file system */ globfs = 1; break; case 'C': /* channel specification for display */ cp = EARGF(badusage()); displaychan = strtochan(cp); if(displaychan == 0){ fprint(2, "emu: invalid channel specifier (-C): %q\n", cp); exits("usage"); } break; case 'S': tkstylus = 1; break; case 'v': vflag = 1; /* print startup messages */ break; } ARGEND } static void savestartup(int argc, char *argv[]) { int i; rebootargc = argc; rebootargv = malloc((argc+1)*sizeof(char*)); if(rebootargv == nil) panic("can't save startup args"); for(i = 0; i < argc; i++) { rebootargv[i] = strdup(argv[i]); if(rebootargv[i] == nil) panic("can't save startup args"); } rebootargv[i] = nil; } void putenvq(char *name, char *val, int conf) { val = smprint("%q", val); ksetenv(name, val, conf); free(val); } void putenvqv(char *name, char **v, int n, int conf) { Fmt f; int i; char *val; fmtstrinit(&f); for(i=0; ienv; e->pgrp = newpgrp(); e->fgrp = newfgrp(nil); e->egrp = newegrp(); e->errstr = e->errbuf0; e->syserrstr = e->errbuf1; e->user = strdup(""); links(); chandevinit(); if(waserror()) panic("setting root and dot"); e->pgrp->slash = namec("#/", Atodir, 0, 0); cnameclose(e->pgrp->slash->name); e->pgrp->slash->name = newcname("/"); e->pgrp->dot = cclone(e->pgrp->slash); poperror(); strcpy(up->text, "main"); if(kopen("#c/cons", OREAD) != 0) fprint(2, "failed to make fd0 from #c/cons: %r\n"); kopen("#c/cons", OWRITE); kopen("#c/cons", OWRITE); /* the setid cannot precede the bind of #U */ kbind("#U", "/", MAFTER|MCREATE); setid(eve, 0); kbind("#^", "/dev", MBEFORE); /* snarf */ kbind("#^", "/chan", MBEFORE); kbind("#m", "/dev", MBEFORE); /* pointer */ kbind("#c", "/dev", MBEFORE); kbind("#p", "/prog", MREPL); kbind("#d", "/fd", MREPL); kbind("#I", "/net", MAFTER); /* will fail on Plan 9 */ /* BUG: we actually only need to do these on Plan 9 */ kbind("#U/dev", "/dev", MAFTER); kbind("#U/net", "/net", MAFTER); kbind("#U/net.alt", "/net.alt", MAFTER); if(cputype != nil) ksetenv("cputype", cputype, 1); putenvqv("emuargs", rebootargv, rebootargc, 1); putenvq("emuroot", rootdir, 1); ksetenv("emuhost", hosttype, 1); kproc("main", disinit, imod, KPDUPFDG|KPDUPPG|KPDUPENVG); for(;;) ospause(); } void errorf(char *fmt, ...) { va_list arg; char buf[PRINTSIZE]; va_start(arg, fmt); vseprint(buf, buf+sizeof(buf), fmt, arg); va_end(arg); error(buf); } void error(char *err) { if(err != up->env->errstr && up->env->errstr != nil) kstrcpy(up->env->errstr, err, ERRMAX); // ossetjmp(up->estack[NERR-1]); nexterror(); } void exhausted(char *resource) { char buf[64]; int n; n = snprint(buf, sizeof(buf), "no free %s\n", resource); iprint(buf); buf[n-1] = 0; error(buf); } void nexterror(void) { oslongjmp(nil, up->estack[--up->nerr], 1); } /* for dynamic modules - functions not macros */ void* waserr(void) { up->nerr++; return up->estack[up->nerr-1]; } void poperr(void) { up->nerr--; } char* enverror(void) { return up->env->errstr; } void panic(char *fmt, ...) { va_list arg; char buf[512]; va_start(arg, fmt); vseprint(buf, buf+sizeof(buf), fmt, arg); va_end(arg); fprint(2, "panic: %s\n", buf); if(sflag) abort(); cleanexit(0); } int iprint(char *fmt, ...) { int n; va_list va; char buf[1024]; va_start(va, fmt); n = vseprint(buf, buf+sizeof buf, fmt, va) - buf; va_end(va); write(1, buf, n); return 1; } void _assert(char *fmt) { panic("assert failed: %s", fmt); } void sysfatal(char *fmt, ...) { va_list arg; char buf[64]; va_start(arg, fmt); vsnprint(buf, sizeof(buf), fmt, arg); va_end(arg); panic("sysfatal: %s", buf); } void oserror(void) { oserrstr(up->env->errstr, ERRMAX); error(up->env->errstr); } /emu/MacOSX 20000000775 inferno inf 1141888102 0 /emu/MacOSX/asm-386.s 664 inferno inf 1141832699 326 /* * File: asm-386.s */ .globl _FPsave _FPsave: pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax fstenv (%eax) popl %ebp ret .globl _FPrestore _FPrestore: pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax fldenv (%eax) popl %ebp ret .globl __tas __tas: movl $1, %eax movl 4(%esp), %ecx xchgl %eax, 0(%ecx) ret /emu/MacOSX/deveia.c 664 inferno inf 1141360215 5044 /* * Darwin serial port definitions, uses IOKit to build sysdev * Loosely based on FreeBSD/deveia.c * Copyright © 1998, 1999 Lucent Technologies Inc. All rights reserved. * Revisions Copyright © 1999, 2000 Vita Nuova Limited. All rights reserved. * Revisions Copyright © 2003 Corpus Callosum Corporation. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include #define B14400 14400 #define B28800 28800 #define B57600 57600 #define B76800 76800 #define B115200 115200 #define B230400 230400 extern int vflag; // #define MAXDEV 8 // static char *sysdev[MAXDEV]; static char **sysdev = NULL; #include #include static void _buildsysdev(void); #define buildsysdev() _buildsysdev() /* for deveia-posix.c */ static void _buildsysdev(void) { kern_return_t kernResult; mach_port_t masterPort; CFMutableDictionaryRef classesToMatch; io_iterator_t serialPortIterator; io_object_t serialDevice; CFMutableArrayRef array; CFIndex idx; kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort); if (KERN_SUCCESS != kernResult) { printf("IOMasterPort returned %d\n", kernResult); } else { classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue); if (classesToMatch == NULL) { printf("IOServiceMatching returned a NULL dictionary.\n"); } else { CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes)); } kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch, &serialPortIterator); if (KERN_SUCCESS != kernResult) { printf("IOServiceGetMatchingServices returned %d\n", kernResult); } else { array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); while ((serialDevice = IOIteratorNext(serialPortIterator))) { CFTypeRef bsdPathAsCFString; bsdPathAsCFString = IORegistryEntryCreateCFProperty(serialDevice, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0); if (bsdPathAsCFString) { CFArrayAppendValue(array, bsdPathAsCFString); } (void) IOObjectRelease(serialDevice); } idx = CFArrayGetCount(array); if (idx > 0) { char bsdPath[MAXPATHLEN]; const char *tmpsysdev; CFIndex i, j; sysdev = (char **)malloc((idx+1)*sizeof(char*)); for (i=j=0; isi_code, siginfo->si_addr,*(char*)siginfo->si_addr); } void trapSEGV(int signo, siginfo_t *info, void *context) { USED(signo); USED(context); if(info) print("trapSEGV: signo: %d code: %d addr: %lx\n", info->si_signo, info->si_code, info->si_addr); else print("trapSEGV: no info\n"); disfault(nil, "Segmentation violation"); } void trapFPE(int signo, siginfo_t *info, void *context) { USED(signo); USED(context); if(info) print("trapFPE: signo: %d code: %d addr: %lx\n", info->si_signo, info->si_code, info->si_addr); else print("trapFPE: no info\n"); disfault(nil, "Floating point exception"); } sigset_t set; void setsigs() { struct sigaction act; memset(&act, 0 , sizeof(act)); sigemptyset(&set); act.sa_handler=SIG_IGN; if(sigaction(SIGPIPE, &act, nil)) panic("can't ignore sig pipe"); act.sa_sigaction=trapUSR1; sigaction(SIGUSR1, &act, nil); /* For the correct functioning of devcmd in the * face of exiting slaves */ signal(SIGPIPE, SIG_IGN); signal(SIGTERM, cleanexit); if(sflag == 0) { act.sa_sigaction = trapBUS; act.sa_flags |= SA_SIGINFO; if(sigaction(SIGBUS, &act, nil)) panic("sigaction SIGBUS"); act.sa_sigaction = trapILL; if(sigaction(SIGILL, &act, nil)) panic("sigaction SIGILL"); act.sa_sigaction = trapSEGV; if(sigaction(SIGSEGV, &act, nil)) panic("sigaction SIGSEGV"); act.sa_sigaction = trapFPE; if(sigaction(SIGFPE, &act, nil)) panic("sigaction SIGFPE"); /* * prevent Zombies forming when any process terminates */ act.sa_sigaction = 0; act.sa_flags |= SA_NOCLDWAIT; if(sigaction(SIGCHLD, &act, nil)) panic("sigaction SIGCHLD"); if(sigaddset(&set, SIGINT) == -1) panic("sigaddset"); signal(SIGINT, cleanexit); } else { act.sa_sigaction=printILL; act.sa_flags=SA_SIGINFO; sigaction(SIGILL, &act, nil); } if(sigprocmask(SIG_BLOCK, &set, nil)!= 0) panic("sigprocmask"); } void tramp(void *arg) { Proc *p = arg; // ProcThreadNode *pt; p->pid = p->sigid = mach_thread_self(); sigprocmask(SIG_BLOCK, &set, nil); if(pthread_setspecific(prdakey, p)) { print("set specific data failed in tramp\n"); pthread_exit(0); } (*p->func)(p->arg); pexit("{Tramp}", 0); _exit(0); // lock(&proclist.l); // pt = _procthread(mach_thread_self(), proclist.free); // if (pt == NULL) { // _addPTNode(p, mach_thread_self()); // } else if (pt->proc == NULL) { // pt->proc = p; // } // unlock(&proclist.l); } static void threadsleep(ulong secs) { osmillisleep(secs * 1000); // sleep(secs); } /* Mach Thread version */ int kproc(char *name, void (*func)(void*), void *arg, int flags) { Proc *p, *pa; Pgrp *pg; Fgrp *fg; Egrp *eg; void *tos; pa = up; p = newproc(); if(flags & KPDUPPG) { pg = pa->env->pgrp; incref(&pg->r); p->env->pgrp = pg; } if(flags & KPDUPFDG) { fg = pa->env->fgrp; incref(&fg->r); p->env->fgrp = fg; } if(flags & KPDUPENVG) { eg = pa->env->egrp; incref(&eg->r); p->env->egrp = eg; } p->env->uid = pa->env->uid; p->env->gid = pa->env->gid; kstrdup(&p->env->user, pa->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); p->kstack = stackalloc(p, &tos); { kern_return_t kr; thread_t thread = MACH_PORT_NULL; kr = thread_create(mach_task_self(), &thread); if (kr != KERN_SUCCESS) panic("kproc: thread_create failure"); else { unsigned int count; #if defined(__ppc__) struct ppc_thread_state state = {0}; struct ppc_thread_state *ts = &state; count = PPC_THREAD_STATE_COUNT; kr = thread_get_state(thread, PPC_THREAD_STATE, (thread_state_t) &state, &count); if (kr != KERN_SUCCESS) { panic("kproc: thread_get_state failure"); } ts->srr0 = (int)tramp; ts->r1 = (uintptr_t)tos - C_ARGSAVE_LEN - C_RED_ZONE; ts->r3 = (unsigned int)p; kr = thread_set_state(thread, PPC_THREAD_STATE, (thread_state_t) &state, PPC_THREAD_STATE_COUNT); if (kr != KERN_SUCCESS) { panic("kproc: thread_set_state failure"); } p->pid = thread; // lock(&proclist.l); // _addPTNode(p, thread); // unlock(&proclist.l); kr = thread_resume(thread); if (kr != KERN_SUCCESS) panic("kproc: thread_resume failue"); } #else #error kproc thread creation not defined for this architecture #endif } return p->pid; } int segflush(void *va, ulong len) { kern_return_t err; vm_machine_attribute_val_t value = MATTR_VAL_ICACHE_FLUSH; err = vm_machine_attribute( (vm_map_t)mach_task_self(), (vm_address_t)va, (vm_size_t)len, MATTR_CACHE, &value); if (err != KERN_SUCCESS) { print("segflush: failure (%d) address %lud\n", err, va); } return (int)err; } /* from geoff collyer's port invalidate instruction cache and write back data cache from a to a+n-1, at least. void segflush(void *a, ulong n) { ulong *p; // paranoia, flush the world __asm__("isync\n\t" "eieio\n\t" : // no output : ); // cache blocks are often eight words (32 bytes) long, sometimes 16 bytes. // need to determine it dynamically? for (p = (ulong *)((ulong)a & ~3UL); (char *)p < (char *)a + n; p++) __asm__("dcbst 0,%0\n\t" // not dcbf, which writes back, then invalidates "icbi 0,%0\n\t" : // no output : "ar" (p) ); __asm__("isync\n\t" "eieio\n\t" : // no output : ); } */ /* Mach Thread version */ void oshostintr(Proc *p) { thread_terminate(p->sigid); } static ulong erendezvous(void*, ulong); void osblock(void) { erendezvous(up, 0); } void osready(Proc *p) { erendezvous(p, 0); } void oslongjmp(void *regs, osjmpbuf env, int val) { USED(regs); siglongjmp(env, val); } struct termios tinit; static void termset(void) { struct termios t; tcgetattr(0, &t); tinit = t; t.c_lflag &= ~(ICANON|ECHO|ISIG); t.c_cc[VMIN] = 1; t.c_cc[VTIME] = 0; tcsetattr(0, TCSANOW, &t); } static void termrestore(void) { tcsetattr(0, TCSANOW, &tinit); } void cleanexit(int x) { USED(x); if(up->intwait) { up->intwait = 0; return; } if(dflag == 0) termrestore(); // kill(0, SIGKILL); exit(0); } void osreboot(char *file, char **argv) { if(dflag == 0) termrestore(); execvp(file, argv); panic("reboot failure"); } int gidnobody= -1, uidnobody= -1; void getnobody() { struct passwd *pwd; if((pwd = getpwnam("nobody"))) { uidnobody = pwd->pw_uid; gidnobody = pwd->pw_gid; } } /* Mach Thread version */ void libinit(char *imod) { struct passwd *pw; struct Proc *p; struct sigaction oldact; char sys[64]; void *tos; setsid(); // host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &clock_port); // setup personality gethostname(sys, sizeof(sys)); kstrdup(&ossysname, sys); getnobody(); if(dflag == 0) termset(); setsigs(); if(sigaction(SIGBUS, nil, &oldact)) { panic("sigaction failed"); } if(oldact.sa_sigaction != trapBUS && sflag == 0) panic("1st old act sa_handler"); if(pthread_key_create(&prdakey,NULL)) print("key_create failed\n"); p = newproc(); p->kstack = stackalloc(p, &tos); if (p == nil || p->kstack == nil) panic("libinit: no memory"); // _addPTNode(p, mach_thread_self()); pw = getpwuid(getuid()); if(pw != nil) { if (strlen(pw->pw_name) + 1 <= KNAMELEN) strcpy(eve, pw->pw_name); else print("pw_name too long\n"); } else print("cannot getpwuid\n"); p->env->uid = getuid(); p->env->gid = getgid(); if(pthread_setspecific(prdakey, p)) panic("set specific thread data failed\n"); emuinit(imod); } int readkbd(void) { int n; char buf[1]; n = read(0, buf, sizeof(buf)); if(n != 1) { print("keyboard close (n=%d, %s)\n", n, strerror(errno)); pexit("keyboard thread", 0); } switch(buf[0]) { case '\r': buf[0] = '\n'; break; case DELETE: cleanexit(0); break; } return buf[0]; } enum { NHLOG = 7, NHASH = (1<hash) { if(t->tag == tag) { rval = t->val; t->val = value; t->tag = 0; unlock(&hlock); semaphore_signal(t->sema); return rval; } } /* create a tag if there is none in the free list */ t = ft; if(t == nil) { /* create the tag */ t = malloc(sizeof(Tag)); if(t == nil) panic("rendezvous: no memory"); } else ft = t->free; /* get tag from free list */ /* setup tag */ t->tag = tag; t->val = value; t->hash = *l; *l = t; /* Mach thread version */ semaphore_create(mach_task_self(), &t->sema, SYNC_POLICY_FIFO, 0); unlock(&hlock); /* wait on semaphore ignoring all EINTR's */ /* Mach thread version */ semaphore_wait(t->sema); lock(&hlock); rval = t->val; for(f = *l; f; f = f->hash){ if(f == t) { *l = f->hash; break; } l = &f->hash; } /* add tag to free list */ t->free = ft; ft = t; unlock(&hlock); return rval; } typedef struct Targ Targ; struct Targ { int fd; int* spin; char* cmd; }; void closeall(int fd) { int nfd, i; nfd = getdtablesize(); for(i = 0; i < nfd; i++) if(i != fd) close(i); } /* old port? int exectramp(Targ *targ) { int fd, error; char *argv[4], buf[MAXDEVCMD]; fd = targ->fd; strncpy(buf, targ->cmd, sizeof(buf)-1); buf[sizeof(buf)-1] = '\0'; argv[0] = "/bin/sh"; argv[1] = "-c"; argv[2] = buf; argv[3] = nil; print("devcmd: '%s'", buf); switch(fork()) { case -1: print("%s\n",strerror(errno)); return -1; default: print(" pid %d\n", getpid()); return 0; case 0: closeall(fd); dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); close(fd); error=0; if(up->env->gid != -1) error=setgid(up->env->gid); else error=setgid(gidnobody); if((error)&&(geteuid()==0)) { print("devcmd: root can't set gid: %d or gidnobody: %d\n", up->env->gid,gidnobody); _exit(0); } error=0; if(up->env->uid != -1) error=setuid(up->env->uid); else error=setuid(uidnobody); if((error)&&(geteuid()==0)) { print("devcmd: root can't set uid: %d or uidnobody: %d\n", up->env->uid,uidnobody); _exit(0); } execv(argv[0], argv); print("%s\n",strerror(errno)); // don't flush buffered i/o twice _exit(0); } panic("exectramp: continued to end"); return 0; } extern int bipipe(int fd[2]); int oscmd(char *cmd, int *rfd, int *sfd) { Targ targ; int r, fd[2]; if(bipipe(fd) < 0) return -1; signal(SIGCHLD, SIG_IGN); targ.fd = fd[0]; targ.cmd = cmd; r = 0; if (exectramp(&targ) < 0) { r = -1; } close(fd[0]); *rfd = fd[1]; *sfd = fd[1]; return r; } */ /* * Return an abitrary millisecond clock time */ long osmillisec(void) { static long sec0 = 0, usec0; struct timeval t; if(gettimeofday(&t,(struct timezone*)0)<0) return(0); if(sec0==0) { sec0 = t.tv_sec; usec0 = t.tv_usec; } return((t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000); } /* * Return the time since the epoch in nanoseconds and microseconds * The epoch is defined at 1 Jan 1970 */ vlong osnsec(void) { struct timeval t; gettimeofday(&t, nil); return (vlong)t.tv_sec*1000000000L + t.tv_usec*1000; } vlong osusectime(void) { struct timeval t; gettimeofday(&t, nil); return (vlong)t.tv_sec * 1000000 + t.tv_usec; } int osmillisleep(ulong milsec) { kern_return_t kr; mach_timespec_t time; time.tv_sec = milsec / 1000; time.tv_nsec = (milsec % 1000) * 1000000; // if(nanosleep(&time, 0) == -1) // panic("nanosleep failed\n"); // kr = clock_sleep(clock_port, TIME_ABSOLUTE, time, NULL); // if (kr != KERN_SUCCESS) // panic("clock_sleep failed\n"); usleep(milsec * 1000); return 0; } int limbosleep(ulong milsec) { return osmillisleep(milsec); } /* Mach thread version */ static struct { Lock l; void *free; } stacklist; static void _stackfree(void *stack) { *((void **)stack) = stacklist.free; stacklist.free = stack; } static void stackfreeandexit(void *stack) { vm_address_t addr = (vm_address_t)stack; vm_size_t size = KSTACK + vm_page_size; lock(&stacklist.l); _stackfree(stack); unlock(&stacklist.l); vm_deallocate(mach_task_self(), addr, size); thread_terminate(mach_thread_self()); } #if defined(__ppc__) static const vm_address_t THREAD_STACK_HINT = 0xF0000000; #elif defined(__i386__) static const vm_address_t THREAD_STACK_HINT = 0xB0000000; #else #error Need to define a stack address hint for this architecture #endif static void * stackalloc(Proc *p, void **tos) { // void *rv; vm_size_t size = KSTACK + vm_page_size; // lock(&stacklist.l); // if (stacklist.free == 0) { kern_return_t kr; // int x; *((vm_address_t *)tos) = THREAD_STACK_HINT; kr = vm_map(mach_task_self(), (vm_address_t *)tos, size, vm_page_size-1, VM_MAKE_TAG(VM_MEMORY_STACK)| VM_FLAGS_ANYWHERE, MEMORY_OBJECT_NULL, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT); if (kr != KERN_SUCCESS) kr = vm_allocate(mach_task_self(), (vm_address_t *)tos, size, VM_MAKE_TAG(VM_MEMORY_STACK)| VM_FLAGS_ANYWHERE); if (kr != KERN_SUCCESS) { panic("stackalloc: no more stacks"); } #ifdef STACK_GROWS_UP // The guard page is the page one higher than the stack // The stack base is at the lowest address kr = vm_protect(mach_task_self(), *tos + KSTACK, vm_page_size, FALSE, VM_PROT_NONE); #else // The guard page is at the lowest address // The stack base is the highest address kr = vm_protect(mach_task_self(), (vm_address_t)*tos, vm_page_size, FALSE, VM_PROT_NONE); #endif // _stackfree((char *)tos); // free all the new stacks onto the freelist // for (x = 0; x < NSTACKSPERALLOC; x++) // _stackfree((char *)stack + (size) * x); // } // rv = stacklist.free; // stacklist.free = *(void **)rv; // unlock(&stacklist.l); // *tos = rv + (size) - sizeof(void *); // *(Proc **)rv = p; // return rv; *tos += size; return tos; } void osyield(void) { thread_switch(mach_thread_self(), SWITCH_OPTION_DEPRESS, 0); } void ospause(void) { for(;;) threadsleep(3600); } void oslopri(void) { setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS,0)+4); } /* static Rb rb; extern int rbnotfull(void*); void osspin(Rendez *prod) { for(;;){ if((rb.randomcount & 0xffff) == 0 && !rbnotfull(0)) { Sleep(prod, rbnotfull, 0); } rb.randomcount++; } } Rb* osraninit(void) { return &rb; } void oswakeupproducer(Rendez *rendez) { Wakeup(rendez); } */ /emu/MacOSX/os.c 664 inferno inf 1141833267 14124 /* * Loosely based on FreeBSD/os.c and Solaris/os.c * Copyright © 1998, 1999 Lucent Technologies Inc. All rights reserved. * Revisions Copyright © 1999, 2000 Vita Nuova Limited. All rights reserved. * Revisions Copyright © 2002, 2003 Corpus Callosum Corporation. All rights reserved. */ #include "dat.h" #include "fns.h" #include "error.h" #undef _POSIX_C_SOURCE #undef getwd #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__ppc__) #include #elif defined (__i386__) #include #endif enum { KSTACK = 32 * 1024, DELETE = 0x7F }; char *hosttype = "MacOSX"; #if defined(__ppc__) char *cputype = "power"; #elif defined (__i386__) char *cputype = "386"; #endif static pthread_key_t prdakey; extern int dflag; Proc * getup(void) { return (Proc *)pthread_getspecific(prdakey); } /* Pthread version */ void pexit(char *msg, int t) { Osenv *e; Proc *p; USED(t); USED(msg); lock(&procs.l); p = up; if(p->prev) p->prev->next = p->next; else procs.head = p->next; if(p->next) p->next->prev = p->prev; else procs.tail = p->prev; unlock(&procs.l); if(0) print("pexit: %s: %s\n", p->text, msg); e = p->env; if(e != nil) { closefgrp(e->fgrp); closepgrp(e->pgrp); closeegrp(e->egrp); closesigs(e->sigs); } free(e->user); free(p->prog); free(p); pthread_exit(0); } void trapBUS(int signo, siginfo_t *info, void *context) { if(info) print("trapBUS: signo: %d code: %d addr: %lx\n", info->si_signo, info->si_code, info->si_addr); else print("trapBUS: no info\n"); disfault(nil, "Bus error"); } void trapUSR1(int signo) { int intwait; USED(signo); intwait = up->intwait; up->intwait = 0; /* clear it to let proc continue in osleave */ if(up->type != Interp) /* Used to unblock pending I/O */ return; if(intwait == 0) /* Not posted so its a sync error */ disfault(nil, Eintr); /* Should never happen */ } void trapUSR2(int signo) { USED(signo); /* we've done our work of interrupting sigsuspend */ } void trapILL(int signo) { USED(signo); disfault(nil, "Illegal instruction"); } /* from geoff collyer's port */ void printILL(int sig, siginfo_t *siginfo, void *v) { USED(sig); USED(v); panic("Illegal instruction with code=%d at address=%x, opcode=%x.\n" ,siginfo->si_code, siginfo->si_addr,*(char*)siginfo->si_addr); } void trapSEGV(int signo) { USED(signo); disfault(nil, "Segmentation violation"); } void trapFPE(int signo) { USED(signo); disfault(nil, "Floating point exception"); } static sigset_t initmask; static void setsigs(void) { struct sigaction act; sigset_t mask; memset(&act, 0 , sizeof(act)); sigemptyset(&initmask); /* * For the correct functioning of devcmd in the * face of exiting slaves */ signal(SIGPIPE, SIG_IGN); /* prevent signal when devcmd child exits */ if(signal(SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, cleanexit); act.sa_handler = trapUSR1; act.sa_mask = initmask; sigaction(SIGUSR1, &act, nil); act.sa_handler = trapUSR2; sigaction(SIGUSR2, &act, nil); sigemptyset(&mask); sigaddset(&mask, SIGUSR2); sigaddset(&initmask, SIGUSR2); sigprocmask(SIG_BLOCK, &mask, NULL); /* * prevent Zombies forming when any process terminates */ act.sa_sigaction = 0; act.sa_flags |= SA_NOCLDWAIT; if(sigaction(SIGCHLD, &act, nil)) panic("sigaction SIGCHLD"); if(sflag == 0) { act.sa_sigaction = trapBUS; act.sa_flags |= SA_SIGINFO; if(sigaction(SIGBUS, &act, nil)) panic("sigaction SIGBUS"); act.sa_handler = trapILL; if(sigaction(SIGILL, &act, nil)) panic("sigaction SIGBUS"); act.sa_handler = trapSEGV; if(sigaction(SIGSEGV, &act, nil)) panic("sigaction SIGSEGV"); if(sigaddset(&initmask, SIGINT) == -1) panic("sigaddset"); act.sa_handler = trapFPE; if(sigaction(SIGFPE, &act, nil)) panic("sigaction SIGFPE"); // if(signal(SIGINT, SIG_IGN) != SIG_IGN) { // print("cleanexit\n"); // signal(SIGINT, cleanexit); // } } if(sigprocmask(SIG_BLOCK, &initmask, nil)!= 0) panic("sigprocmask"); } /* -- original void * tramp(void *arg) { Proc *p = arg; p->pid = p->sigid = (long)pthread_self(); // p->pid = p->sigid = (pthread_self())->__sig; // fails on release/free sigprocmask(SIG_BLOCK, &initmask, nil); if(pthread_setspecific(prdakey, arg)) { print("set specific data failed in tramp\n"); pthread_exit(0); } p->func(p->arg); pexit("{Tramp}", 0); return NULL; } */ void * tramp(void *arg) { Proc *p = arg; p->sigid = (int)pthread_self(); p->pid = p->sigid; sigprocmask(SIG_BLOCK, &initmask, nil); if(pthread_setspecific(prdakey, arg)) { print("set specific data failed in tramp\n"); pthread_exit(0); } p->func(p->arg); pexit("{Tramp}", 0); return NULL; } int kproc(char *name, void (*func)(void*), void *arg, int flags) { pthread_t thread; Proc *p; Pgrp *pg; Fgrp *fg; Egrp *eg; pthread_attr_t attr; 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); up->kid = p; up->kidsp = p->kstack; if((pthread_attr_init(&attr))== -1) panic("pthread_attr_init failed"); errno=0; pthread_attr_setschedpolicy(&attr,SCHED_OTHER); if(errno) panic("pthread_attr_setschedpolicy failed"); pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if(pthread_create(&thread, &attr, tramp, p)) panic("thr_create failed\n"); pthread_attr_destroy(&attr); return (int)thread; } int segflush(void *va, ulong len) { kern_return_t err; vm_machine_attribute_val_t value = MATTR_VAL_ICACHE_FLUSH; err = vm_machine_attribute( (vm_map_t)mach_task_self(), (vm_address_t)va, (vm_size_t)len, MATTR_CACHE, &value); if (err != KERN_SUCCESS) { print("segflush: failure (%d) address %lud\n", err, va); } return (int)err; } /* from geoff collyer's port invalidate instruction cache and write back data cache from a to a+n-1, at least. void segflush(void *a, ulong n) { ulong *p; // paranoia, flush the world __asm__("isync\n\t" "eieio\n\t" : // no output : ); // cache blocks are often eight words (32 bytes) long, sometimes 16 bytes. // need to determine it dynamically? for (p = (ulong *)((ulong)a & ~3UL); (char *)p < (char *)a + n; p++) __asm__("dcbst 0,%0\n\t" // not dcbf, which writes back, then invalidates "icbi 0,%0\n\t" : // no output : "ar" (p) ); __asm__("isync\n\t" "eieio\n\t" : // no output : ); } */ void oshostintr(Proc *p) { pthread_kill((pthread_t)p->sigid, SIGUSR1); } static ulong erendezvous(void*, ulong); void osblock(void) { erendezvous(up, 0); } void osready(Proc *p) { erendezvous(p, 0); } void oslongjmp(void *regs, osjmpbuf env, int val) { USED(regs); siglongjmp(env, val); } struct termios tinit; static void termset(void) { struct termios t; tcgetattr(0, &t); tinit = t; t.c_lflag &= ~(ICANON|ECHO|ISIG); t.c_cc[VMIN] = 1; t.c_cc[VTIME] = 0; tcsetattr(0, TCSANOW, &t); } static void termrestore(void) { tcsetattr(0, TCSANOW, &tinit); } void cleanexit(int x) { USED(x); if(up->intwait) { up->intwait = 0; return; } if(dflag == 0) termrestore(); exit(0); } void osreboot(char *file, char **argv) { if(dflag == 0) termrestore(); execvp(file, argv); panic("reboot failure"); } int gidnobody= -1, uidnobody= -1; void getnobody() { struct passwd *pwd; if((pwd = getpwnam("nobody"))) { uidnobody = pwd->pw_uid; gidnobody = pwd->pw_gid; } } /* Pthread version */ static pthread_mutex_t rendezvouslock; static pthread_mutexattr_t *pthread_mutexattr_default = NULL; void libinit(char *imod) { struct passwd *pw; Proc *p; char sys[64]; setsid(); // setup personality gethostname(sys, sizeof(sys)); kstrdup(&ossysname, sys); getnobody(); if(dflag == 0) termset(); setsigs(); if(pthread_mutex_init(&rendezvouslock, pthread_mutexattr_default)) panic("pthread_mutex_init"); if(pthread_key_create(&prdakey,NULL)) print("key_create failed\n"); p = newproc(); if(pthread_setspecific(prdakey, p)) panic("set specific thread data failed\n"); pw = getpwuid(getuid()); if(pw != nil) kstrdup(&eve, pw->pw_name); else print("cannot getpwuid\n"); up->env->uid = getuid(); up->env->gid = getgid(); emuinit(imod); } int readkbd(void) { int n; char buf[1]; n = read(0, buf, sizeof(buf)); if(n < 0) print("keyboard close (n=%d, %s)\n", n, strerror(errno)); if(n <= 0) pexit("keyboard thread", 0); switch(buf[0]) { case '\r': buf[0] = '\n'; break; case DELETE: cleanexit(0); break; } return buf[0]; } enum { NHLOG = 7, NHASH = (1<next) { if(t->tag == tag) { rval = t->val; t->val = value; t->tag = 0; pthread_mutex_unlock(&rendezvouslock); // unlock(&hlock); if(pthread_cond_signal(&(t->cv))) panic("pthread_cond_signal"); return rval; } } t = ft; if(t == 0) { t = malloc(sizeof(Tag)); if(t == nil) panic("rendezvous: no memory"); if(pthread_cond_init(&(t->cv), NULL)) { print("pthread_cond_init (errno: %s) \n", strerror(errno)); panic("pthread_cond_init"); } } else ft = t->next; t->tag = tag; t->val = value; t->next = *l; *l = t; // pthread_mutex_unlock(&rendezvouslock); // unlock(&hlock); while(t->tag != nil) pthread_cond_wait(&(t->cv),&rendezvouslock); // pthread_mutex_lock(&rendezvouslock); // lock(&hlock); rval = t->val; for(f = *l; f; f = f->next){ if(f == t) { *l = f->next; break; } l = &f->next; } t->next = ft; ft = t; pthread_mutex_unlock(&rendezvouslock); // unlock(&hlock); return rval; } /* * Return an abitrary millisecond clock time */ long osmillisec(void) { static long sec0 = 0, usec0; struct timeval t; if(gettimeofday(&t, NULL)<0) return(0); if(sec0==0) { sec0 = t.tv_sec; usec0 = t.tv_usec; } return((t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000); } /* * Return the time since the epoch in nanoseconds and microseconds * The epoch is defined at 1 Jan 1970 */ vlong osnsec(void) { struct timeval t; gettimeofday(&t, nil); return (vlong)t.tv_sec*1000000000L + t.tv_usec*1000; } vlong osusectime(void) { struct timeval t; gettimeofday(&t, nil); return (vlong)t.tv_sec * 1000000 + t.tv_usec; } int osmillisleep(ulong milsec) { struct timespec time; time.tv_sec = milsec / 1000; time.tv_nsec = (milsec % 1000) * 1000000; nanosleep(&time, nil); return 0; } int limbosleep(ulong milsec) { return osmillisleep(milsec); } void osyield(void) { pthread_yield_np(); // sched_yield(); } void ospause(void) { for(;;) pause(); } void oslopri(void) { // pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param); setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS,0)+4); } /* moved to lib9 char* sbrk(int size) { void *brk; kern_return_t err; err = vm_allocate( (vm_map_t) mach_task_self(), (vm_address_t *)&brk, size, VM_FLAGS_ANYWHERE); if (err != KERN_SUCCESS) brk = (void*)-1; return brk; } */ /emu/mkfile 664 inferno inf 1131688563 548 <../mkconfig all:V: all-$HOSTMODEL install:V: install-$HOSTMODEL safeinstall:V: safeinstall-$HOSTMODEL clean:V: clean-$HOSTMODEL nuke:V: nuke-$HOSTMODEL &-Posix:QV: echo "(cd $SYSTARG; mk $MKFLAGS $stem)" (cd $SYSTARG; mk $MKFLAGS $stem) &-Nt:QV: echo '@{builtin cd' $SYSTARG '; mk $MKFLAGS $stem}' @{builtin cd $SYSTARG; mk $MKFLAGS $stem } &-Plan9:QV: echo '@{builtin cd' $SYSTARG '; mk $MKFLAGS $stem}' @{builtin cd $SYSTARG; mk $MKFLAGS $stem } &-MacOSX:QV: echo "(cd $SYSTARG; mk $MKFLAGS $stem)" (cd $SYSTARG; mk $MKFLAGS $stem) /lib9 20000000775 inferno inf 1141888096 0 /lib9/getcallerpc-MacOSX-386.s 664 inferno inf 1131668004 109 .file "getcallerpc-MacOSX-386.s" .text .globl _getcallerpc _getcallerpc: movl 4(%ebp), %eax ret /lib9/mkfile-MacOSX 664 inferno inf 1141362106 565 # At one point it was important to have sbrk and filter out some of the # duplicate functions from libc. As of Tiger, it seems that these measures # no longer need to be put into place. #COMMONFILES=`echo "$COMMONFILES" | sed 's/ qsort.o//'`\ COMMONFILES= $COMMONFILES \ sbrk-MacOSX.$O \ #IMPORTFILES=`echo "$IMPORTFILES" | sed 's/ strdup.o//'` TARGFILES=\ $IMPORTFILES\ dirstat-posix.$O\ errstr-posix.$O\ getuser-posix.$O\ getcallerpc-$SYSTARG-$OBJTYPE.$O\ getwd-posix.$O\ sbrk-MacOSX.$O\ #sysfatal.$O: sysfatal.c # $CC $CFLAGS -fno-common sysfatal.c /lib9/sbrk-MacOSX.c 664 inferno inf 1130087457 930 #include "lib9.h" #undef _POSIX_C_SOURCE #undef getwd #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if (__GNUC__ == 3 && __GNUC_MINOR__ == 5) || (__GNUC__ == 4) void* #else char* #endif sbrk(int size) { #if (__GNUC__ == 3 && __GNUC_MINOR__ == 5) || (__GNUC__ == 4) void *brk; #else char *brk; #endif kern_return_t err; err = vm_allocate( (vm_map_t) mach_task_self(), (vm_address_t *)&brk, size, VM_FLAGS_ANYWHERE); if (err != KERN_SUCCESS) brk = (void*)-1; return brk; } /libdraw 20000000775 inferno inf 1141888101 0 /libdraw/mkfile-MacOSX 664 inferno inf 1130087665 95 OFILES=`echo "$OFILES" | sed ' s/ freesubfont.o// s/ subfontname.o// s/ subfontcache.o// '` /libinterp 20000000775 inferno inf 1141888100 0 /libinterp/dlm-MacOSX.c 664 inferno inf 1130087852 23 #include "dlm-Posix.c" /libinterp/load.c 664 inferno inf 1141832440 10611 #include "lib9.h" #include "isa.h" #include "interp.h" #include "raise.h" #include #define A(r) *((Array**)(r)) Module* modules; extern int dontcompile; static int operand(uchar **p) { int c; uchar *cp; cp = *p; c = cp[0]; switch(c & 0xC0) { case 0x00: *p = cp+1; return c; case 0x40: *p = cp+1; return c|~0x7F; case 0x80: *p = cp+2; if(c & 0x20) c |= ~0x3F; else c &= 0x3F; return (c<<8)|cp[1]; case 0xC0: *p = cp+4; if(c & 0x20) c |= ~0x3F; else c &= 0x3F; return (c<<24)|(cp[1]<<16)|(cp[2]<<8)|cp[3]; } return 0; } static ulong disw(uchar **p) { ulong v; uchar *c; c = *p; v = c[0] << 24; v |= c[1] << 16; v |= c[2] << 8; v |= c[3]; *p = c + 4; return v; } double canontod(ulong v[2]) { union { double d; unsigned long ul[2]; } a; a.d = 1.; if(a.ul[0]) { a.ul[0] = v[0]; a.ul[1] = v[1]; } else { a.ul[1] = v[0]; a.ul[0] = v[1]; } return a.d; } Module* load(char *path) { return readmod(path, nil, 0); } Type* dtype(void (*destroy)(Heap*, int), int size, uchar *map, int mapsize) { Type *t; t = malloc(sizeof(Type)+mapsize); if(t != nil) { t->ref = 1; t->free = destroy; t->mark = markheap; t->size = size; t->np = mapsize; memmove(t->map, map, mapsize); } return t; } int brpatch(Inst *ip, Module *m) { switch(ip->op) { case ICALL: case IJMP: case IBEQW: case IBNEW: case IBLTW: case IBLEW: case IBGTW: case IBGEW: case IBEQB: case IBNEB: case IBLTB: case IBLEB: case IBGTB: case IBGEB: case IBEQF: case IBNEF: case IBLTF: case IBLEF: case IBGTF: case IBGEF: case IBEQC: case IBNEC: case IBLTC: case IBLEC: case IBGTC: case IBGEC: case IBEQL: case IBNEL: case IBLTL: case IBLEL: case IBGTL: case IBGEL: case ISPAWN: if(ip->d.imm < 0 || ip->d.imm >= m->nprog) return 0; ip->d.imm = (WORD)&m->prog[ip->d.imm]; break; } return 1; } Module* parsemod(char *path, uchar *code, ulong length, Dir *dir) { Heap *h; Inst *ip; Type *pt; String *s; Module *m; Array *ary; ulong ul[2]; WORD lo, hi; int lsize, id, v, entry, entryt, tnp, tsz, siglen; int de, pc, i, n, isize, dsize, hsize, dasp; uchar *mod, sm, *istream, **isp, *si, *addr, *dastack[DADEPTH]; Link *l; istream = code; isp = &istream; m = malloc(sizeof(Module)); if(m == nil) return nil; m->dev = dir->dev; m->dtype = dir->type; m->qid = dir->qid; m->mtime = dir->mtime; m->origmp = H; m->pctab = nil; switch(operand(isp)) { default: kwerrstr("bad magic"); goto bad; case SMAGIC: siglen = operand(isp); n = length-(*isp-code); if(n < 0 || siglen > n){ kwerrstr("corrupt signature"); goto bad; } if(verifysigner(*isp, siglen, *isp+siglen, n-siglen) == 0) { kwerrstr("security violation"); goto bad; } *isp += siglen; break; case XMAGIC: if(mustbesigned(path, code, length, dir)){ kwerrstr("security violation: not signed"); goto bad; } break; } m->rt = operand(isp); m->ss = operand(isp); isize = operand(isp); dsize = operand(isp); hsize = operand(isp); lsize = operand(isp); entry = operand(isp); entryt = operand(isp); if(isize < 0 || dsize < 0 || hsize < 0 || lsize < 0) { kwerrstr("implausible Dis file"); goto bad; } m->nprog = isize; m->prog = mallocz(isize*sizeof(Inst), 0); if(m->prog == nil) { kwerrstr(exNomem); goto bad; } m->ref = 1; ip = m->prog; for(i = 0; i < isize; i++) { ip->op = *istream++; ip->add = *istream++; ip->reg = 0; ip->s.imm = 0; ip->d.imm = 0; switch(ip->add & ARM) { case AXIMM: case AXINF: case AXINM: ip->reg = operand(isp); break; } switch(UXSRC(ip->add)) { case SRC(AFP): case SRC(AMP): case SRC(AIMM): ip->s.ind = operand(isp); break; case SRC(AIND|AFP): case SRC(AIND|AMP): ip->s.i.f = operand(isp); ip->s.i.s = operand(isp); break; } switch(UXDST(ip->add)) { case DST(AFP): case DST(AMP): ip->d.ind = operand(isp); break; case DST(AIMM): ip->d.ind = operand(isp); if(brpatch(ip, m) == 0) { kwerrstr("bad branch addr"); goto bad; } break; case DST(AIND|AFP): case DST(AIND|AMP): ip->d.i.f = operand(isp); ip->d.i.s = operand(isp); break; } ip++; } m->ntype = hsize; m->type = malloc(hsize*sizeof(Type*)); if(m->type == nil) { kwerrstr(exNomem); goto bad; } for(i = 0; i < hsize; i++) { id = operand(isp); if(id > hsize) { kwerrstr("heap id range"); goto bad; } tsz = operand(isp); tnp = operand(isp); if(tsz < 0 || tnp < 0 || tnp > 128*1024){ kwerrstr("implausible Dis file"); goto bad; } pt = dtype(freeheap, tsz, istream, tnp); if(pt == nil) { kwerrstr(exNomem); goto bad; } istream += tnp; m->type[id] = pt; } if(dsize != 0) { pt = m->type[0]; if(pt == 0 || pt->size != dsize) { kwerrstr("bad desc for mp"); goto bad; } h = heapz(pt); m->origmp = H2D(uchar*, h); } addr = m->origmp; dasp = 0; for(;;) { sm = *istream++; if(sm == 0) break; n = DLEN(sm); if(n == 0) n = operand(isp); v = operand(isp); si = addr + v; switch(DTYPE(sm)) { default: kwerrstr("bad data item"); goto bad; case DEFS: s = c2string((char*)istream, n); istream += n; *(String**)si = s; break; case DEFB: for(i = 0; i < n; i++) *si++ = *istream++; break; case DEFW: for(i = 0; i < n; i++) { *(WORD*)si = disw(isp); si += sizeof(WORD); } break; case DEFL: for(i = 0; i < n; i++) { hi = disw(isp); lo = disw(isp); *(LONG*)si = (LONG)hi << 32 | (LONG)(ulong)lo; si += sizeof(LONG); } break; case DEFF: for(i = 0; i < n; i++) { ul[0] = disw(isp); ul[1] = disw(isp); *(REAL*)si = canontod(ul); si += sizeof(REAL); } break; case DEFA: /* Array */ v = disw(isp); if(v < 0 || v > m->ntype) { kwerrstr("bad array type"); goto bad; } pt = m->type[v]; v = disw(isp); h = nheap(sizeof(Array)+(pt->size*v)); h->t = &Tarray; h->t->ref++; ary = H2D(Array*, h); ary->t = pt; ary->len = v; ary->root = H; ary->data = (uchar*)ary+sizeof(Array); memset((void*)ary->data, 0, pt->size*v); initarray(pt, ary); A(si) = ary; break; case DIND: /* Set index */ ary = A(si); if(ary == H || D2H(ary)->t != &Tarray) { kwerrstr("ind not array"); goto bad; } v = disw(isp); if(v > ary->len || v < 0 || dasp >= DADEPTH) { kwerrstr("array init range"); goto bad; } dastack[dasp++] = addr; addr = ary->data+v*ary->t->size; break; case DAPOP: if(dasp == 0) { kwerrstr("pop range"); goto bad; } addr = dastack[--dasp]; break; } } mod = istream; if(memchr(mod, 0, 128) == 0) { kwerrstr("bad module name"); goto bad; } m->name = strdup((char*)mod); if(m->name == nil) { kwerrstr(exNomem); goto bad; } while(*istream++) ; l = m->ext = (Link*)malloc((lsize+1)*sizeof(Link)); if(l == nil){ kwerrstr(exNomem); goto bad; } for(i = 0; i < lsize; i++, l++) { pc = operand(isp); de = operand(isp); v = disw(isp); pt = nil; if(de != -1) pt = m->type[de]; mlink(m, l, istream, v, pc, pt); while(*istream++) ; } l->name = nil; if(m->rt & HASLDT0){ kwerrstr("obsolete dis"); goto bad; } if(m->rt & HASLDT){ int j, nl; Import *i1, **i2; nl = operand(isp); i2 = m->ldt = (Import**)malloc((nl+1)*sizeof(Import*)); if(i2 == nil){ kwerrstr(exNomem); goto bad; } for(i = 0; i < nl; i++, i2++){ n = operand(isp); i1 = *i2 = (Import*)malloc((n+1)*sizeof(Import)); if(i1 == nil){ kwerrstr(exNomem); goto bad; } for(j = 0; j < n; j++, i1++){ i1->sig = disw(isp); i1->name = strdup((char*)istream); if(i1->name == nil){ kwerrstr(exNomem); goto bad; } while(*istream++) ; } } istream++; } if(m->rt & HASEXCEPT){ int j, nh; Handler *h; Except *e; nh = operand(isp); m->htab = malloc((nh+1)*sizeof(Handler)); if(m->htab == nil){ kwerrstr(exNomem); goto bad; } h = m->htab; for(i = 0; i < nh; i++, h++){ h->eoff = operand(isp); h->pc1 = operand(isp); h->pc2 = operand(isp); n = operand(isp); if(n != -1) h->t = m->type[n]; n = operand(isp); h->ne = n>>16; n &= 0xffff; h->etab = malloc((n+1)*sizeof(Except)); if(h->etab == nil){ kwerrstr(exNomem); goto bad; } e = h->etab; for(j = 0; j < n; j++, e++){ e->s = strdup((char*)istream); if(e->s == nil){ kwerrstr(exNomem); goto bad; } while(*istream++) ; e->pc = operand(isp); } e->s = nil; e->pc = operand(isp); } istream++; } m->entryt = nil; m->entry = m->prog; if((ulong)entry < isize && (ulong)entryt < hsize) { m->entry = &m->prog[entry]; m->entryt = m->type[entryt]; } if(cflag) { if((m->rt&DONTCOMPILE) == 0 && !dontcompile) compile(m, isize, nil); } else if(m->rt & MUSTCOMPILE && !dontcompile) { if(compile(m, isize, nil) == 0) { kwerrstr("compiler required"); goto bad; } } m->path = strdup(path); if(m->path == nil) { kwerrstr(exNomem); goto bad; } m->link = modules; modules = m; return m; bad: destroy(m->origmp); freemod(m); return nil; } Module* newmod(char *s) { Module *m; m = malloc(sizeof(Module)); if(m == nil) error(exNomem); m->ref = 1; m->path = s; m->origmp = H; m->name = strdup(s); if(m->name == nil) { free(m); error(exNomem); } m->link = modules; modules = m; m->pctab = nil; return m; } Module* lookmod(char *s) { Module *m; for(m = modules; m != nil; m = m->link) if(strcmp(s, m->path) == 0) { m->ref++; return m; } return nil; } void freemod(Module *m) { int i; Handler *h; Except *e; Import *i1, **i2; if(m->type != nil) { for(i = 0; i < m->ntype; i++) freetype(m->type[i]); free(m->type); } free(m->name); free(m->prog); free(m->path); free(m->pctab); if(m->ldt != nil){ for(i2 = m->ldt; *i2 != nil; i2++){ for(i1 = *i2; i1->name != nil; i1++) free(i1->name); free(*i2); } free(m->ldt); } if(m->htab != nil){ for(h = m->htab; h->etab != nil; h++){ for(e = h->etab; e->s != nil; e++) free(e->s); free(h->etab); } free(m->htab); } free(m); } void unload(Module *m) { Module **last, *mm; m->ref--; if(m->ref > 0) return; if(m->ref == -1) abort(); last = &modules; for(mm = modules; mm != nil; mm = mm->link) { if(mm == m) { *last = m->link; break; } last = &mm->link; } if(m->rt == DYNMOD) freedyncode(m); else destroy(m->origmp); destroylinks(m); freemod(m); } /libmath 20000000775 inferno inf 1141888100 0 /libmath/FPcontrol-MacOSX.c 664 inferno inf 1141886497 2335 #include "lib9.h" #include "fpuctl.h" #include "mathi.h" #include void PPC_PrintFPSCR() { #if defined (__ppc__) ppc_fp_scr_t fpscr; fpscr = get_fp_scr(); fprintf(stderr, "FPSCR = 0x%08x : 0x%08x\n", ((unsigned int *)&fpscr)[0], ((unsigned int *)&fpscr)[1]); fprintf(stderr, "FPSCR[ve] = %d\n", fpscr.ve); fprintf(stderr, "FPSCR[ze] = %d\n", fpscr.ze); fprintf(stderr, "FPSCR[ue] = %d\n", fpscr.ue); fprintf(stderr, "FPSCR[oe] = %d\n", fpscr.oe); #endif } void FPinit(void) { #if defined (__ppc__) ulong fcr9 = FPPDBL|FPRNR|FPINVAL|FPZDIV|FPUNFL|FPOVFL; setfsr(0); /* Clear pending exceptions */ setfcr(fcr9); #elif defined (__i386__) setfsr(0); /* Clear pending exceptions */ setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPUNFL|FPOVFL); #else #error architecture not supported #endif } ulong getFPstatus(void) { ulong fsr = 0, fsr9 = getfsr(); /* on specific machines, could be table lookup */ if(fsr9&FPAINEX) fsr |= INEX; if(fsr9&FPAOVFL) fsr |= OVFL; if(fsr9&FPAUNFL) fsr |= UNFL; if(fsr9&FPAZDIV) fsr |= ZDIV; if(fsr9&FPAINVAL) fsr |= INVAL; return fsr; } ulong FPstatus(ulong fsr, ulong mask) { ulong fsr9 = 0; ulong old = getFPstatus(); fsr = (fsr&mask) | (old&~mask); if(fsr&INEX) fsr9 |= FPAINEX; if(fsr&OVFL) fsr9 |= FPAOVFL; if(fsr&UNFL) fsr9 |= FPAUNFL; if(fsr&ZDIV) fsr9 |= FPAZDIV; if(fsr&INVAL) fsr9 |= FPAINVAL; setfsr(fsr9); return(old&mask); } ulong getFPcontrol(void) { ulong fcr = 0, fcr9 = getfcr(); switch(fcr9&FPRMASK){ case FPRNR: fcr = RND_NR; break; case FPRNINF: fcr = RND_NINF; break; case FPRPINF: fcr = RND_PINF; break; case FPRZ: fcr = RND_Z; break; } if(fcr9&FPINEX) fcr |= INEX; if(fcr9&FPOVFL) fcr |= OVFL; if(fcr9&FPUNFL) fcr |= UNFL; if(fcr9&FPZDIV) fcr |= ZDIV; if(fcr9&FPINVAL) fcr |= INVAL; return fcr; } ulong FPcontrol(ulong fcr, ulong mask) { ulong fcr9 = FPPDBL; ulong old = getFPcontrol(); fcr = (fcr&mask) | (old&~mask); if(fcr&INEX) fcr9 |= FPINEX; if(fcr&OVFL) fcr9 |= FPOVFL; if(fcr&UNFL) fcr9 |= FPUNFL; if(fcr&ZDIV) fcr9 |= FPZDIV; if(fcr&INVAL) fcr9 |= FPINVAL; switch(fcr&RND_MASK){ case RND_NR: fcr9 |= FPRNR; break; case RND_NINF: fcr9 |= FPRNINF; break; case RND_PINF: fcr9 |= FPRPINF; break; case RND_Z: fcr9 |= FPRZ; break; } setfcr(fcr9); return(old&mask); } /libmath/mkfile 664 inferno inf 1130088152 928 <../mkconfig TARGTYPE=${SYSTARG:os%=Inferno%} # maps 'os' into 'Inferno' LIB=libmath.a OFILES=\ blas.$O\ dtoa.$O\ fdim.$O\ FPcontrol-$TARGTYPE.$O\ gemm.$O\ g_fmt.$O\ gfltconv.$O\ pow10.$O\ e_acos.$O\ e_acosh.$O\ e_asin.$O\ e_atan2.$O\ e_atanh.$O\ e_cosh.$O\ e_exp.$O\ e_fmod.$O\ e_hypot.$O\ e_j0.$O\ e_j1.$O\ e_jn.$O\ e_lgamma_r.$O\ e_log.$O\ e_log10.$O\ e_pow.$O\ e_rem_pio2.$O\ e_remainder.$O\ e_sinh.$O\ e_sqrt.$O\ k_cos.$O\ k_rem_pio2.$O\ k_sin.$O\ k_tan.$O\ s_asinh.$O\ s_atan.$O\ s_cbrt.$O\ s_ceil.$O\ s_copysign.$O\ s_cos.$O\ s_erf.$O\ s_expm1.$O\ s_fabs.$O\ s_finite.$O\ s_floor.$O\ s_ilogb.$O\ s_isnan.$O\ s_log1p.$O\ s_nextafter.$O\ s_rint.$O\ s_scalbn.$O\ s_sin.$O\ s_tan.$O\ s_tanh.$O\ HFILES=\ $ROOT/include/mathi.h\ fdlibm/fdlibm.h\ char * myctime(long x) { time_t t; t = x; return ctime(&t); } /utils/mkfile 664 inferno inf 1141369583 1512 <../mkconfig # # Utils we build everywhere, because the Plan 9 versions don't yet # contain our changes (or they don't exist on Plan 9). # Fairly soon the Plan 9 compilers will be updated to match. # ALWAYS=\ libmach\ libregexp\ iar\ cc\ 0a\ 0c\ 0l\ 1a\ 1c\ 1l\ 2a\ 2c\ 2l\ 5a\ 5c\ 5l\ # 5i\ 5coff\ 5cv\ ka\ kc\ kl\ qa\ qc\ ql\ sqz\ tc\ acid\ srclist\ ftl\ ms2\ data2c\ data2s\ idea\ kprof\ c2l\ mkppcimage\ nm\ # # Utils we build on Posix and Nt, which already exist on Plan 9. # NOTPLAN9=\ yacc\ 8a\ 8c\ 8l\ va\ vc\ vl\ mk\ ksize\ kstrip\ md5sum\ mkext\ ndate\ # # Utils we build on Nt, for build environment compatibility. # NTONLY=\ cp\ echo\ format\ mkdir\ mv\ ntsrv\ rcsh\ rm\ sed\ test\ tr\ all:QV: all-$TARGMODEL clean:QV: clean-$TARGMODEL install:QV: install-$TARGMODEL installall:QV: installall-$TARGMODEL nuke:QV: nuke-$TARGMODEL %-Plan9:QV: for (j in $ALWAYS) { test -d $j && { echo '@{cd' $j '; mk $MKFLAGS $stem}' @{cd $j; mk $MKFLAGS $stem } } || test ! -e $j } %-Posix:QV: for j in $ALWAYS $NOTPLAN9 do test -d $j || continue echo "(cd $j; mk $MKFLAGS $stem)" (cd $j; mk $MKFLAGS $stem) done %-MacOSX:QV: for j in $ALWAYS $NOTPLAN9 do test -d $j || continue echo "(cd $j; mk $MKFLAGS $stem)" (cd $j; mk $MKFLAGS $stem) done %-Nt:QV: for (j in $ALWAYS $NTONLY $NOTPLAN9) { test -d $j && { echo.exe '@{cd' $j '; mk $MKFLAGS $stem}' @{cd $j; mk $MKFLAGS $stem } } || test ! -e $j } /utils/srclist 20000000775 inferno inf 1141885640 0 /utils/srclist/MacOSX.c 664 inferno inf 1130478858 19 #include "Posix.c" end of archive