don't overflow doing long writes on ptc (from thomas@utah-cs)
[unix-history] / usr / src / sys / kern / tty_subr.c
index 90c2f68..d584b5f 100644 (file)
@@ -1,30 +1,24 @@
-/*     tty_subr.c      3.3     %H%     */
+/*     tty_subr.c      6.1     83/07/29        */
 
 #include "../h/param.h"
 
 #include "../h/param.h"
-#include "../h/tty.h"
 #include "../h/systm.h"
 #include "../h/conf.h"
 #include "../h/buf.h"
 #include "../h/systm.h"
 #include "../h/conf.h"
 #include "../h/buf.h"
+#include "../h/tty.h"
+#include "../h/clist.h"
 
 
-struct cblock {
-       struct cblock *c_next;
-       char    c_info[CBSIZE];
-};
-
-struct cblock  cfree[NCLIST];
-int    cbad;
-struct cblock  *cfreelist;
+char   cwaiting;
 
 /*
  * Character list get/put
  */
 getc(p)
 
 /*
  * Character list get/put
  */
 getc(p)
-register struct clist *p;
+       register struct clist *p;
 {
        register struct cblock *bp;
        register int c, s;
 
 {
        register struct cblock *bp;
        register int c, s;
 
-       s = spl6();
+       s = spl5();
        if (p->c_cc <= 0) {
                c = -1;
                p->c_cc = 0;
        if (p->c_cc <= 0) {
                c = -1;
                p->c_cc = 0;
@@ -38,25 +32,36 @@ register struct clist *p;
                        p->c_cl = NULL;
                        bp->c_next = cfreelist;
                        cfreelist = bp;
                        p->c_cl = NULL;
                        bp->c_next = cfreelist;
                        cfreelist = bp;
+                       cfreecount += CBSIZE;
+                       if (cwaiting) {
+                               wakeup(&cwaiting);
+                               cwaiting = 0;
+                       }
                } else if (((int)p->c_cf & CROUND) == 0){
                        bp = (struct cblock *)(p->c_cf);
                        bp--;
                        p->c_cf = bp->c_next->c_info;
                        bp->c_next = cfreelist;
                        cfreelist = bp;
                } else if (((int)p->c_cf & CROUND) == 0){
                        bp = (struct cblock *)(p->c_cf);
                        bp--;
                        p->c_cf = bp->c_next->c_info;
                        bp->c_next = cfreelist;
                        cfreelist = bp;
+                       cfreecount += CBSIZE;
+                       if (cwaiting) {
+                               wakeup(&cwaiting);
+                               cwaiting = 0;
+                       }
                }
        }
        splx(s);
        return(c);
 }
 
                }
        }
        splx(s);
        return(c);
 }
 
+#ifdef notdef
 /*
  * copy clist to buffer.
  * return number of bytes moved.
  */
 q_to_b(q, cp, cc)
 /*
  * copy clist to buffer.
  * return number of bytes moved.
  */
 q_to_b(q, cp, cc)
-register struct clist *q;
-register char *cp;
+       register struct clist *q;
+       register char *cp;
 {
        register struct cblock *bp;
        register int s;
 {
        register struct cblock *bp;
        register int s;
@@ -64,10 +69,11 @@ register char *cp;
 
        if (cc <= 0)
                return(0);
 
        if (cc <= 0)
                return(0);
-       s = spl6();
+       s = spl5();
        if (q->c_cc <= 0) {
                q->c_cc = 0;
                q->c_cf = q->c_cl = NULL;
        if (q->c_cc <= 0) {
                q->c_cc = 0;
                q->c_cf = q->c_cl = NULL;
+               splx(s);
                return(0);
        }
        acp = cp;
                return(0);
        }
        acp = cp;
@@ -81,6 +87,11 @@ register char *cp;
                        q->c_cf = q->c_cl = NULL;
                        bp->c_next = cfreelist;
                        cfreelist = bp;
                        q->c_cf = q->c_cl = NULL;
                        bp->c_next = cfreelist;
                        cfreelist = bp;
+                       cfreecount += CBSIZE;
+                       if (cwaiting) {
+                               wakeup(&cwaiting);
+                               cwaiting = 0;
+                       }
                        break;
                }
                if (((int)q->c_cf & CROUND) == 0) {
                        break;
                }
                if (((int)q->c_cf & CROUND) == 0) {
@@ -89,11 +100,17 @@ register char *cp;
                        q->c_cf = bp->c_next->c_info;
                        bp->c_next = cfreelist;
                        cfreelist = bp;
                        q->c_cf = bp->c_next->c_info;
                        bp->c_next = cfreelist;
                        cfreelist = bp;
+                       cfreecount += CBSIZE;
+                       if (cwaiting) {
+                               wakeup(&cwaiting);
+                               cwaiting = 0;
+                       }
                }
        }
        splx(s);
        return(cp-acp);
 }
                }
        }
        splx(s);
        return(cp-acp);
 }
