From 95f38fb193753bdaddc188c9b9501d6d1f95217e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 6 Dec 1990 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1990-12-06 --- gnot/sturp.c | 140 +++++++++-------------------- port/devmnt.c | 19 ++++ port/sturp.c | 140 +++++++++-------------------- power/devrtc.c | 235 +++++++++++++++++++++++++++---------------------- 4 files changed, 233 insertions(+), 301 deletions(-) diff --git a/gnot/sturp.c b/gnot/sturp.c index d3f6c462efebad7eb125cc3ac722a1be28999b8e..ed99aea02ef32ca92b4d748dbcf4ceaf99c0bb72 100644 --- a/gnot/sturp.c +++ b/gnot/sturp.c @@ -33,9 +33,9 @@ struct urpstat { } urpstat; struct Urp { - Lock; + QLock; short state; /* flags */ - Rendez r; /* process waiting for close */ + Rendez r; /* process waiting for output to finish */ /* input */ QLock ack; /* ack lock */ @@ -59,9 +59,13 @@ struct Urp { QLock xl[8]; ulong timer; /* timeout for xmit */ int rexmit; - - int kstarted; }; +Urp *urp; + +Rendez urpkr; +QLock urpkl; +int urpkstarted; + #define WINDOW(u) ((u)->unechoed>(u)->next ? (u)->unechoed+(u)->maxout-(u)->next-8 :\ (u)->unechoed+(u)->maxout-(u)->next) #define IN(x, f, n) (f<=n ? (x>=f && x=f)) @@ -96,8 +100,6 @@ struct Urp { #define OPEN 0x8 #define CLOSING 0x10 -Urp *urp; - /* * predeclared */ @@ -117,7 +119,6 @@ static void sendrej(Urp*); static void initoutput(Urp*, int); static void initinput(Urp*, int); static void urpkproc(void *arg); -static void urptimer(Alarm*); static void urpvomit(char*, Urp*); Qinfo urpinfo = @@ -134,7 +135,6 @@ static void urpreset(void) { urp = (Urp *)ialloc(conf.nurp*sizeof(Urp), 0); - alarm(500, urptimer, 0); } static void @@ -144,14 +144,23 @@ urpopen(Queue *q, Stream *s) int i; char name[128]; + if(!urpkstarted){ + qlock(&urpkl); + if(!urpkstarted){ + urpkstarted = 1; + kproc("urpkproc", urpkproc, 0); + } + qunlock(&urpkl); + } + /* * find a free urp structure */ for(up = urp; up < &urp[conf.nurp]; up++){ - lock(up); + qlock(up); if(up->state == 0) break; - unlock(up); + qunlock(up); } if(up == &urp[conf.nurp]){ q->ptr = 0; @@ -163,29 +172,15 @@ urpopen(Queue *q, Stream *s) up->rq = q; up->wq = q->other; up->state = OPEN; - unlock(up); + qunlock(up); initinput(up, 0); initoutput(up, 0); - - /* - * start the ack/(re)xmit process - */ - sprint(name, "urp%d", up - urp); - kproc(name, urpkproc, up); } /* * Shut down the connection and kill off the kernel process */ static int -isdead(void *a) -{ - Urp *up; - - up = (Urp *)a; - return up->kstarted==0; -} -static int isflushed(void *a) { Urp *up; @@ -212,12 +207,7 @@ urpclose(Queue *q) */ up->state |= CLOSING; tsleep(&up->r, isflushed, up, 2*60*1000); - - /* - * tell kernel process to die - */ up->state |= HUNGUP; - wakeup(&up->rq->r); qlock(&up->xmit); /* @@ -238,16 +228,9 @@ urpclose(Queue *q) } qunlock(&up->xmit); - /* - * wait for kernel process to die - */ - while(up->kstarted) - sleep(&up->r, isdead, up); - - lock(up); + qlock(up); up->state = 0; - up->rq = 0; - unlock(up); + qunlock(up); } /* @@ -260,7 +243,6 @@ urpctliput(Urp *up, Queue *q, Block *bp) case M_HANGUP: up->state |= HUNGUP; wakeup(&up->r); - wakeup(&up->rq->r); break; } PUTNEXT(q, bp); @@ -319,7 +301,7 @@ urpciput(Queue *q, Block *bp) case AINIT: up->state &= ~INITING; flushinput(up); - wakeup(&up->rq->r); + wakeup(&urpkr); break; case INIT0: @@ -440,7 +422,7 @@ urpiput(Queue *q, Block *bp) case AINIT: up->state &= ~INITING; flushinput(up); - wakeup(&up->rq->r); + wakeup(&urpkr); break; case INIT0: @@ -873,7 +855,7 @@ rcvack(Urp *up, int msg) break; } - wakeup(&up->rq->r); + wakeup(&urpkr); } /* @@ -950,69 +932,29 @@ initinput(Urp *up, int window) flushinput(up); } -/* - * do retransmissions etc - */ -static int -todo(void *arg) -{ - Urp *up; - - up = (Urp *)arg; - - return (up->state&INITING) - ? NOW>up->timer /* time to INIT1 */ - : ((up->unechoed!=up->next && NOW>up->timer) /* time to ENQ */ - || (WINDOW(up)>0 && (up->next!=up->nxb || up->wq->first)) /* open xmit window */ - || (up->iseq!=(up->lastecho&7) && !QFULL(up->rq->next))); /* time to ECHO */ -} static void urpkproc(void *arg) { - Urp *up; + Urp *up, *eup; - up = (Urp *)arg; - up->kstarted = 1; + if(waserror()) + ; - if(waserror()){ - print("urpkproc error %ux\n", up); - up->kstarted = 0; - wakeup(&up->r); - return; - } + eup = urp + conf.nurp; for(;;){ - if(up->state & HUNGUP) - break; - if(!QFULL(up->rq->next)) - sendack(up); - output(up); - sleep(&up->rq->r, todo, up); - } - up->kstarted = 0; - wakeup(&up->r); - poperror(); -} - -/* - * timer to wakeup urpkproc's for retransmissions - */ -static void -urptimer(Alarm *a) -{ - Urp *up; - Urp *last; - - cancel(a); - alarm(500, urptimer, 0); - for(up = urp, last = &urp[conf.nurp]; up < last; up++){ - if(up->state==0) - continue; - if(up->rq && canlock(up)){ - if(up->rq && NOW>up->timer - && ((up->state&INITING) || up->unechoed!=up->next)) - wakeup(&up->rq->r); - unlock(up); + for(up = urp; up < eup; up++){ + if(up->state==0 || (up->state&HUNGUP)) + break; + if(!canqlock(up)) + continue; + if(up->state==0 || (up->state&HUNGUP)) + break; + if(up->iseq!=(up->lastecho&7) && !QFULL(up->rq->next)) + sendack(up); + output(up); + qunlock(up); } + tsleep(&urpkr, return0, 0, 1000); } } diff --git a/port/devmnt.c b/port/devmnt.c index d026eaf296f0badd4b3c59cdc1f26c3d8c13d3ae..ae0c1ee728eaa07ce6473c7c290b7fe8256bd4c3 100644 --- a/port/devmnt.c +++ b/port/devmnt.c @@ -37,6 +37,7 @@ struct Mntbuf { Mntbuf *next; char buf[BUFSIZE]; + int n; }; struct @@ -665,6 +666,20 @@ mntreadreply(void *a) return ((Mnthdr *)a)->readreply; } +/* + * print out first few bytes of the message + */ +dumpmsg(Mntbuf *mb) +{ + int i; + char *x; + + x = mb->buf; + for(i = 0; i < mb->n; i++) + print("%.2ux ", *x++); + print("\n"); +} + void mntxmit(Mnt *m, Mnthdr *mh) { @@ -777,8 +792,10 @@ mntxmit(Mnt *m, Mnthdr *mh) mh->mbr = mballoc(); n = (*devtab[q->msg->type].read)(q->msg, mh->mbr->buf, BUFSIZE); poperror(); /* 3 */ + mh->mbr->n = n; if(convM2S(mh->mbr->buf, &mh->rhdr, n) == 0){ print("bad reply message\n"); + dumpmsg(mh->mbr); mnterrdequeue(m, mh); error(Ebadmsg); } @@ -806,6 +823,7 @@ mntxmit(Mnt *m, Mnthdr *mh) */ if(tag<0 || tag>=conf.nmnthdr){ print("unknown tag %d\n", tag); + dumpmsg(mh->mbr); goto Read; } w = &mnthdralloc.arena[tag]; @@ -853,6 +871,7 @@ mntxmit(Mnt *m, Mnthdr *mh) error(Eshutdown); }else if(mh->rhdr.type != mh->thdr.type+1){ print("bad type %d not %d in mntxmit\n", mh->rhdr.type, mh->thdr.type+1); + dumpmsg(mh->mbr); error(Ebadmsg); } /* diff --git a/port/sturp.c b/port/sturp.c index d3f6c462efebad7eb125cc3ac722a1be28999b8e..ed99aea02ef32ca92b4d748dbcf4ceaf99c0bb72 100644 --- a/port/sturp.c +++ b/port/sturp.c @@ -33,9 +33,9 @@ struct urpstat { } urpstat; struct Urp { - Lock; + QLock; short state; /* flags */ - Rendez r; /* process waiting for close */ + Rendez r; /* process waiting for output to finish */ /* input */ QLock ack; /* ack lock */ @@ -59,9 +59,13 @@ struct Urp { QLock xl[8]; ulong timer; /* timeout for xmit */ int rexmit; - - int kstarted; }; +Urp *urp; + +Rendez urpkr; +QLock urpkl; +int urpkstarted; + #define WINDOW(u) ((u)->unechoed>(u)->next ? (u)->unechoed+(u)->maxout-(u)->next-8 :\ (u)->unechoed+(u)->maxout-(u)->next) #define IN(x, f, n) (f<=n ? (x>=f && x=f)) @@ -96,8 +100,6 @@ struct Urp { #define OPEN 0x8 #define CLOSING 0x10 -Urp *urp; - /* * predeclared */ @@ -117,7 +119,6 @@ static void sendrej(Urp*); static void initoutput(Urp*, int); static void initinput(Urp*, int); static void urpkproc(void *arg); -static void urptimer(Alarm*); static void urpvomit(char*, Urp*); Qinfo urpinfo = @@ -134,7 +135,6 @@ static void urpreset(void) { urp = (Urp *)ialloc(conf.nurp*sizeof(Urp), 0); - alarm(500, urptimer, 0); } static void @@ -144,14 +144,23 @@ urpopen(Queue *q, Stream *s) int i; char name[128]; + if(!urpkstarted){ + qlock(&urpkl); + if(!urpkstarted){ + urpkstarted = 1; + kproc("urpkproc", urpkproc, 0); + } + qunlock(&urpkl); + } + /* * find a free urp structure */ for(up = urp; up < &urp[conf.nurp]; up++){ - lock(up); + qlock(up); if(up->state == 0) break; - unlock(up); + qunlock(up); } if(up == &urp[conf.nurp]){ q->ptr = 0; @@ -163,29 +172,15 @@ urpopen(Queue *q, Stream *s) up->rq = q; up->wq = q->other; up->state = OPEN; - unlock(up); + qunlock(up); initinput(up, 0); initoutput(up, 0); - - /* - * start the ack/(re)xmit process - */ - sprint(name, "urp%d", up - urp); - kproc(name, urpkproc, up); } /* * Shut down the connection and kill off the kernel process */ static int -isdead(void *a) -{ - Urp *up; - - up = (Urp *)a; - return up->kstarted==0; -} -static int isflushed(void *a) { Urp *up; @@ -212,12 +207,7 @@ urpclose(Queue *q) */ up->state |= CLOSING; tsleep(&up->r, isflushed, up, 2*60*1000); - - /* - * tell kernel process to die - */ up->state |= HUNGUP; - wakeup(&up->rq->r); qlock(&up->xmit); /* @@ -238,16 +228,9 @@ urpclose(Queue *q) } qunlock(&up->xmit); - /* - * wait for kernel process to die - */ - while(up->kstarted) - sleep(&up->r, isdead, up); - - lock(up); + qlock(up); up->state = 0; - up->rq = 0; - unlock(up); + qunlock(up); } /* @@ -260,7 +243,6 @@ urpctliput(Urp *up, Queue *q, Block *bp) case M_HANGUP: up->state |= HUNGUP; wakeup(&up->r); - wakeup(&up->rq->r); break; } PUTNEXT(q, bp); @@ -319,7 +301,7 @@ urpciput(Queue *q, Block *bp) case AINIT: up->state &= ~INITING; flushinput(up); - wakeup(&up->rq->r); + wakeup(&urpkr); break; case INIT0: @@ -440,7 +422,7 @@ urpiput(Queue *q, Block *bp) case AINIT: up->state &= ~INITING; flushinput(up); - wakeup(&up->rq->r); + wakeup(&urpkr); break; case INIT0: @@ -873,7 +855,7 @@ rcvack(Urp *up, int msg) break; } - wakeup(&up->rq->r); + wakeup(&urpkr); } /* @@ -950,69 +932,29 @@ initinput(Urp *up, int window) flushinput(up); } -/* - * do retransmissions etc - */ -static int -todo(void *arg) -{ - Urp *up; - - up = (Urp *)arg; - - return (up->state&INITING) - ? NOW>up->timer /* time to INIT1 */ - : ((up->unechoed!=up->next && NOW>up->timer) /* time to ENQ */ - || (WINDOW(up)>0 && (up->next!=up->nxb || up->wq->first)) /* open xmit window */ - || (up->iseq!=(up->lastecho&7) && !QFULL(up->rq->next))); /* time to ECHO */ -} static void urpkproc(void *arg) { - Urp *up; + Urp *up, *eup; - up = (Urp *)arg; - up->kstarted = 1; + if(waserror()) + ; - if(waserror()){ - print("urpkproc error %ux\n", up); - up->kstarted = 0; - wakeup(&up->r); - return; - } + eup = urp + conf.nurp; for(;;){ - if(up->state & HUNGUP) - break; - if(!QFULL(up->rq->next)) - sendack(up); - output(up); - sleep(&up->rq->r, todo, up); - } - up->kstarted = 0; - wakeup(&up->r); - poperror(); -} - -/* - * timer to wakeup urpkproc's for retransmissions - */ -static void -urptimer(Alarm *a) -{ - Urp *up; - Urp *last; - - cancel(a); - alarm(500, urptimer, 0); - for(up = urp, last = &urp[conf.nurp]; up < last; up++){ - if(up->state==0) - continue; - if(up->rq && canlock(up)){ - if(up->rq && NOW>up->timer - && ((up->state&INITING) || up->unechoed!=up->next)) - wakeup(&up->rq->r); - unlock(up); + for(up = urp; up < eup; up++){ + if(up->state==0 || (up->state&HUNGUP)) + break; + if(!canqlock(up)) + continue; + if(up->state==0 || (up->state&HUNGUP)) + break; + if(up->iseq!=(up->lastecho&7) && !QFULL(up->rq->next)) + sendack(up); + output(up); + qunlock(up); } + tsleep(&urpkr, return0, 0, 1000); } } diff --git a/power/devrtc.c b/power/devrtc.c index 0e51a0c8c3087aeee55e23550a4bb1fbe7101ca7..a13ac555a7383f1aba1db40a9cb7b67454b044ca 100644 --- a/power/devrtc.c +++ b/power/devrtc.c @@ -8,10 +8,14 @@ #include "io.h" -typedef struct Rtc Rtc; +typedef struct Rtc Rtc; + +enum { + Nbcd = 8 /* number of bcd bytes in the clock */ +}; + struct Rtc { - QLock; int sec; int min; int hour; @@ -19,9 +23,10 @@ struct Rtc int mon; int year; }; -Rtc rtc; -Dirtab rtcdir[]={ +QLock rtclock; /* mutex on clock operations */ + +static Dirtab rtcdir[]={ "rtc", {1}, 0, 0600, }; @@ -30,6 +35,10 @@ static uchar pattern[] = 0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c }; +ulong rtc2sec(Rtc*); +void sec2rtc(ulong, Rtc*); +int *yrsize(int); + /* * issue pattern recognition bits to nv ram to address the * real time clock @@ -51,7 +60,7 @@ rtcpattern(void) * stuff the pattern recognition codes one bit at * a time into *nv. */ - for(i = 0; i < sizeof(pattern); i++){ + for(i = 0; i < Nbcd; i++){ ch = pattern[i]; for (j = 0; j < 8; j++){ *nv = ch & 0x1; @@ -103,6 +112,10 @@ rtcstat(Chan *c, char *dp) Chan* rtcopen(Chan *c, int omode) { + if(c->qid.path==1 && (omode&(OWRITE|OTRUNC))){ + if(strcmp(u->p->pgrp->user, "bootes")) /* BUG */ + error(Eperm); + } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; @@ -120,7 +133,7 @@ rtcclose(Chan *c) { } -#define GETBCD(o) ((clock[o]&0xf) + 10*(clock[o]>>4)) +#define GETBCD(o) ((bcdclock[o]&0xf) + 10*(bcdclock[o]>>4)) long rtcread(Chan *c, void *buf, long n) @@ -128,29 +141,38 @@ rtcread(Chan *c, void *buf, long n) int i,j; uchar ch; uchar *nv; - uchar clock[8]; + uchar bcdclock[Nbcd]; char atime[64]; + Rtc rtc; - if(c->offset!=0) - error(Ebadarg); nv = RTC; /* * set up the pattern for the clock */ - qlock(&rtc); + qlock(&rtclock); rtcpattern(); /* * read out the clock one bit at a time */ - for (i = 0; i < 8; i++){ + for (i = 0; i < Nbcd; i++){ ch = 0; for (j = 0; j < 8; j++) ch |= ((*nv & 0x1) << j); - clock[i] = ch; + bcdclock[i] = ch; } - qunlock(&rtc); + qunlock(&rtclock); + + /* + * see if the clock oscillator is on + */ + if(bcdclock[4] & 0x20) + return 0; /* nope, time is bogus */ + + /* + * convert from BCD + */ rtc.sec = GETBCD(1); rtc.min = GETBCD(2); rtc.hour = GETBCD(3); @@ -166,80 +188,68 @@ rtcread(Chan *c, void *buf, long n) else rtc.year += 1900; - sprint(atime, "%.2d:%.2d:%.2d %d/%d/%d", rtc.hour, rtc.min, rtc.sec, - rtc.mon, rtc.mday, rtc.year); - i = strlen(atime); - - if(c->offset >= i) - return 0; - if(c->offset + n > i) - n = i - c->offset; - strncpy(buf, &atime[c->offset], n); - - return n; + return readnum(c->offset, buf, n, rtc2sec(&rtc), 12); } -static int perm[] = -{ - 3, 2, 1, 6, 5, 7 -}; +#define PUTBCD(n,o) bcdclock[o] = (n % 10) | (((n / 10) % 10)<<4) long rtcwrite(Chan *c, void *buf, long n) { + Rtc rtc; + ulong secs; int i,j; uchar ch; - uchar clock[8]; + uchar bcdclock[Nbcd]; uchar *nv; - char *cp; + char *cp, *ep; if(c->offset!=0) error(Ebadarg); /* - * parse (most any separator will do) + * read the time */ - ch = 0; - j = 0; - clock[0] = clock[4] = 0; - cp = buf; - for(i = 0; i < n; i++){ - switch(*cp){ - case ':': case ' ': case '\t': case '/': case '-': - clock[perm[j++]] = ch; - ch = 0; - break; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - ch = (ch<<4) | (*cp - '0'); + cp = ep = buf; + ep += n; + while(cp < ep){ + if(*cp>='0' && *cp<='9') break; - default: - error(Ebadarg); - } cp++; } - clock[perm[j++]] = ch; - if(j != 6) - error(Ebadarg); + secs = strtoul(cp, 0, 0); + + /* + * convert to bcd + */ + sec2rtc(secs, &rtc); + bcdclock[0] = bcdclock[4] = 0; + PUTBCD(rtc.sec, 1); + PUTBCD(rtc.min, 2); + PUTBCD(rtc.hour, 3); + PUTBCD(rtc.mday, 5); + PUTBCD(rtc.mon, 6); + PUTBCD(rtc.year, 7); /* * set up the pattern for the clock */ - qlock(&rtc); + qlock(&rtclock); rtcpattern(); /* * write the clock one bit at a time */ nv = RTC; - for (i = 0; i < 8; i++){ - ch = clock[i]; + for (i = 0; i < Nbcd; i++){ + ch = bcdclock[i]; for (j = 0; j < 8; j++){ *nv = ch & 1; ch >>= 1; } } - qunlock(&rtc); + qunlock(&rtclock); + return n; } @@ -255,45 +265,78 @@ rtcwstat(Chan *c, char *dp) error(Eperm); } -#define SEC2MIN 60 -#define SEC2HOUR (60*SEC2MIN) -#define SEC2DAY (24*SEC2HOUR) -#define SEC2YR (365*SEC2DAY) +#define SEC2MIN 60L +#define SEC2HOUR (60L*SEC2MIN) +#define SEC2DAY (24L*SEC2HOUR) -static char dmsize[12] = +/* + * days per month plus days/year + */ +static int dmsize[] = +{ + 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; +static int ldmsize[] = { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +/* + * return the days/month for the given year + */ +int * +yrsize(int yr) +{ + if((yr % 4) == 0) + return ldmsize; + else + return dmsize; +} + /* * compute seconds since Jan 1 1970 */ ulong -rtc2sec(void) +rtc2sec(Rtc *rtc) { ulong secs; int i; + int *d2m; + + secs = 0; + + /* + * seconds per year + */ + for(i = 1970; i < rtc->year; i++){ + d2m = yrsize(i); + secs += d2m[0] * SEC2DAY; + } + + /* + * seconds per month + */ + d2m = yrsize(rtc->year); + for(i = 1; i < rtc->mon; i++) + secs += d2m[i] * SEC2DAY; + + secs += (rtc->mday-1) * SEC2DAY; + secs += rtc->hour * SEC2HOUR; + secs += rtc->min * SEC2MIN; + secs += rtc->sec; - for(i = 1970; i < rtc.year; i++) - secs += dysize(i); - for(i = 0; i < rtc.mon-1; i++) - secs += dmsize[i] * SEC2DAY; - if(dysize(rtc.year)==366 && rtc.mon>2) - secs += SEC2DAY; - secs += (rtc.mday-1) * SEC2DAY; - secs += rtc.hour * SEC2HOUR; - secs += rtc.min * SEC2MIN; - secs += rtc.sec; return secs; } /* * compute rtc from seconds since Jan 1 1970 */ -sec2rtc(ulong secs) +void +sec2rtc(ulong secs, Rtc *rtc) { - int d0, d1; + int d; long hms, day; + int *d2m; /* * break initial number into days @@ -308,45 +351,31 @@ sec2rtc(ulong secs) /* * generate hours:minutes:seconds */ - rtc.sec = hms % SEC2MIN; - d1 = hms / SEC2MIN; - rtc.min = d1 % SEC2MIN; - d1 /= SEC2MIN; - rtc.hour = d1; + rtc->sec = hms % 60; + d = hms / 60; + rtc->min = d % 60; + d /= 60; + rtc->hour = d; /* * year number */ if(day >= 0) - for(d1 = 70; day >= dysize(d1); d1++) - day -= dysize(d1); + for(d = 1970; day >= *yrsize(d); d++) + day -= *yrsize(d); else - for (d1 = 70; day < 0; d1--) - day += dysize(d1-1); - rtc.year = d1; + for (d = 1970; day < 0; d--) + day += *yrsize(d-1); + rtc->year = d; /* * generate month */ - if(dysize(d1) == 366) - dmsize[1] = 29; - for(d1 = 0; d0 >= dmsize[d1]; d1++) - d0 -= dmsize[d1]; - dmsize[1] = 28; - rtc.mday = d0 + 1; - rtc.mon = d1; - return; -} + d2m = yrsize(rtc->year); + for(d = 1; day >= d2m[d]; d++) + day -= d2m[d]; + rtc->mday = day + 1; + rtc->mon = d; -/* - * days to year - */ -static -dysize(int y) -{ - - if((y%4) == 0) - return 366; - return 365; + return; } -