From 07a64a72bcb5487cf53e6c6775412c92c2f6285b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 19 Feb 1999 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1999-02-19 --- pc/clock.c | 1 - pc/ether589.c | 1 + pc/etherelnk3.c | 15 ++++- port/devaudio.c | 2 +- port/devcons.c | 130 ++++------------------------------------ port/devpipe.c | 4 +- port/portfns.h | 6 +- port/qio.c | 12 ++-- port/tod.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 195 insertions(+), 130 deletions(-) create mode 100644 port/tod.c diff --git a/pc/clock.c b/pc/clock.c index abf42626ed78b1f27752b2114dba8b68da0df7dc..a036d7efd41ee324490a55f963cca8e2a0347869 100644 --- a/pc/clock.c +++ b/pc/clock.c @@ -42,7 +42,6 @@ clockintr(Ureg* ureg, void*) m->ticks++; if(m->proc) m->proc->pc = ureg->pc; - fixtod(); accounttime(); if(kproftimer != nil) diff --git a/pc/ether589.c b/pc/ether589.c index fd940b8199de17001de0928076383f51c31b2433..d8931e2ddcc712827f6f61b23e1604100f822889 100644 --- a/pc/ether589.c +++ b/pc/ether589.c @@ -152,4 +152,5 @@ ether589link(void) { addethercard("3C589", reset); addethercard("3C562", reset); + addethercard("589E", reset); } diff --git a/pc/etherelnk3.c b/pc/etherelnk3.c index 02bba8eeb9c198f204c994c41f6f47fe4a78318f..7e5945cdb2f65da0c9122c96f50fce0d0014a13e 100644 --- a/pc/etherelnk3.c +++ b/pc/etherelnk3.c @@ -1399,11 +1399,22 @@ tcm59Xpci(void) } } +static char* tcmpcmcia[] = { + "3C589", /* 3COM 589[ABCD] */ + "3C562", /* 3COM 562 */ + "589E", /* 3COM Megahertz 589E */ + nil, +}; + static int tcm5XXpcmcia(Ether* ether) { - if(!cistrcmp(ether->type, "3C589") || !cistrcmp(ether->type, "3C562")) - return ether->port; + int i; + + for(i = 0; tcmpcmcia[i] != nil; i++){ + if(!cistrcmp(ether->type, tcmpcmcia[i])) + return ether->port; + } return 0; } diff --git a/port/devaudio.c b/port/devaudio.c index aaafb59edebd95640404b455996cb5f8b3434c4c..29f7de9b3b5dedcb7e5c47960879c2792b589087 100644 --- a/port/devaudio.c +++ b/port/devaudio.c @@ -885,7 +885,7 @@ audioclose(Chan *c) b = audio.filling; if(b) { audio.filling = 0; - memset(b->virt, 0, Bufsize-audio.curcount); + memset(b->virt+audio.curcount, 0, Bufsize-audio.curcount); swab(b->virt); putbuf(&audio.full, b); } diff --git a/port/devcons.c b/port/devcons.c index d191dc4f32eed1858f586c91c2228b374df609cc..d9364b3f9fe3f106eb08717dc20e3672dedffc23 100644 --- a/port/devcons.c +++ b/port/devcons.c @@ -27,6 +27,7 @@ static struct } kbd; char sysname[NAMELEN]; +vlong fasthz; static ulong randomread(void*, ulong); static void randominit(void); @@ -393,115 +394,6 @@ static Dirtab consdir[]={ "user", {Quser}, NAMELEN, 0666, }; -ulong boottime; /* seconds since epoch at boot */ - -struct -{ - Lock; - vlong hz; /* frequency of fast clock */ - vlong last; /* last reading of fast clock */ - vlong off; /* offset from epoch to last */ - vlong lastns; /* last return value from gettod */ - vlong bias; /* current bias */ - vlong delta; /* amount to add to bias each slow clock tick */ - int n; /* number of times to add in delta */ - int i; /* number of times we've added in delta */ -} tod; - -void -settod(vlong now, vlong delta, int n) -{ - ilock(&tod); - tod.last = fastticks(nil); - tod.off = now; - tod.delta = delta; - tod.n = n; - tod.i = 0; - iunlock(&tod); -} - -// largest vlong devided by 10, 100, ... -static vlong vlmax[9] = { - 9223372036LL, - 92233720368LL, - 922337203685LL, - 9223372036854LL, - 92233720368547LL, - 922337203685477LL, - 9223372036854775LL, - 92233720368547758LL, - 922337203685477580LL, -}; -static vlong vlmult[9] = { - 1000000000LL, - 100000000LL, - 10000000LL, - 1000000LL, - 100000LL, - 10000LL, - 1000LL, - 100LL, - 10LL, -}; - -vlong -gettod(void) -{ - vlong x; - int i; - - ilock(&tod); - if(tod.hz == 0) - x = fastticks((uvlong*)&tod.hz); - else - x = fastticks(nil); - x -= tod.last; - - /* convert to nanoseconds */ - for(i = 0; i < 9; i++) - if(x < vlmax[i]){ - x *= vlmult[i]; - break; - } - x /= tod.hz; - if(i > 0) - x *= vlmult[9-i]; - - /* convert to epoch */ - x += tod.off; - - /* add in bias */ - x += tod.bias; - - if(x < tod.lastns) - x = tod.lastns; - tod.lastns = x; - iunlock(&tod); - - return x; -} - -void -fixtod(void) -{ - ilock(&tod); - if(tod.n > tod.i) - tod.bias += tod.delta; - iunlock(&tod); -} - -long -seconds(void) -{ - vlong x; - int i; - - x = gettod(); - x /= 1000000000LL; - i = x; - return i; -} - int readvlnum(ulong off, char *buf, ulong n, uvlong val, int size) { @@ -549,6 +441,7 @@ readstr(ulong off, char *buf, ulong n, char *str) static void consinit(void) { + todinit(); randominit(); } @@ -718,8 +611,8 @@ consread(Chan *c, void *buf, long n, vlong off) return n; case Qfastclock: - if(tod.hz == 0L) - ticks = fastticks((uvlong*)&tod.hz); + if(fasthz == 0L) + ticks = fastticks((uvlong*)&fasthz); else ticks = fastticks(nil); @@ -729,7 +622,7 @@ consread(Chan *c, void *buf, long n, vlong off) if(k+n > 4*NUMSIZE) n = 4*NUMSIZE - k; readvlnum(0, tmp, 2*NUMSIZE, ticks, 2*NUMSIZE); - readvlnum(0, tmp+2*NUMSIZE, 2*NUMSIZE, tod.hz, 2*NUMSIZE); + readvlnum(0, tmp+2*NUMSIZE, 2*NUMSIZE, fasthz, 2*NUMSIZE); memmove(buf, tmp+k, n); return n; @@ -758,17 +651,17 @@ consread(Chan *c, void *buf, long n, vlong off) return 0; case Qnsec: - x = gettod(); + x = todget(); return readvlnum((ulong)offset, buf, n, x, 2*NUMSIZE); case Qmsec: - x = gettod(); + x = todget(); x /= 1000000LL; i = x; return readnum((ulong)offset, buf, n, i, NUMSIZE); case Qtime: - x = gettod(); + x = todget(); x /= 1000000000LL; i = x; return readnum((ulong)offset, buf, n, i, NUMSIZE); @@ -902,7 +795,7 @@ conswrite(Chan *c, void *va, long n, vlong off) cbuf[n] = 0; nsec = strtol(cbuf, 0, 0); nsec *= 1000000000LL; - settod(nsec, 0, 0); + todset(nsec, 0, 0); break; case Qfastclock: @@ -915,7 +808,8 @@ conswrite(Chan *c, void *va, long n, vlong off) f = strtovl(cbuf, 0, 0); if(f <= 0L) error(Ebadarg); - tod.hz = f; + fasthz = f; + todsetfreq(f); break; case Qnsec: @@ -928,7 +822,7 @@ conswrite(Chan *c, void *va, long n, vlong off) nsec = strtovl(cbuf, &a, 0); delta = strtovl(a, &a, 0); n = strtol(a, &a, 0); - settod(nsec, delta, n); + todset(nsec, delta, n); break; case Qkey: diff --git a/port/devpipe.c b/port/devpipe.c index 74f593968e3b02ee2054b8c72f2b4622c00f2204..b3021334bd814b2183e67be8bec0a3a3adcbd047 100644 --- a/port/devpipe.c +++ b/port/devpipe.c @@ -294,7 +294,7 @@ pipewrite(Chan *c, void *va, long n, vlong) /* avoid notes when pipe is a mounted queue */ if((c->flag & CMSG) == 0) postnote(up, 1, "sys: write on closed pipe", NUser); - error(Ehungup); + nexterror(); } p = c->aux; @@ -326,7 +326,7 @@ pipebwrite(Chan *c, Block *bp, ulong) /* avoid notes when pipe is a mounted queue */ if((c->flag & CMSG) == 0) postnote(up, 1, "sys: write on closed pipe", NUser); - error(Ehungup); + nexterror(); } p = c->aux; diff --git a/port/portfns.h b/port/portfns.h index c9d0d7f96055147ba5f728a3e0621a0e46249ac7..bd817fc6b894a0153de5161e1f55d9995e838d86 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -96,7 +96,6 @@ int fault(ulong, int); void fdclose(int, int); Chan* fdtochan(int, int, int, int); int fixfault(Segment*, ulong, int, int); -void fixtod(void); void flushmmu(void); void forkchild(Proc*, Ureg*); void forkret(void); @@ -296,6 +295,11 @@ void srvrecover(Chan*, Chan*); int swapcount(ulong); int swapfull(void); void swapinit(void); +vlong todget(void); +void todfix(void); +void todsetfreq(vlong); +void todinit(void); +void todset(vlong, vlong, int); Block* trimblock(Block*, int, int); void tsleep(Rendez*, int (*)(void*), void*, int); void unbreak(Proc*); diff --git a/port/qio.c b/port/qio.c index 3b6b72b7b4db85b11fbbabd6c042b50d86dd7aa8..06d466523a5b9d1c3b5b176ac73f179566020135 100644 --- a/port/qio.c +++ b/port/qio.c @@ -65,6 +65,8 @@ enum Hdrspc = 64, /* leave room for high-level headers */ Bdead = 0x51494F42, /* "QIOB" */ + + Maxatomic = 32*1024, }; void @@ -1092,7 +1094,7 @@ qbwrite(Queue *q, Block *b) } /* - * write to a queue. only 128k at a time is atomic. + * write to a queue. only Maxatomic bytes at a time is atomic. */ int qwrite(Queue *q, void *vp, int len) @@ -1107,8 +1109,8 @@ qwrite(Queue *q, void *vp, int len) sofar = 0; do { n = len-sofar; - if(n > 128*1024) - n = 128*1024; + if(n > Maxatomic) + n = Maxatomic; b = allocb(n); if(waserror()){ @@ -1143,8 +1145,8 @@ qiwrite(Queue *q, void *vp, int len) sofar = 0; do { n = len-sofar; - if(n > 128*1024) - n = 128*1024; + if(n > Maxatomic) + n = Maxatomic; b = allocb(n); memmove(b->wp, p+sofar, n); diff --git a/port/tod.c b/port/tod.c new file mode 100644 index 0000000000000000000000000000000000000000..4d321b3bf3bf273954ccb0e9579c7b70d2aaad9b --- /dev/null +++ b/port/tod.c @@ -0,0 +1,154 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + + +// frequency of the tod clock +#define TODFREQ 1000000000LL + +enum +{ + Log2mult= 22, // multiplier should have 22 bits + Log2todfreq= 30, // number of significant bits of TODFREQ +}; + +static vlong logtab[40]; + +struct { + Lock; + int shift; // time = (ticks*multiplier)>>shift + vlong multiplier; // ... + vlong hz; // frequency of fast clock + vlong last; // last reading of fast clock + vlong off; // offset from epoch to last + vlong lasttime; // last return value from gettod + vlong delta; // amount to add to bias each slow clock tick + int n; // number of times to add in delta + int i; // number of times we've added in delta +} tod; + +int +log2(vlong x) +{ + int i; + + for(i = 0; i < nelem(logtab); i++){ + if(x < logtab[i]) + break; + } + return i+8; +} + +void +todinit(void) +{ + vlong v; + int i; + + v = 1LL<<8; + for(i = 0; i < nelem(logtab); i++){ + logtab[i] = v; + v <<= 1; + } + fastticks((uvlong*)&tod.hz); + todsetfreq(tod.hz); + addclock0link(todfix); +} + +// +// This routine makes sure that the multiplier has +// at least Log2mult bits to guarantee that precision. +// +void +todsetfreq(vlong f) +{ + // this ensures that the multiplier has 22 bits + ilock(&tod); + tod.hz = f; + tod.shift = Log2mult - Log2todfreq + log2(f); + tod.multiplier = (TODFREQ<= 0){ + tod.off = t; + tod.last = fastticks(nil); + tod.lasttime = 0; + } else { + tod.delta = delta; + tod.n = n; + } + iunlock(&tod); +} + +// +// get time of day +// +vlong +todget(void) +{ + vlong ticks, x, diff; + + ilock(&tod); + + if(tod.hz == 0) + ticks = fastticks((uvlong*)&tod.hz); + else + ticks = fastticks(nil); + diff = ticks - tod.last; + + // convert to epoch + x = (diff*tod.multiplier)>>tod.shift; + x += tod.off; + + // protect against overflows + if(diff > (1LL<<(63-Log2mult))){ + tod.last = ticks; + tod.off = x; + } + + /* time can't go backwards */ + if(x < tod.lasttime) + x = tod.lasttime; + tod.lasttime = x; + + iunlock(&tod); + return x; +} + +// +// called every clock tick +// +void +todfix(void) +{ + if((MACHP(0)->ticks % HZ) != 0) + return; + ilock(&tod); + if(tod.n > tod.i++) + tod.off += tod.delta; + iunlock(&tod); +} + +long +seconds(void) +{ + vlong x; + int i; + + x = todget(); + x /= TODFREQ; + i = x; + return i; +}