+#endif
 
 /*
  * Return count of contiguous characters
 
 /*
  * Return count of contiguous characters
@@ -101,12 +118,12 @@ register char *cp;
  * Stop counting if flag&character is non-null.
  */
 ndqb(q, flag)
  * Stop counting if flag&character is non-null.
  */
 ndqb(q, flag)
-register struct clist *q;
+       register struct clist *q;
 {
 {
-register cc;
-int s;
+       register cc;
+       int s;
 
 
-       s = spl6();
+       s = spl5();
        if (q->c_cc <= 0) {
                cc = -q->c_cc;
                goto out;
        if (q->c_cc <= 0) {
                cc = -q->c_cc;
                goto out;
@@ -123,7 +140,8 @@ int s;
                end += cc;
                while (p < end) {
                        if (*p & flag) {
                end += cc;
                while (p < end) {
                        if (*p & flag) {
-                               cc = (int)p - (int)q->c_cf;
+                               cc = (int)p;
+                               cc -= (int)q->c_cf;
                                break;
                        }
                        p++;
                                break;
                        }
                        p++;
@@ -134,78 +152,81 @@ out:
        return(cc);
 }
 
        return(cc);
 }
 
+
+
 /*
 /*
- * Update clist to show that cc characters
- * were removed.  It is assumed that cc < CBSIZE.
+ * Flush cc bytes from q.
  */
 ndflush(q, cc)
  */
 ndflush(q, cc)
-register struct clist *q;
-register cc;
+       register struct clist *q;
+       register cc;
 {
 {
-register s;
-
-       if (cc == 0)
-               return;
-       s = spl6();
-       if (q->c_cc < 0) {
-               if (q->c_cf != NULL) {
-                       q->c_cc += cc;
-                       q->c_cf += cc;
-                       goto out;
-               }
-               q->c_cc = 0;
-               goto out;
-       }
-       if (q->c_cc == 0) {
-               goto out;
-       }
-       if (cc > CBSIZE || cc <= 0) {
-               cbad++;
+       register struct cblock *bp;
+       char *end;
+       int rem, s;
+
+       s = spl5();
+       if (q->c_cc <= 0) {
                goto out;
        }
                goto out;
        }
-       q->c_cc -= cc;
-       q->c_cf += cc;
-       if (((int)q->c_cf & CROUND) == 0) {
-               register struct cblock *bp;
-
-               bp = (struct cblock *)(q->c_cf) -1;
-               if (bp->c_next) {
+       while (cc>0 && q->c_cc) {
+               bp = (struct cblock *)((int)q->c_cf & ~CROUND);
+               if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) {
+                       end = q->c_cl;
+               } else {
+                       end = (char *)((int)bp + sizeof (struct cblock));
+               }
+               rem = end - q->c_cf;
+               if (cc >= rem) {
+                       cc -= rem;
+                       q->c_cc -= rem;
                        q->c_cf = bp->c_next->c_info;
                        q->c_cf = bp->c_next->c_info;
+                       bp->c_next = cfreelist;
+                       cfreelist = bp;
+                       cfreecount += CBSIZE;
+                       if (cwaiting) {
+                               wakeup(&cwaiting);
+                               cwaiting = 0;
+                       }
                } else {
                } else {
-                       q->c_cf = q->c_cl = NULL;
+                       q->c_cc -= cc;
+                       q->c_cf += cc;
+                       if (q->c_cc <= 0) {
+                               bp->c_next = cfreelist;
+                               cfreelist = bp;
+                               cfreecount += CBSIZE;
+                               if (cwaiting) {
+                                       wakeup(&cwaiting);
+                                       cwaiting = 0;
+                               }
+                       }
+                       break;
                }
                }
-               bp->c_next = cfreelist;
-               cfreelist = bp;
-       } else
-       if (q->c_cc == 0) {
-               register struct cblock *bp;
-               q->c_cf = (char *)((int)q->c_cf & ~CROUND);
-               bp = (struct cblock *)(q->c_cf);
-               bp->c_next = cfreelist;
-               cfreelist = bp;
+       }
+       if (q->c_cc <= 0) {
                q->c_cf = q->c_cl = NULL;
                q->c_cf = q->c_cl = NULL;
+               q->c_cc = 0;
        }
 out:
        splx(s);
 }
 
        }
 out:
        splx(s);
 }
 
-/*
- * Put character c in queue p.
- */
+
 putc(c, p)
 putc(c, p)
-register struct clist *p;
+       register struct clist *p;
 {
        register struct cblock *bp;
        register char *cp;
        register s;
 
 {
        register struct cblock *bp;
        register char *cp;
        register s;
 
-       s = spl6();
+       s = spl5();
        if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
                if ((bp = cfreelist) == NULL) {
                        splx(s);
                        return(-1);
                }
                cfreelist = bp->c_next;
        if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) {
                if ((bp = cfreelist) == NULL) {
                        splx(s);
                        return(-1);
                }
                cfreelist = bp->c_next;
+               cfreecount -= CBSIZE;
                bp->c_next = NULL;
                p->c_cf = cp = bp->c_info;
        } else if (((int)cp & CROUND) == 0) {
                bp->c_next = NULL;
                p->c_cf = cp = bp->c_info;
        } else if (((int)cp & CROUND) == 0) {
@@ -216,6 +237,7 @@ register struct clist *p;
                }
                bp = bp->c_next;
                cfreelist = bp->c_next;
                }
                bp = bp->c_next;
                cfreelist = bp->c_next;
+               cfreecount -= CBSIZE;
                bp->c_next = NULL;
                cp = bp->c_info;
        }
                bp->c_next = NULL;
                cp = bp->c_info;
        }
@@ -226,14 +248,16 @@ register struct clist *p;
        return(0);
 }
 
        return(0);
 }
 
