From 4ba7baf2b947af31108b7d0494658651c77ba36a Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 24 Oct 1990 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1990-10-24 --- gnot/devcons.c | 2 +- gnot/devdk.c | 112 ++++++++++++++++++++++++++++++++++++------------ gnot/devincon.c | 6 +++ gnot/fns.h | 2 +- gnot/stream.c | 8 +++- port/devdk.c | 4 -- 6 files changed, 99 insertions(+), 35 deletions(-) diff --git a/gnot/devcons.c b/gnot/devcons.c index b9caaeadca3bad1b083cfc0f3434a6400e845d3e..a93eb6c1d3a1eee7fe54ab9d9c04c92a551f89c1 100644 --- a/gnot/devcons.c +++ b/gnot/devcons.c @@ -537,7 +537,7 @@ consclose(Chan *c) { if(c->qid==Qrcons && (c->flag&COPEN)) decref(&raw); - if(c->qid == Qrs232) + if(c->stream) streamclose(c); } diff --git a/gnot/devdk.c b/gnot/devdk.c index c492391c541978c6d95227b7d84ed86ed3e68141..412d55eb3a5f3d22748feb099e9eb6854e967293 100644 --- a/gnot/devdk.c +++ b/gnot/devdk.c @@ -116,10 +116,10 @@ struct Line { * dkmux line discipline is pushed onto. */ struct Dk { - QLock; - int ref; + Lock; char name[64]; /* dk name */ Queue *wq; /* dk output queue */ + Stream *s; int lines; /* number of lines */ int ncsc; /* csc line number */ Chan *csc; /* common signalling line */ @@ -189,6 +189,7 @@ static void dktimer(void*); static void dkchgmesg(Dk*, Dkmsg*, int); static void dkreplymesg(Dk*, Dkmsg*, int); Chan* dkopen(Chan*, int); +static void dkhangup(Line*); /* * the datakit multiplexor stream module definition @@ -201,6 +202,7 @@ Qinfo dkmuxinfo = { dkmuxiput, dkmuxoput, dkmuxopen, dkmuxclose, "dkmux" }; /* * a new dkmux. find a free dk structure and assign it to this queue. + * when we get though here dp->s is meaningful and the name is set to "/". */ static void dkmuxopen(Queue *q, Stream *s) @@ -209,20 +211,21 @@ dkmuxopen(Queue *q, Stream *s) int i; for(dp = dk; dp < &dk[Ndk]; dp++){ - if(dp->wq == 0){ - qlock(dp); - if(dp->wq) { + if(dp->name[0]==0){ + lock(dp); + if(dp->name[0]){ /* someone was faster than us */ - qunlock(dp); + unlock(dp); continue; } q->ptr = q->other->ptr = (void *)dp; dp->csc = 0; dp->ncsc = 4; dp->lines = 16; - dp->name[0] = 0; + strcpy(dp->name, "/"); dp->wq = WR(q); - qunlock(dp); + dp->s = s; + unlock(dp); return; } } @@ -236,13 +239,22 @@ static void dkmuxclose(Queue *q) { Dk *dp; + int i; dp = (Dk *)q->ptr; - qlock(dp); - if(dp->csc) - close(dp->csc); - dp->wq = 0; - qunlock(dp); + + /* + * if we're the last user of the stream, + * free the Dk structure + */ + if(dp->s->inuse == 1) + dp->name[0] = 0; + + /* + * hang up all datakit connections + */ + for(i=dp->ncsc; i < dp->lines; i++) + dkhangup(&dp->line[i]); } /* @@ -272,7 +284,7 @@ dkmuxoput(Queue *q, Block *bp) * * Simplifying assumption: one put == one message && the channel number * is in the first block. If this isn't true, demultiplexing will not - * work. + * work. */ static void dkmuxiput(Queue *q, Block *bp) @@ -608,30 +620,53 @@ dkattach(char *spec) if(*spec == 0) spec = "dk"; for(dp = dk; dp < &dk[Ndk]; dp++){ - qlock(dp); - if(dp->wq && strcmp(spec, dp->name)==0) { - dp->ref++; - qunlock(dp); + lock(dp); + if(strcmp(spec, dp->name)==0) break; - } - qunlock(dp); + unlock(dp); } if(dp == &dk[Ndk]) error(0, Enoifc); + + /* + * don't let the multiplexed stream disappear under us + */ + if(streamenter(dp->s) < 0){ + /* + * it's closing down, forget it + */ + unlock(dp); + error(0, Ehungup); + } + + /* + * return the new channel + */ + if(waserror()){ + if(streamexit(dp->s, 0) == 0) + dp->name[0] = 0; + unlock(dp); + nexterror(); + } c = devattach('k', spec); c->dev = dp - dk; + unlock(dp); + poperror(); return c; } +/* + * clone as long as the multiplexed channel is not closing + * down + */ Chan* dkclone(Chan *c, Chan *nc) { Dk *dp; dp = &dk[c->dev]; - qlock(dp); - dp->ref++; - qunlock(dp); + if(streamenter(dp->s) < 0) + error(0, Ehungup); return devclone(c, nc); } @@ -679,10 +714,10 @@ dkopen(Chan *c, int omode) error(0, Ebadarg); } else switch(STREAMTYPE(c->qid)){ case Dcloneqid: + dp = &dk[c->dev]; /* * get an unused device and open it's control file */ - dp = &dk[c->dev]; end = &dp->line[dp->lines]; for(lp = &dp->line[dp->ncsc+1]; lp < end; lp++){ if(lp->state == Lclosed && canqlock(lp)){ @@ -752,10 +787,13 @@ dkclose(Chan *c) if(c->stream) streamclose(c); + /* + * Let go of the mulitplexed stream. If we're the last out, + * free dp. + */ dp = &dk[c->dev]; - qlock(dp); - dp->ref--; - qunlock(dp); + if(streamexit(dp->s, 0) == 0) + dp->name[0] = 0; } long @@ -1320,12 +1358,25 @@ dkcsckproc(void *a) dp = (Dk *)a; + if(waserror()){ + Chan *csc; + + csc = dp->csc; + lock(dp); + dp->csc = 0; + unlock(dp); + close(csc); + return; + } + /* * loop forever listening */ for(;;){ n = streamread(dp->csc, (char *)&d, (long)sizeof(d)); if(n != sizeof(d)){ + if(n == 0) + error(0, Ehungup); print("strange csc message %d\n", n); continue; } @@ -1527,8 +1578,12 @@ dktimer(void *a) */ for(dki=0; dkicsc==0) + if(!canlock(dp)) continue; + if(dp->csc==0){ + unlock(dp); + continue; + } /* * send keep alive @@ -1553,6 +1608,7 @@ dktimer(void *a) break; } } + unlock(dp); } tsleep(&dkt, fuckit, 0, 7500); } diff --git a/gnot/devincon.c b/gnot/devincon.c index 10bf3df2cdd9896d78629dd6c59f75c277358340..e2b479cc67b8aa3ea17ce51c3f83fdc74aab7c2e 100644 --- a/gnot/devincon.c +++ b/gnot/devincon.c @@ -610,6 +610,12 @@ inconkproc(void *arg) bp->wptr += 3; } + /* + * ignore errors + */ + if(waserror()) + ; + for(;;){ /* * sleep if input fifo empty diff --git a/gnot/fns.h b/gnot/fns.h index 4f56834e6e923649e0766f3fefdc2fd001cb5995..8999502e7e8388d5116aed3d5fada970e7f50d02 100644 --- a/gnot/fns.h +++ b/gnot/fns.h @@ -155,7 +155,7 @@ Devgen streamgen; void streamclose(Chan*); void streamclose1(Stream*); int streamenter(Stream*); -void streamexit(Stream*, int); +int streamexit(Stream*, int); void streaminit(void); long streamread(Chan*, void*, long); long streamwrite(Chan*, void*, long, int); diff --git a/gnot/stream.c b/gnot/stream.c index bd317bf6e200f6cbff3bab455c07c1d55394e138..d4380b8da0ddea6ca3fdd6b509c6c068c049b07f 100644 --- a/gnot/stream.c +++ b/gnot/stream.c @@ -746,11 +746,12 @@ streamenter(Stream *s) * Decrement the reference count on a stream. If the count is * zero, free the stream. */ -void +int streamexit(Stream *s, int locked) { Queue *q; Queue *nq; + int rv; if(!locked) lock(s); @@ -765,8 +766,10 @@ streamexit(Stream *s, int locked) s->id = s->dev = s->type = 0; } s->inuse--; + rv = s->inuse; if(!locked) unlock(s); + return rv; } /* @@ -791,6 +794,9 @@ streamclose1(Stream *s) for(q = s->procq; q; q = q->next){ if(q->info->close) (*q->info->close)(q->other); + RD(q)->put = nullput; + WR(q)->put = nullput; + /* * this may be 2 streams joined device end to device end */ diff --git a/port/devdk.c b/port/devdk.c index 93dd488ef23f71280235a7cebd669c820388527f..c492391c541978c6d95227b7d84ed86ed3e68141 100644 --- a/port/devdk.c +++ b/port/devdk.c @@ -206,7 +206,6 @@ static void dkmuxopen(Queue *q, Stream *s) { Dk *dp; - Line *lp; int i; for(dp = dk; dp < &dk[Ndk]; dp++){ @@ -223,9 +222,6 @@ dkmuxopen(Queue *q, Stream *s) dp->lines = 16; dp->name[0] = 0; dp->wq = WR(q); - for(lp = dp->line; lp < &dp->line[Nline]; lp++) - if(lp->state != 0) - panic("dkmuxopen l %d s %lux", lp-dp->line, lp->state); qunlock(dp); return; }