double read_test(ui count) { double t1; register ui *o,i=0; o=(ui *)buf[0]; t1=readtime(); while(i<count) { o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); i+=64; } return(readtime()-t1); }
int main(int argc, char *argv[]) { struct timespec t; if(argc < 2) usage(); argc--; argv++; init(); for(;;){ if(readtime(&t) < 0) t = deftime; if(rise) forkexec(argv); nanosleep(&t, NULL); if(fall) forkexec(argv); } return 0; }
int stdio_io(int vec) { union { double d; int i[2]; } db1, db2, db3; register int arg1, arg2, arg3, arg4; int i, j, k; char str1[150], str2[150], rdwrbuf[RDWRBUF]; FILE *fp_out = stdout; arg1 = getarg(1); arg2 = getarg(2); arg3 = getarg(3); arg4 = getarg(4); switch(vec) { /* unsupported trap */ default: return(1); case 0x1fb: /* Unix times */ /* addr = m88000.Regs[2]; */ i = readtime(); PPrintf("at clock = %d\n",i); /* membyte(addr+0) = (char) uext(i,0,8); */ /* membyte(addr+1) = (char) uext(i,8,8); */ /* membyte(addr+2) = (char) uext(i,16,8); */ /* membyte(addr+3) = (char) uext(i,24,8); */ break; case S_PRINTF: /* printf */ if(!copystr(1, str1)) return(-1); sim_printf(fp_out, str1, 2); break; case S_FPRINTF: /* fprintf: */ if(!copystr(2, str1)) return(-1); sim_printf(ckiob((TARGETFILE *)arg1), str1, 3); break; case S_SPRINTF: /* _sprintf: */ Eprintf("sorry, sprintf not yet supported\n"); break; case S_SCANF: /* _scanf: */ case S_FSCANF: /* _fscanf: */ case S_SSCANF: /* _sscanf: */ Eprintf("sorry, scanf not yet supported\n"); break; case S_FOPEN: if(!copystr(1, str1) || !copystr(2, str2)) return(-1); m88000.Regs[2] = (int)fopen(str1, str2); break; case S_FREOPEN: if(!copystr(1, str1) || !copystr(2, str2)) return(-1); m88000.Regs[2] = (int)freopen(str1, str2, ckiob((TARGETFILE *)arg3)); break; case S_FDOPEN: if(!copystr(2, str1)) return(-1); m88000.Regs[2] = (int)fdopen(arg1, str1); break; case S_FREAD: k = arg2 * arg3; j = 0; do { i = fread(rdwrbuf, sizeof(char), RDWRBUF, ckiob((TARGETFILE *)getarg(4))); if(rdwr((M_DATA | M_RD), arg1, rdwrbuf, (i < k) ? k: i) == -1) return(-1); j += (i < k) ? k: i; arg1 += i; } while((k -= i) < 0); m88000.Regs[2] = j; break; case S_FWRITE: k = arg2 * arg3; j = 0; do { if((i = k / RDWRBUF) == 0) i = k % RDWRBUF; if(rdwr((M_DATA | M_WR), arg1, rdwrbuf, i) == -1) return(-1); if(i != fwrite(rdwrbuf, sizeof(char), i, ckiob((TARGETFILE *)getarg(4)))) { j = 0; break; } j += i; arg1 += i; } while((k -= i) < 0); m88000.Regs[2] = j; break; case S_FCLOSE: m88000.Regs[2] = (int)fclose(ckiob((TARGETFILE *)arg1)); break; case S_FFLUSH: m88000.Regs[2] = (int)fflush(ckiob((TARGETFILE *)arg1)); break; case 0x203: case 0x204: case S__FILBUF: /* __filbuf: */ case S__FLSBUF: /* __flsbuf: */ case S_MALLOC: /* _malloc: */ case S_SETBUF: case S_SETBUFFER: case S_SETLINEBUF: Eprintf("unsupported trap\n"); break; case S_FSEEK: m88000.Regs[2] = (int)fseek(ckiob((TARGETFILE *)arg1), arg2, arg3); break; case S_GETS: if(fgets(rdwrbuf, sizeof(rdwrbuf), stdin) == 0) m88000.Regs[2] = 0; else { i = strchr(rdwrbuf, '\0') - rdwrbuf + 1; if(rdwr((M_DATA | M_WR), arg1, rdwrbuf, i) == -1) return(-1); } break; case S_FGETS: i = (arg2 < sizeof(rdwrbuf)) ? arg2: sizeof(rdwrbuf); if(fgets(rdwrbuf, i, ckiob((TARGETFILE *)arg3)) == 0) m88000.Regs[2] = 0; else { i = strchr(rdwrbuf, '\0') - rdwrbuf + 1; if(rdwr((M_DATA | M_WR), arg1, rdwrbuf, i) == -1) return(-1); } break; case S_REWIND: rewind(ckiob((TARGETFILE *)arg1)); break; case S_FTELL: m88000.Regs[2] = (int)ftell(ckiob((TARGETFILE *)arg1)); break; case S_FEOF: m88000.Regs[2] = feof((FILE *)ckiob((TARGETFILE *)arg1)); break; case S_FERROR: m88000.Regs[2] = ferror((FILE *)ckiob((TARGETFILE *)arg1)); break; case S_CLEARERR: clearerr((FILE *)ckiob((TARGETFILE *)arg1)); break; case S_FILENO: m88000.Regs[2] = (int)fileno((FILE *)ckiob((TARGETFILE *)arg1)); break; case S_GETC: case S_FGETC: m88000.Regs[2] = (int)getc((FILE *)ckiob((TARGETFILE *)arg1)); break; case S_GETCHAR: m88000.Regs[2] = (int)getchar(); break; case S_GETW: m88000.Regs[2] = (int)getw(ckiob((TARGETFILE *)arg1)); break; case S_PUTC: case S_FPUTC: m88000.Regs[2] = (int)fputc(arg1,ckiob((TARGETFILE *)arg2)); break; case S_PUTCHAR: m88000.Regs[2] = (int)putchar(arg1); break; case S_PUTW: m88000.Regs[2] = (int)putw(arg1,ckiob((TARGETFILE *)arg2)); break; case S_PUTS: if(!copystr(1, str1)) return(-1); m88000.Regs[2] = (int)puts(str1); break; case S_FPUTS: if(!copystr(1, str1)) return(-1); m88000.Regs[2] = (int)fputs(str1, ckiob((TARGETFILE *)arg2)); break; case S_UNGETC: m88000.Regs[2] = (int)ungetc(arg1, ckiob((TARGETFILE *)arg2)); break; case S_GETTIME: m88000.Regs[2] = (int)readtime(); break; case S_SYSTEM: if(!copystr(1, str1)) return(-1); m88000.Regs[2] = (int)system(str1); break; case S_EXP: db1.i[0] = arg1; db1.i[1] = arg2; db2.d = exp(db1.d); m88000.Regs[2] = db2.i[0]; m88000.Regs[3] = db2.i[1]; break; case S_LOG: db1.i[0] = arg1; db1.i[1] = arg2; db2.d = log(db1.d); m88000.Regs[2] = db2.i[0]; m88000.Regs[3] = db2.i[1]; break; case S_LOG10: db1.i[0] = arg1; db1.i[1] = arg2; db2.d = log10(db1.d); m88000.Regs[2] = db2.i[0]; m88000.Regs[3] = db2.i[1]; break; case S_SQRT: db1.i[0] = arg1; db1.i[1] = arg2; db2.d = sqrt(db1.d); m88000.Regs[2] = db2.i[0]; m88000.Regs[3] = db2.i[1]; break; case S_SINH: db1.i[0] = arg1; db1.i[1] = arg2; db2.d = sinh(db1.d); m88000.Regs[2] = db2.i[0]; m88000.Regs[3] = db2.i[1]; break; case S_COSH: db1.i[0] = arg1; db1.i[1] = arg2; db2.d = cosh(db1.d); m88000.Regs[2] = db2.i[0]; m88000.Regs[3] = db2.i[1]; break; case S_TANH: db1.i[0] = arg1; db1.i[1] = arg2; db2.d = tanh(db1.d); m88000.Regs[2] = db2.i[0]; m88000.Regs[3] = db2.i[1]; break; case S_FLOOR: db1.i[0] = arg1; db1.i[1] = arg2; db2.d = floor(db1.d); m88000.Regs[2] = db2.i[0]; m88000.Regs[3] = db2.i[1]; break; case S_CEIL: db1.i[0] = arg1; db1.i[1] = arg2; db2.d = ceil(db1.d); m88000.Regs[2] = db2.i[0]; m88000.Regs[3] = db2.i[1]; break; case S_POW: db1.i[0] = arg1; db1.i[1] = arg2; db2.i[0] = arg3; db2.i[1] = arg4; db3.d = pow(db1.d,db2.d); m88000.Regs[2] = db3.i[0]; m88000.Regs[3] = db3.i[1]; break; } IP += 4; return(0); }
static int32_t consread(Chan *c, void *buf, int32_t n, int64_t off) { Proc *up = externup(); uint64_t l; Mach *mp; char *b, *bp, *s, *e; char tmp[512]; /* Qswap is 381 bytes at clu */ int i, k, id; int32_t offset; if(n <= 0) return n; offset = off; switch((uint32_t)c->qid.path){ case Qdir: return devdirread(c, buf, n, consdir, nelem(consdir), devgen); case Qcons: error(Egreg); case Qcputime: k = offset; if(k >= 6*NUMSIZE) return 0; if(k+n > 6*NUMSIZE) n = 6*NUMSIZE - k; /* easiest to format in a separate buffer and copy out */ for(i=0; i<6 && NUMSIZE*i<k+n; i++){ l = up->time[i]; if(i == TReal) l = sys->ticks - l; l = TK2MS(l); readnum(0, tmp+NUMSIZE*i, NUMSIZE, l, NUMSIZE); } memmove(buf, tmp+k, n); return n; case Qkmesg: /* * This is unlocked to avoid tying up a process * that's writing to the buffer. kmesg.n never * gets smaller, so worst case the reader will * see a slurred buffer. */ if(off >= kmesg.n) n = 0; else{ if(off+n > kmesg.n) n = kmesg.n - off; memmove(buf, kmesg.buf+off, n); } return n; case Qkprint: error(Egreg); case Qpgrpid: return readnum(offset, buf, n, up->pgrp->pgrpid, NUMSIZE); case Qpid: return readnum(offset, buf, n, up->pid, NUMSIZE); case Qppid: return readnum(offset, buf, n, up->parentpid, NUMSIZE); case Qtime: return readtime(offset, buf, n); case Qbintime: return readbintime(buf, n); case Qhostowner: return readstr(offset, buf, n, eve); case Qhostdomain: return readstr(offset, buf, n, hostdomain); case Quser: return readstr(offset, buf, n, up->user); case Qnull: return 0; case Qsysstat: n = MACHMAX*(NUMSIZE*11+2+1); b = smalloc(n + 1); /* +1 for NUL */ bp = b; e = bp + n; for(id = 0; id < MACHMAX; id++) if((mp = sys->machptr[id]) != nil && mp->online){ readnum(0, bp, NUMSIZE, mp->machno, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->cs, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->intr, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, sys->load, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, (mp->perf.avg_inidle*100)/mp->perf.period, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, (mp->perf.avg_inintr*100)/mp->perf.period, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, 0, NUMSIZE); /* sched # */ bp += NUMSIZE; bp = strecpy(bp, e, rolename[mp->NIX.nixtype]); *bp++ = '\n'; } if(waserror()){ free(b); nexterror(); } n = readstr(offset, buf, n, b); free(b); poperror(); return n; case Qswap: tmp[0] = 0; s = seprintpagestats(tmp, tmp + sizeof tmp); s = seprintphysstats(s, tmp + sizeof tmp); b = buf; l = s - tmp; i = readstr(offset, b, l, tmp); b += i; n -= i; if(offset > l) offset -= l; else offset = 0; return i + mallocreadsummary(c, b, n, offset); case Qsysname: if(sysname == nil) return 0; return readstr(offset, buf, n, sysname); case Qrandom: return randomread(buf, n); case Qurandom: return urandomread(buf, n); case Qdrivers: return devtabread(c, buf, n, off); case Qzero: memset(buf, 0, n); return n; case Qosversion: snprint(tmp, sizeof tmp, "2000"); n = readstr(offset, buf, n, tmp); return n; case Qdebug: s = seprint(tmp, tmp + sizeof tmp, "locks %lu\n", lockstats.locks); s = seprint(s, tmp + sizeof tmp, "glare %lu\n", lockstats.glare); s = seprint(s, tmp + sizeof tmp, "inglare %lu\n", lockstats.inglare); s = seprint(s, tmp + sizeof tmp, "qlock %lu\n", qlockstats.qlock); seprint(s, tmp + sizeof tmp, "qlockq %lu\n", qlockstats.qlockq); return readstr(offset, buf, n, tmp); break; case Qsyscall: snprint(tmp, sizeof tmp, "%s", printallsyscalls ? "on" : "off"); return readstr(offset, buf, n, tmp); break; default: print("consread %#llx\n", c->qid.path); error(Egreg); } return -1; /* never reached */ }
static long consread(Chan *c, void *buf, long n, vlong off) { ulong l; Mach *mp; char *b, *bp; char tmp[256]; /* must be >= 18*NUMSIZE (Qswap) */ int i, k, id; vlong offset = off; extern char configfile[]; if(n <= 0) return n; switch((ulong)c->qid.path){ case Qdir: return devdirread(c, buf, n, consdir, nelem(consdir), devgen); case Qcons: error(Egreg); case Qcputime: k = offset; if(k >= 6*NUMSIZE) return 0; if(k+n > 6*NUMSIZE) n = 6*NUMSIZE - k; /* easiest to format in a separate buffer and copy out */ for(i=0; i<6 && NUMSIZE*i<k+n; i++){ l = up->time[i]; if(i == TReal) l = MACHP(0)->ticks - l; l = TK2MS(l); readnum(0, tmp+NUMSIZE*i, NUMSIZE, l, NUMSIZE); } memmove(buf, tmp+k, n); return n; case Qkmesg: /* * This is unlocked to avoid tying up a process * that's writing to the buffer. kmesg.n never * gets smaller, so worst case the reader will * see a slurred buffer. */ if(off >= kmesg.n) n = 0; else{ if(off+n > kmesg.n) n = kmesg.n - off; memmove(buf, kmesg.buf+off, n); } return n; case Qkprint: return qread(kprintoq, buf, n); case Qpgrpid: return readnum((ulong)offset, buf, n, up->pgrp->pgrpid, NUMSIZE); case Qpid: return readnum((ulong)offset, buf, n, up->pid, NUMSIZE); case Qppid: return readnum((ulong)offset, buf, n, up->parentpid, NUMSIZE); case Qtime: return readtime((ulong)offset, buf, n); case Qbintime: return readbintime(buf, n); case Qhostowner: return readstr((ulong)offset, buf, n, eve); case Qhostdomain: return readstr((ulong)offset, buf, n, hostdomain); case Quser: return readstr((ulong)offset, buf, n, up->user); case Qnull: return 0; case Qconfig: return readstr((ulong)offset, buf, n, configfile); case Qsysstat: b = smalloc(conf.nmach*(NUMSIZE*11+1) + 1); /* +1 for NUL */ bp = b; for(id = 0; id < 32; id++) { if(active.machs & (1<<id)) { mp = MACHP(id); readnum(0, bp, NUMSIZE, id, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->cs, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->intr, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->load, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, (mp->perf.avg_inidle*100)/mp->perf.period, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, (mp->perf.avg_inintr*100)/mp->perf.period, NUMSIZE); bp += NUMSIZE; *bp++ = '\n'; } } if(waserror()){ free(b); nexterror(); } n = readstr((ulong)offset, buf, n, b); free(b); poperror(); return n; case Qswap: snprint(tmp, sizeof tmp, "%lud memory\n" "%d pagesize\n" "%lud kernel\n" "%lud/%lud user\n" "%lud/%lud swap\n" "%lud/%lud kernel malloc\n" "%lud/%lud kernel draw\n", conf.npage*BY2PG, BY2PG, conf.npage-conf.upages, palloc.user-palloc.freecount, palloc.user, conf.nswap-swapalloc.free, conf.nswap, mainmem->cursize, mainmem->maxsize, imagmem->cursize, imagmem->maxsize); return readstr((ulong)offset, buf, n, tmp); case Qsysname: if(sysname == nil) return 0; return readstr((ulong)offset, buf, n, sysname); case Qrandom: return randomread(buf, n); case Qdrivers: b = smalloc(READSTR); k = 0; for(i = 0; devtab[i] != nil; i++) k += snprint(b+k, READSTR-k, "#%C %s\n", devtab[i]->dc, devtab[i]->name); if(waserror()){ free(b); nexterror(); } n = readstr((ulong)offset, buf, n, b); poperror(); free(b); return n; case Qzero: memset(buf, 0, n); return n; case Qmordor: error("one does not simply read from mordor"); return 0; case Qosversion: snprint(tmp, sizeof tmp, "2000"); n = readstr((ulong)offset, buf, n, tmp); return n; default: print("consread %#llux\n", c->qid.path); error(Egreg); } return -1; /* never reached */ }
/*---------------------------------------------------------------------------- Thread 1 'command': command processor *---------------------------------------------------------------------------*/ void command (void const *argument) { int i; printf (menu); /* display command menu */ while (1) { /* endless loop */ printf ("\r\nCommand: "); /* display prompt */ #ifdef __USE_FFLUSH fflush (stdout); #endif getline (cmdline, sizeof (cmdline)); /* get command line input */ for (i = 0; cmdline[i] != 0; i++) { /* convert to uppercase */ cmdline[i] = (char) toupper((int)cmdline[i]); } for (i = 0; cmdline[i] == ' '; i++); /* skip blanks */ switch (cmdline[i]) { /* proceed to command function */ case 'D': /* Display Time Command */ printf ("Start Time: %02d:%02d:%02d " "End Time: %02d:%02d:%02d\r\n", stime.hour, stime.min, stime.sec, etime.hour, etime.min, etime.sec); printf (" type ESC to abort\r"); #ifdef __USE_FFLUSH fflush (stdout); #endif tid_getesc = osThreadCreate(osThread(get_escape), NULL); /* ESC check in display loop */ escape = false; /* clear escape flag */ display_time = true; /* set display time flag */ osSignalClear(tid_command, 0x0003); /* clear pending signals */ while (!escape) { /* while no ESC enteRED */ printf ("Clock Time: %02d:%02d:%02d\r", /* display time */ ctime.hour, ctime.min, ctime.sec); #ifdef __USE_FFLUSH fflush (stdout); #endif osSignalWait(0, osWaitForever); /* wait for time change or ESC */ } osThreadTerminate(tid_getesc); /* terminate 'get_escape' */ display_time = false; /* clear display time flag */ printf ("\r\n\r\n"); break; case 'T': /* Set Time Command */ if (readtime (&cmdline[i+1])) { /* read time input and */ ctime.hour = rtime.hour; /* store in 'ctime' */ ctime.min = rtime.min; ctime.sec = rtime.sec; } break; case 'E': /* Set End Time Command */ if (readtime (&cmdline[i+1])) { /* read time input and */ etime.hour = rtime.hour; /* store in 'end' */ etime.min = rtime.min; etime.sec = rtime.sec; } break; case 'S': /* Set Start Time Command */ if (readtime (&cmdline[i+1])) { /* read time input and */ stime.hour = rtime.hour; /* store in 'start' */ stime.min = rtime.min; stime.sec = rtime.sec; } break; default: /* Error Handling */ printf (menu); /* display command menu */ break; } } }
static long consread(struct chan *c, void *buf, long n, int64_t off) { ERRSTACK(1); uint32_t l; #if 0 Mach *mp; #endif char *b, *bp, ch; char tmp[256]; /* must be >= 18*NUMSIZE (Qswap) */ int i, k, id, send; int64_t offset = off; #if 0 extern char configfile[]; #endif if (n <= 0) return n; switch ((uint32_t) c->qid.path) { case Qdir: return devdirread(c, buf, n, consdir, ARRAY_SIZE(consdir), devgen); case Qcons: qlock(&(&kbd)->qlock); if (waserror()) { qunlock(&(&kbd)->qlock); nexterror(); } while (!qcanread(lineq)) { if (qread(kbdq, &ch, 1) == 0) continue; send = 0; if (ch == 0) { /* flush output on rawoff -> rawon */ if (kbd.x > 0) send = !qcanread(kbdq); } else if (kbd.raw) { kbd.line[kbd.x++] = ch; send = !qcanread(kbdq); } else { switch (ch) { case '\b': if (kbd.x > 0) kbd.x--; break; case 0x15: /* ^U */ kbd.x = 0; break; case '\n': case 0x04: /* ^D */ send = 1; default: if (ch != 0x04) kbd.line[kbd.x++] = ch; break; } } if (send || kbd.x == sizeof kbd.line) { qwrite(lineq, kbd.line, kbd.x); kbd.x = 0; } } n = qread(lineq, buf, n); qunlock(&(&kbd)->qlock); poperror(); return n; #if 0 case Qcputime: k = offset; if (k >= 6 * NUMSIZE) return 0; if (k + n > 6 * NUMSIZE) n = 6 * NUMSIZE - k; /* easiest to format in a separate buffer and copy out */ for (i = 0; i < 6 && NUMSIZE * i < k + n; i++) { l = current->time[i]; if (i == TReal) l = MACHP(0)->ticks - l; l = TK2MS(l); consreadnum(0, tmp + NUMSIZE * i, NUMSIZE, l, NUMSIZE); } memmove(buf, tmp + k, n); return n; #endif case Qkmesg: /* * This is unlocked to avoid tying up a process * that's writing to the buffer. kmesg.n never * gets smaller, so worst case the reader will * see a slurred buffer. */ if (off >= kmesg.n) n = 0; else { if (off + n > kmesg.n) n = kmesg.n - off; memmove(buf, kmesg.buf + off, n); } return n; case Qkprint: return qread(kprintoq, buf, n); case Qpgrpid: return consreadnum((uint32_t) offset, buf, n, current->pgrp->pgrpid, NUMSIZE); case Qpid: return consreadnum((uint32_t) offset, buf, n, current->pid, NUMSIZE); case Qppid: return consreadnum((uint32_t) offset, buf, n, current->ppid, NUMSIZE); case Qtime: return readtime((uint32_t) offset, buf, n); case Qbintime: return readbintime(buf, n); case Qhostowner: return consreadstr((uint32_t) offset, buf, n, eve); case Qhostdomain: return consreadstr((uint32_t) offset, buf, n, hostdomain); case Quser: return consreadstr((uint32_t) offset, buf, n, current->user); case Qnull: return 0; #if 0 case Qconfig: return consreadstr((uint32_t) offset, buf, n, configfile); case Qsysstat: b = kzmalloc(conf.nmach * (NUMSIZE * 11 + 1) + 1, 0); /* +1 for NUL */ bp = b; for (id = 0; id < 32; id++) { if (active.machs & (1 << id)) { mp = MACHP(id); consreadnum(0, bp, NUMSIZE, id, NUMSIZE); bp += NUMSIZE; consreadnum(0, bp, NUMSIZE, mp->cs, NUMSIZE); bp += NUMSIZE; consreadnum(0, bp, NUMSIZE, mp->intr, NUMSIZE); bp += NUMSIZE; consreadnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE); bp += NUMSIZE; consreadnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE); bp += NUMSIZE; consreadnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE); bp += NUMSIZE; consreadnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE); bp += NUMSIZE; consreadnum(0, bp, NUMSIZE, mp->load, NUMSIZE); bp += NUMSIZE; consreadnum(0, bp, NUMSIZE, (mp->perf.avg_inidle * 100) / mp->perf.period, NUMSIZE); bp += NUMSIZE; consreadnum(0, bp, NUMSIZE, (mp->perf.avg_inintr * 100) / mp->perf.period, NUMSIZE); bp += NUMSIZE; *bp++ = '\n'; } } if (waserror()) { kfree(b); nexterror(); } n = consreadstr((uint32_t) offset, buf, n, b); kfree(b); poperror(); return n; case Qswap: snprintf(tmp, sizeof tmp, "%lud memory\n" "%d pagesize\n" "%lud kernel\n" "%lud/%lud user\n" "%lud/%lud swap\n" "%lud/%lud kernel malloc\n" "%lud/%lud kernel draw\n", conf.npage * BY2PG, BY2PG, conf.npage - conf.upages, palloc.user - palloc.freecount, palloc.user, conf.nswap - swapalloc.free, conf.nswap, mainmem->cursize, mainmem->maxsize, imagmem->cursize, imagmem->maxsize); return consreadstr((uint32_t) offset, buf, n, tmp); #endif case Qsysname: if (sysname == NULL) return 0; return consreadstr((uint32_t) offset, buf, n, sysname); case Qdrivers: b = kzmalloc(READSTR, 0); if (b == NULL) error(ENOMEM, "allocation for /dev/drivers read failed"); k = 0; for (int i = 0; &devtab[i] < __devtabend; i++) k += snprintf(b + k, READSTR - k, "#%s\n", devtab[i].name); if (waserror()) { kfree(b); nexterror(); } n = consreadstr((uint32_t) offset, buf, n, b); kfree(b); poperror(); return n; case Qklog: //return qread(klogq, buf, n); /* the queue gives us some elasticity for log reading. */ if (!logqueue) logqueue = qopen(1 << 20, 0, 0, 0); if (logqueue) { int ret; /* atomic sets/gets are not that important in this case. */ reading_kmesg = 1; qwrite(logqueue, logbuffer, index); index = 0; ret = qread(logqueue, buf, n); reading_kmesg = 0; return ret; } break; case Qzero: memset(buf, 0, n); return n; case Qosversion: snprintf(tmp, sizeof tmp, "2000"); n = consreadstr((uint32_t) offset, buf, n, tmp); return n; default: printd("consread %#llux\n", c->qid.path); error(EINVAL, "bad QID in consread"); } return -1; /* never reached */ }
static long consread(Chan *c, void *buf, long n, vlong off) { ulong l; Mach *mp; char *b, *bp, ch; char tmp[256]; /* must be >= 18*NUMSIZE (Qswap) */ int i, k, id, send; vlong offset = off; if(n <= 0) return n; switch((ulong)c->qid.path){ case Qdir: return devdirread(c, buf, n, consdir, nelem(consdir), devgen); case Qcons: qlock(&kbd.lk); if(waserror()) { qunlock(&kbd.lk); nexterror(); } while(!qcanread(lineq)){ if(qread(kbdq, &ch, 1) == 0) continue; send = 0; if(ch == 0){ /* flush output on rawoff -> rawon */ if(kbd.x > 0) send = !qcanread(kbdq); }else if(kbd.raw){ kbd.line[kbd.x++] = ch; send = !qcanread(kbdq); }else{ switch(ch){ case '\b': if(kbd.x > 0) kbd.x--; break; case 0x15: /* ^U */ kbd.x = 0; break; case '\n': case 0x04: /* ^D */ send = 1; default: if(ch != 0x04) kbd.line[kbd.x++] = ch; break; } } if(send || kbd.x == sizeof kbd.line){ qwrite(lineq, kbd.line, kbd.x); kbd.x = 0; } } n = qread(lineq, buf, n); qunlock(&kbd.lk); poperror(); return n; case Qcputime: k = offset; if(k >= 6*NUMSIZE) return 0; if(k+n > 6*NUMSIZE) n = 6*NUMSIZE - k; /* easiest to format in a separate buffer and copy out */ for(i=0; i<6 && NUMSIZE*i<k+n; i++){ l = up->time[i]; if(i == TReal) l = msec() - l; l = TK2MS(l); readnum(0, tmp+NUMSIZE*i, NUMSIZE, l, NUMSIZE); } memmove(buf, tmp+k, n); return n; case Qkmesg: /* * This is unlocked to avoid tying up a process * that's writing to the buffer. kmesg.n never * gets smaller, so worst case the reader will * see a slurred buffer. */ if(off >= kmesg.n) n = 0; else{ if(off+n > kmesg.n) n = kmesg.n - off; memmove(buf, kmesg.buf+off, n); } return n; case Qkprint: return qread(kprintoq, buf, n); case Qpgrpid: return readnum((ulong)offset, buf, n, up->pgrp->pgrpid, NUMSIZE); case Qpid: return readnum((ulong)offset, buf, n, up->pid, NUMSIZE); case Qppid: return readnum((ulong)offset, buf, n, up->parentpid, NUMSIZE); case Qtime: return readtime((ulong)offset, buf, n); case Qbintime: return readbintime(buf, n); case Qhostowner: return readstr((ulong)offset, buf, n, eve); case Qhostdomain: return readstr((ulong)offset, buf, n, hostdomain); case Quser: return readstr((ulong)offset, buf, n, up->user); case Qnull: return 0; case Qsysstat: b = smalloc(conf.nmach*(NUMSIZE*11+1) + 1); /* +1 for NUL */ bp = b; for(id = 0; id < 32; id++) { if(active.machs & (1<<id)) { mp = MACHP(id); readnum(0, bp, NUMSIZE, id, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->cs, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->intr, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->syscall, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->pfault, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, mp->load, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, (mp->perf.avg_inidle*100)/mp->perf.period, NUMSIZE); bp += NUMSIZE; readnum(0, bp, NUMSIZE, (mp->perf.avg_inintr*100)/mp->perf.period, NUMSIZE); bp += NUMSIZE; *bp++ = '\n'; } } if(waserror()){ free(b); nexterror(); } n = readstr((ulong)offset, buf, n, b); free(b); poperror(); return n; case Qswap: tmp[0] = 0; return readstr((ulong)offset, buf, n, tmp); case Qsysname: if(sysname == nil) return 0; return readstr((ulong)offset, buf, n, sysname); case Qrandom: return randomread(buf, n); case Qdrivers: b = malloc(READSTR); if(b == nil) error(Enomem); n = 0; for(i = 0; devtab[i] != nil; i++) n += snprint(b+n, READSTR-n, "#%C %s\n", devtab[i]->dc, devtab[i]->name); if(waserror()){ free(b); nexterror(); } n = readstr((ulong)offset, buf, n, b); free(b); poperror(); return n; case Qzero: memset(buf, 0, n); return n; case Qosversion: snprint(tmp, sizeof tmp, "2000"); n = readstr((ulong)offset, buf, n, tmp); return n; default: print("consread 0x%llux\n", c->qid.path); error(Egreg); } return -1; /* never reached */ }