+
+
 /*
  * copy buffer to clist.
  * return number of bytes not transfered.
  */
 b_to_q(cp, cc, q)
 /*
  * copy buffer to clist.
  * return number of bytes not transfered.
  */
 b_to_q(cp, cc, q)
-register char *cp;
-struct clist *q;
-register int cc;
+       register char *cp;
+       struct clist *q;
+       register int cc;
 {
        register char *cq;
        register struct cblock *bp;
 {
        register char *cq;
        register struct cblock *bp;
@@ -242,11 +266,14 @@ register int cc;
        if (cc <= 0)
                return(0);
        acc = cc;
        if (cc <= 0)
                return(0);
        acc = cc;
-       s = spl6();
+
+
+       s = spl5();
        if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
                if ((bp = cfreelist) == NULL) 
                        goto out;
                cfreelist = bp->c_next;
        if ((cq = q->c_cl) == NULL || q->c_cc < 0) {
                if ((bp = cfreelist) == NULL) 
                        goto out;
                cfreelist = bp->c_next;
+               cfreecount -= CBSIZE;
                bp->c_next = NULL;
                q->c_cf = cq = bp->c_info;
        }
                bp->c_next = NULL;
                q->c_cf = cq = bp->c_info;
        }
@@ -258,6 +285,7 @@ register int cc;
                                goto out;
                        bp = bp->c_next;
                        cfreelist = bp->c_next;
                                goto out;
                        bp = bp->c_next;
                        cfreelist = bp->c_next;
+                       cfreecount -= CBSIZE;
                        bp->c_next = NULL;
                        cq = bp->c_info;
                }
                        bp->c_next = NULL;
                        cq = bp->c_info;
                }
@@ -281,8 +309,8 @@ out:
  */
 char *
 nextc(p, cp)
  */
 char *
 nextc(p, cp)
-register struct clist *p;
-register char *cp;
+       register struct clist *p;
+       register char *cp;
 {
 
        if (p->c_cc && ++cp != p->c_cl) {
 {
 
        if (p->c_cc && ++cp != p->c_cl) {
@@ -297,13 +325,13 @@ register char *cp;
  * Remove the last character in the list and return it.
  */
 unputc(p)
  * Remove the last character in the list and return it.
  */
 unputc(p)
-register struct clist *p;
+       register struct clist *p;
 {
        register struct cblock *bp;
        register int c, s;
        struct cblock *obp;
 
 {
        register struct cblock *bp;
        register int c, s;
        struct cblock *obp;
 
-       s = spl6();
+       s = spl5();
        if (p->c_cc <= 0)
                c = -1;
        else {
        if (p->c_cc <= 0)
                c = -1;
        else {
@@ -314,6 +342,7 @@ register struct clist *p;
                        p->c_cl = p->c_cf = NULL;
                        bp->c_next = cfreelist;
                        cfreelist = bp;
                        p->c_cl = p->c_cf = NULL;
                        bp->c_next = cfreelist;
                        cfreelist = bp;
+                       cfreecount += CBSIZE;
                } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) {
                        p->c_cl = (char *)((int)p->c_cl & ~CROUND);
                        bp = (struct cblock *)p->c_cf;
                } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) {
                        p->c_cl = (char *)((int)p->c_cl & ~CROUND);
                        bp = (struct cblock *)p->c_cf;
@@ -325,6 +354,7 @@ register struct clist *p;
                        bp = bp->c_next;
                        bp->c_next = cfreelist;
                        cfreelist = bp;
                        bp = bp->c_next;
                        bp->c_next = cfreelist;
                        cfreelist = bp;
+                       cfreecount += CBSIZE;
                        obp->c_next = NULL;
                }
        }
                        obp->c_next = NULL;
                }
        }
@@ -339,7 +369,7 @@ register struct clist *p;
  * SHOULD JUST USE q_to_b AND THEN b_to_q HERE.
  */
 catq(from, to)
  * SHOULD JUST USE q_to_b AND THEN b_to_q HERE.
  */
 catq(from, to)
-struct clist *from, *to;
+       struct clist *from, *to;
 {
        register c;
 
 {
        register c;
 
@@ -348,56 +378,46 @@ struct clist *from, *to;
 }
 
 /*
 }
 
 /*
- * Initialize clist by freeing all character blocks, then count
- * number of character devices. (Once-only routine)
- */
-cinit()
-{
-       register int ccp;
-       register struct cblock *cp;
-       register struct cdevsw *cdp;
-
-       ccp = (int)cfree;
-       ccp = (ccp+CROUND) & ~CROUND;
-       for(cp=(struct cblock *)ccp; cp <= &cfree[NCLIST-1]; cp++) {
-               cp->c_next = cfreelist;
-               cfreelist = cp;
-       }
-       ccp = 0;
-       for(cdp = cdevsw; cdp->d_open; cdp++)
-               ccp++;
-       nchrdev = ccp;
-}
-
-/*
- * integer (2-byte) get/put
+ * Integer (short) get/put
  * using clists
  */
  * using clists
  */
-/*
+typedef        short word_t;
+union chword {
+       word_t  word;
+       struct {
+               char    Ch[sizeof (word_t)];
+       } Cha;
+#define        ch      Cha.Ch
+};
+
 getw(p)
 getw(p)
-register struct clist *p;
+       register struct clist *p;
 {
 {
-       register int s;
+       register int i;
+       union chword x;
 
 
-       if (p->c_cc <= 1)
-               return(-1);
-       s = getc(p);
-       return(s | (getc(p)<<8));
+       if (p->c_cc < sizeof (word_t))
+               return (-1);
+       for (i = 0; i < sizeof (word_t); i++)
+               x.ch[i] = getc(p);
+       return (x.word);
 }
 }
-*/
 
 putw(c, p)
 
 putw(c, p)
-register struct clist *p;
+       register struct clist *p;
 {
        register s;
 {
        register s;
+       register int i;
+       union chword x;
 
 
-       s = spl6();
+       s = spl5();
        if (cfreelist==NULL) {
                splx(s);
                return(-1);
        }
        if (cfreelist==NULL) {
                splx(s);
                return(-1);
        }
-       (void) putc(c, p);
-       (void) putc(c>>8, p);
+       x.word = c;
+       for (i = 0; i < sizeof (word_t); i++)
+               (void) putc(x.ch[i], p);
        splx(s);
        splx(s);
-       return(0);
+       return (0);
 }
 }