summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/subr_clist.c191
-rw-r--r--sys/kern/tty.c43
-rw-r--r--sys/kern/tty_subr.c191
-rw-r--r--sys/net/if_ppp.c22
-rw-r--r--sys/net/if_sl.c41
-rw-r--r--sys/sys/tty.h15
6 files changed, 339 insertions, 164 deletions
diff --git a/sys/kern/subr_clist.c b/sys/kern/subr_clist.c
index 46a8f1e..a261533 100644
--- a/sys/kern/subr_clist.c
+++ b/sys/kern/subr_clist.c
@@ -6,7 +6,7 @@
* of this software, nor does the author assume any responsibility
* for damages incurred with its use.
*
- * $Id: tty_subr.c,v 1.7 1994/09/25 19:33:50 phk Exp $
+ * $Id: tty_subr.c,v 1.8 1994/10/30 19:43:49 bde Exp $
*/
/*
@@ -22,17 +22,25 @@
struct cblock *cfreelist = 0;
int cfreecount = 0;
+static int cslushcount;
+static int ctotcount;
#ifndef INITIAL_CBLOCKS
-#define INITIAL_CBLOCKS 50
+#define INITIAL_CBLOCKS 50
#endif
-#define MBUF_DIAG
-#ifdef MBUF_DIAG
-void
-print_nblocks()
+static void cblock_alloc_cblocks __P((int number));
+static void cblock_free_cblocks __P((int number));
+
+#define CBLOCK_DIAG
+#ifdef CBLOCK_DIAG
+static void
+cbstat()
{
- printf("There are currently %d bytes in cblocks\n", cfreecount);
+ printf(
+ "tot = %d (active = %d, free = %d (reserved = %d, slush = %d))\n",
+ ctotcount * CBSIZE, ctotcount * CBSIZE - cfreecount, cfreecount,
+ cfreecount - cslushcount * CBSIZE, cslushcount * CBSIZE);
}
#endif
@@ -44,10 +52,13 @@ clist_init()
{
/*
* Allocate an initial base set of cblocks as a 'slush'.
- * We allocate more with each ttyopen().
+ * We allocate non-slush cblocks with each initial ttyopen() and
+ * deallocate them with each ttyclose().
+ * We should adjust the slush allocation. This can't be done in
+ * the i/o routines because they are sometimes called from
+ * interrupt handlers when it may be unsafe to call malloc().
*/
- cblock_alloc_cblocks(INITIAL_CBLOCKS);
- return;
+ cblock_alloc_cblocks(cslushcount = INITIAL_CBLOCKS);
}
/*
@@ -60,10 +71,8 @@ cblock_alloc()
struct cblock *cblockp;
cblockp = cfreelist;
- if (!cblockp) {
- /* XXX should syslog a message that we're out! */
- return (0);
- }
+ if (cblockp == NULL)
+ panic("clist reservation botch");
cfreelist = cblockp->c_next;
cblockp->c_next = NULL;
cfreecount -= CBSIZE;
@@ -80,13 +89,12 @@ cblock_free(cblockp)
cblockp->c_next = cfreelist;
cfreelist = cblockp;
cfreecount += CBSIZE;
- return;
}
/*
* Allocate some cblocks for the cfreelist queue.
*/
-void
+static void
cblock_alloc_cblocks(number)
int number;
{
@@ -94,36 +102,66 @@ cblock_alloc_cblocks(number)
struct cblock *tmp;
for (i = 0; i < number; ++i) {
- tmp = malloc(sizeof(struct cblock), M_TTYS, M_NOWAIT);
- if (!tmp) {
- printf("cblock_alloc_cblocks: could not malloc cblock");
- break;
- }
+ tmp = malloc(sizeof(struct cblock), M_TTYS, M_WAITOK);
bzero((char *)tmp, sizeof(struct cblock));
cblock_free(tmp);
}
- return;
+ ctotcount += number;
+}
+
+/*
+ * Set the cblock allocation policy for a a clist.
+ * Must be called at spltty().
+ */
+void
+clist_alloc_cblocks(clistp, ccmax, ccreserved)
+ struct clist *clistp;
+ int ccmax;
+ int ccreserved;
+{
+ int dcbr;
+
+ clistp->c_cbmax = roundup(ccmax, CBSIZE) / CBSIZE;
+ dcbr = roundup(ccreserved, CBSIZE) / CBSIZE - clistp->c_cbreserved;
+ if (dcbr >= 0)
+ cblock_alloc_cblocks(dcbr);
+ else {
+ if (clistp->c_cbreserved + dcbr < clistp->c_cbcount)
+ dcbr = clistp->c_cbcount - clistp->c_cbreserved;
+ cblock_free_cblocks(-dcbr);
+ }
+ clistp->c_cbreserved += dcbr;
}
/*
* Free some cblocks from the cfreelist queue back to the
* system malloc pool.
*/
-void
+static void
cblock_free_cblocks(number)
int number;
{
int i;
- struct cblock *tmp;
- for (i = 0; i < number; ++i) {
- tmp = cblock_alloc();
- if (tmp == NULL)
- return;
- free(tmp, M_TTYS);
- }
+ for (i = 0; i < number; ++i)
+ free(cblock_alloc(), M_TTYS);
+ ctotcount -= number;
}
+/*
+ * Free the cblocks reserved for a clist.
+ * Must be called at spltty().
+ */
+void
+clist_free_cblocks(clistp)
+ struct clist *clistp;
+{
+ if (clistp->c_cbcount != 0)
+ panic("freeing active clist cblocks");
+ cblock_free_cblocks(clistp->c_cbreserved);
+ clistp->c_cbmax = 0;
+ clistp->c_cbreserved = 0;
+}
/*
* Get a character from the head of a clist.
@@ -168,6 +206,8 @@ getc(clistp)
clistp->c_cf = clistp->c_cl = NULL;
}
cblock_free(cblockp);
+ if (--clistp->c_cbcount >= clistp->c_cbreserved)
+ ++cslushcount;
}
}
@@ -217,6 +257,8 @@ q_to_b(clistp, dest, amount)
clistp->c_cf = clistp->c_cl = NULL;
}
cblock_free(cblockp);
+ if (--clistp->c_cbcount >= clistp->c_cbreserved)
+ ++cslushcount;
}
}
@@ -260,11 +302,12 @@ ndflush(clistp, amount)
clistp->c_cf = clistp->c_cl = NULL;
}
cblock_free(cblockp);
+ if (--clistp->c_cbcount >= clistp->c_cbreserved)
+ ++cslushcount;
}
}
splx(s);
- return;
}
/*
@@ -281,28 +324,30 @@ putc(chr, clistp)
s = spltty();
- cblockp = (struct cblock *)((long)clistp->c_cl & ~CROUND);
-
if (clistp->c_cl == NULL) {
+ if (clistp->c_cbreserved < 1)
+ panic("putc to a clist with no reserved cblocks");
cblockp = cblock_alloc();
- if (cblockp) {
- clistp->c_cf = clistp->c_cl = cblockp->c_info;
- clistp->c_cc = 0;
- } else {
- splx(s);
- return (-1);
- }
+ clistp->c_cbcount = 1;
+ clistp->c_cf = clistp->c_cl = cblockp->c_info;
+ clistp->c_cc = 0;
} else {
+ cblockp = (struct cblock *)((long)clistp->c_cl & ~CROUND);
if (((long)clistp->c_cl & CROUND) == 0) {
struct cblock *prev = (cblockp - 1);
- cblockp = cblock_alloc();
- if (cblockp) {
- prev->c_next = cblockp;
- clistp->c_cl = cblockp->c_info;
- } else {
- splx(s);
- return (-1);
+
+ if (clistp->c_cbcount >= clistp->c_cbreserved) {
+ if (clistp->c_cbcount >= clistp->c_cbmax
+ || cslushcount <= 0) {
+ splx(s);
+ return (-1);
+ }
+ --cslushcount;
}
+ cblockp = cblock_alloc();
+ clistp->c_cbcount++;
+ prev->c_next = cblockp;
+ clistp->c_cl = cblockp->c_info;
}
}
@@ -337,6 +382,13 @@ b_to_q(src, amount, clistp)
int startbit, endbit, num_between, numc;
int s;
+ /*
+ * Avoid allocating an initial cblock and then not using it.
+ * c_cc == 0 must imply c_cbount == 0.
+ */
+ if (amount <= 0)
+ return (amount);
+
s = spltty();
/*
@@ -344,14 +396,12 @@ b_to_q(src, amount, clistp)
* then get one.
*/
if (clistp->c_cl == NULL) {
+ if (clistp->c_cbreserved < 1)
+ panic("b_to_q to a clist with no reserved cblocks");
cblockp = cblock_alloc();
- if (cblockp) {
- clistp->c_cf = clistp->c_cl = cblockp->c_info;
- clistp->c_cc = 0;
- } else {
- splx(s);
- return (amount);
- }
+ clistp->c_cbcount = 1;
+ clistp->c_cf = clistp->c_cl = cblockp->c_info;
+ clistp->c_cc = 0;
} else {
cblockp = (struct cblock *)((long)clistp->c_cl & ~CROUND);
}
@@ -362,14 +412,19 @@ b_to_q(src, amount, clistp)
*/
if (((long)clistp->c_cl & CROUND) == 0) {
struct cblock *prev = cblockp - 1;
- cblockp = cblock_alloc();
- if (cblockp) {
- prev->c_next = cblockp;
- clistp->c_cl = cblockp->c_info;
- } else {
- splx(s);
- return (amount);
+
+ if (clistp->c_cbcount >= clistp->c_cbreserved) {
+ if (clistp->c_cbcount >= clistp->c_cbmax
+ || cslushcount <= 0) {
+ splx(s);
+ return (amount);
+ }
+ --cslushcount;
}
+ cblockp = cblock_alloc();
+ clistp->c_cbcount++;
+ prev->c_next = cblockp;
+ clistp->c_cl = cblockp->c_info;
}
/*
@@ -515,6 +570,8 @@ unputc(clistp)
*/
clistp->c_cl = (char *)(cbp+1);
cblock_free(cblockp);
+ if (--clistp->c_cbcount >= clistp->c_cbreserved)
+ ++cslushcount;
cbp->c_next = NULL;
}
}
@@ -526,6 +583,8 @@ unputc(clistp)
if ((clistp->c_cc == 0) && clistp->c_cl) {
cblockp = (struct cblock *)((long)clistp->c_cl & ~CROUND);
cblock_free(cblockp);
+ if (--clistp->c_cbcount >= clistp->c_cbreserved)
+ ++cslushcount;
clistp->c_cf = clistp->c_cl = NULL;
}
@@ -546,19 +605,25 @@ catq(src_clistp, dest_clistp)
s = spltty();
/*
* If the destination clist is empty (has no cblocks atttached),
+ * and there are no possible complications with the resource counters,
* then we simply assign the current clist to the destination.
*/
- if (!dest_clistp->c_cf) {
+ if (!dest_clistp->c_cf
+ && src_clistp->c_cbcount <= src_clistp->c_cbmax
+ && src_clistp->c_cbcount <= dest_clistp->c_cbmax) {
dest_clistp->c_cf = src_clistp->c_cf;
dest_clistp->c_cl = src_clistp->c_cl;
src_clistp->c_cf = src_clistp->c_cl = NULL;
dest_clistp->c_cc = src_clistp->c_cc;
src_clistp->c_cc = 0;
+ dest_clistp->c_cbcount = src_clistp->c_cbcount;
+ src_clistp->c_cbcount = 0;
splx(s);
return;
}
+
splx(s);
/*
@@ -567,6 +632,4 @@ catq(src_clistp, dest_clistp)
*/
while ((chr = getc(src_clistp)) != -1)
putc(chr, dest_clistp);
-
- return;
}
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index dca12f9..d15110f 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)tty.c 8.8 (Berkeley) 1/21/94
- * $Id: tty.c,v 1.13 1994/11/01 22:23:29 bde Exp $
+ * $Id: tty.c,v 1.14 1994/11/26 18:54:25 bde Exp $
*/
#include <sys/param.h>
@@ -72,10 +72,6 @@ char ttybuf[] = "ttybuf";
char ttyin[] = "ttyin";
char ttyout[] = "ttyout";
-#ifndef CBLOCKS_PER_TTY
-#define CBLOCKS_PER_TTY 10
-#endif
-
/*
* Table with character classes and parity. The 8th bit indicates parity,
* the 7th bit indicates the character is an alphameric or underscore (for
@@ -169,12 +165,17 @@ ttyopen(device, tp)
if (!ISSET(tp->t_state, TS_ISOPEN)) {
SET(tp->t_state, TS_ISOPEN);
bzero(&tp->t_winsize, sizeof(tp->t_winsize));
- /*
- * Add some cblocks to the clistfree pool.
- */
- cblock_alloc_cblocks(CBLOCKS_PER_TTY);
}
CLR(tp->t_state, TS_WOPEN);
+
+ /*
+ * Initialize or restore a cblock allocation policy suitable for
+ * the standard line discipline.
+ */
+ clist_alloc_cblocks(&tp->t_canq, TTYHOG, 512);
+ clist_alloc_cblocks(&tp->t_outq, TTMAXHIWAT + 200, 512);
+ clist_alloc_cblocks(&tp->t_rawq, TTYHOG, 512);
+
splx(s);
return (0);
}
@@ -189,23 +190,22 @@ ttyclose(tp)
register struct tty *tp;
{
extern struct tty *constty; /* Temporary virtual console. */
+ int s;
+ s = spltty();
if (constty == tp)
constty = NULL;
ttyflush(tp, FREAD | FWRITE);
+ clist_free_cblocks(&tp->t_canq);
+ clist_free_cblocks(&tp->t_outq);
+ clist_free_cblocks(&tp->t_rawq);
tp->t_gen++;
tp->t_pgrp = NULL;
tp->t_session = NULL;
- /*
- * If the tty has not already been closed, free the cblocks
- * that were allocated in ttyopen() back to the system malloc
- * pool.
- */
- if (ISSET(tp->t_state, (TS_ISOPEN|TS_WOPEN)))
- cblock_free_cblocks(CBLOCKS_PER_TTY);
tp->t_state = 0;
+ splx(s);
return (0);
}
@@ -1209,9 +1209,16 @@ ttypend(tp)
CLR(tp->t_lflag, PENDIN);
SET(tp->t_state, TS_TYPEN);
+ /*
+ * XXX this assumes too much about clist internals. It may even
+ * fail if the cblock slush pool is empty. We can't allocate more
+ * cblocks here because we are called from an interrupt handler
+ * and clist_alloc_cblocks() can wait.
+ */
tq = tp->t_rawq;
- tp->t_rawq.c_cc = 0;
- tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
+ bzero(&tp->t_rawq, sizeof tp->t_rawq);
+ tp->t_rawq.c_cbmax = tq.c_cbmax;
+ tp->t_rawq.c_cbreserved = tq.c_cbreserved;
while ((c = getc(&tq)) >= 0)
ttyinput(c, tp);
CLR(tp->t_state, TS_TYPEN);
diff --git a/sys/kern/tty_subr.c b/sys/kern/tty_subr.c
index 46a8f1e..a261533 100644
--- a/sys/kern/tty_subr.c
+++ b/sys/kern/tty_subr.c
@@ -6,7 +6,7 @@
* of this software, nor does the author assume any responsibility
* for damages incurred with its use.
*
- * $Id: tty_subr.c,v 1.7 1994/09/25 19:33:50 phk Exp $
+ * $Id: tty_subr.c,v 1.8 1994/10/30 19:43:49 bde Exp $
*/
/*
@@ -22,17 +22,25 @@
struct cblock *cfreelist = 0;
int cfreecount = 0;
+static int cslushcount;
+static int ctotcount;
#ifndef INITIAL_CBLOCKS
-#define INITIAL_CBLOCKS 50
+#define INITIAL_CBLOCKS 50
#endif
-#define MBUF_DIAG
-#ifdef MBUF_DIAG
-void
-print_nblocks()
+static void cblock_alloc_cblocks __P((int number));
+static void cblock_free_cblocks __P((int number));
+
+#define CBLOCK_DIAG
+#ifdef CBLOCK_DIAG
+static void
+cbstat()
{
- printf("There are currently %d bytes in cblocks\n", cfreecount);
+ printf(
+ "tot = %d (active = %d, free = %d (reserved = %d, slush = %d))\n",
+ ctotcount * CBSIZE, ctotcount * CBSIZE - cfreecount, cfreecount,
+ cfreecount - cslushcount * CBSIZE, cslushcount * CBSIZE);
}
#endif
@@ -44,10 +52,13 @@ clist_init()
{
/*
* Allocate an initial base set of cblocks as a 'slush'.
- * We allocate more with each ttyopen().
+ * We allocate non-slush cblocks with each initial ttyopen() and
+ * deallocate them with each ttyclose().
+ * We should adjust the slush allocation. This can't be done in
+ * the i/o routines because they are sometimes called from
+ * interrupt handlers when it may be unsafe to call malloc().
*/
- cblock_alloc_cblocks(INITIAL_CBLOCKS);
- return;
+ cblock_alloc_cblocks(cslushcount = INITIAL_CBLOCKS);
}
/*
@@ -60,10 +71,8 @@ cblock_alloc()
struct cblock *cblockp;
cblockp = cfreelist;
- if (!cblockp) {
- /* XXX should syslog a message that we're out! */
- return (0);
- }
+ if (cblockp == NULL)
+ panic("clist reservation botch");
cfreelist = cblockp->c_next;
cblockp->c_next = NULL;
cfreecount -= CBSIZE;
@@ -80,13 +89,12 @@ cblock_free(cblockp)
cblockp->c_next = cfreelist;
cfreelist = cblockp;
cfreecount += CBSIZE;
- return;
}
/*
* Allocate some cblocks for the cfreelist queue.
*/
-void
+static void
cblock_alloc_cblocks(number)
int number;
{
@@ -94,36 +102,66 @@ cblock_alloc_cblocks(number)
struct cblock *tmp;
for (i = 0; i < number; ++i) {
- tmp = malloc(sizeof(struct cblock), M_TTYS, M_NOWAIT);
- if (!tmp) {
- printf("cblock_alloc_cblocks: could not malloc cblock");
- break;
- }
+ tmp = malloc(sizeof(struct cblock), M_TTYS, M_WAITOK);
bzero((char *)tmp, sizeof(struct cblock));
cblock_free(tmp);
}
- return;
+ ctotcount += number;
+}
+
+/*
+ * Set the cblock allocation policy for a a clist.
+ * Must be called at spltty().
+ */
+void
+clist_alloc_cblocks(clistp, ccmax, ccreserved)
+ struct clist *clistp;
+ int ccmax;
+ int ccreserved;
+{
+ int dcbr;
+
+ clistp->c_cbmax = roundup(ccmax, CBSIZE) / CBSIZE;
+ dcbr = roundup(ccreserved, CBSIZE) / CBSIZE - clistp->c_cbreserved;
+ if (dcbr >= 0)
+ cblock_alloc_cblocks(dcbr);
+ else {
+ if (clistp->c_cbreserved + dcbr < clistp->c_cbcount)
+ dcbr = clistp->c_cbcount - clistp->c_cbreserved;
+ cblock_free_cblocks(-dcbr);
+ }
+ clistp->c_cbreserved += dcbr;
}
/*
* Free some cblocks from the cfreelist queue back to the
* system malloc pool.
*/
-void
+static void
cblock_free_cblocks(number)
int number;
{
int i;
- struct cblock *tmp;
- for (i = 0; i < number; ++i) {
- tmp = cblock_alloc();
- if (tmp == NULL)
- return;
- free(tmp, M_TTYS);
- }
+ for (i = 0; i < number; ++i)
+ free(cblock_alloc(), M_TTYS);
+ ctotcount -= number;
}
+/*
+ * Free the cblocks reserved for a clist.
+ * Must be called at spltty().
+ */
+void
+clist_free_cblocks(clistp)
+ struct clist *clistp;
+{
+ if (clistp->c_cbcount != 0)
+ panic("freeing active clist cblocks");
+ cblock_free_cblocks(clistp->c_cbreserved);
+ clistp->c_cbmax = 0;
+ clistp->c_cbreserved = 0;
+}
/*
* Get a character from the head of a clist.
@@ -168,6 +206,8 @@ getc(clistp)
clistp->c_cf = clistp->c_cl = NULL;
}
cblock_free(cblockp);
+ if (--clistp->c_cbcount >= clistp->c_cbreserved)
+ ++cslushcount;
}
}
@@ -217,6 +257,8 @@ q_to_b(clistp, dest, amount)
clistp->c_cf = clistp->c_cl = NULL;
}
cblock_free(cblockp);
+ if (--clistp->c_cbcount >= clistp->c_cbreserved)
+ ++cslushcount;
}
}
@@ -260,11 +302,12 @@ ndflush(clistp, amount)
clistp->c_cf = clistp->c_cl = NULL;
}
cblock_free(cblockp);
+ if (--clistp->c_cbcount >= clistp->c_cbreserved)
+ ++cslushcount;
}
}
splx(s);
- return;
}
/*
@@ -281,28 +324,30 @@ putc(chr, clistp)
s = spltty();
- cblockp = (struct cblock *)((long)clistp->c_cl & ~CROUND);
-
if (clistp->c_cl == NULL) {
+ if (clistp->c_cbreserved < 1)
+ panic("putc to a clist with no reserved cblocks");
cblockp = cblock_alloc();
- if (cblockp) {
- clistp->c_cf = clistp->c_cl = cblockp->c_info;
- clistp->c_cc = 0;
- } else {
- splx(s);
- return (-1);
- }
+ clistp->c_cbcount = 1;
+ clistp->c_cf = clistp->c_cl = cblockp->c_info;
+ clistp->c_cc = 0;
} else {
+ cblockp = (struct cblock *)((long)clistp->c_cl & ~CROUND);
if (((long)clistp->c_cl & CROUND) == 0) {
struct cblock *prev = (cblockp - 1);
- cblockp = cblock_alloc();
- if (cblockp) {
- prev->c_next = cblockp;
- clistp->c_cl = cblockp->c_info;
- } else {
- splx(s);
- return (-1);
+
+ if (clistp->c_cbcount >= clistp->c_cbreserved) {
+ if (clistp->c_cbcount >= clistp->c_cbmax
+ || cslushcount <= 0) {
+ splx(s);
+ return (-1);
+ }
+ --cslushcount;
}
+ cblockp = cblock_alloc();
+ clistp->c_cbcount++;
+ prev->c_next = cblockp;
+ clistp->c_cl = cblockp->c_info;
}
}
@@ -337,6 +382,13 @@ b_to_q(src, amount, clistp)
int startbit, endbit, num_between, numc;
int s;
+ /*
+ * Avoid allocating an initial cblock and then not using it.
+ * c_cc == 0 must imply c_cbount == 0.
+ */
+ if (amount <= 0)
+ return (amount);
+
s = spltty();
/*
@@ -344,14 +396,12 @@ b_to_q(src, amount, clistp)
* then get one.
*/
if (clistp->c_cl == NULL) {
+ if (clistp->c_cbreserved < 1)
+ panic("b_to_q to a clist with no reserved cblocks");
cblockp = cblock_alloc();
- if (cblockp) {
- clistp->c_cf = clistp->c_cl = cblockp->c_info;
- clistp->c_cc = 0;
- } else {
- splx(s);
- return (amount);
- }
+ clistp->c_cbcount = 1;
+ clistp->c_cf = clistp->c_cl = cblockp->c_info;
+ clistp->c_cc = 0;
} else {
cblockp = (struct cblock *)((long)clistp->c_cl & ~CROUND);
}
@@ -362,14 +412,19 @@ b_to_q(src, amount, clistp)
*/
if (((long)clistp->c_cl & CROUND) == 0) {
struct cblock *prev = cblockp - 1;
- cblockp = cblock_alloc();
- if (cblockp) {
- prev->c_next = cblockp;
- clistp->c_cl = cblockp->c_info;
- } else {
- splx(s);
- return (amount);
+
+ if (clistp->c_cbcount >= clistp->c_cbreserved) {
+ if (clistp->c_cbcount >= clistp->c_cbmax
+ || cslushcount <= 0) {
+ splx(s);
+ return (amount);
+ }
+ --cslushcount;
}
+ cblockp = cblock_alloc();
+ clistp->c_cbcount++;
+ prev->c_next = cblockp;
+ clistp->c_cl = cblockp->c_info;
}
/*
@@ -515,6 +570,8 @@ unputc(clistp)
*/
clistp->c_cl = (char *)(cbp+1);
cblock_free(cblockp);
+ if (--clistp->c_cbcount >= clistp->c_cbreserved)
+ ++cslushcount;
cbp->c_next = NULL;
}
}
@@ -526,6 +583,8 @@ unputc(clistp)
if ((clistp->c_cc == 0) && clistp->c_cl) {
cblockp = (struct cblock *)((long)clistp->c_cl & ~CROUND);
cblock_free(cblockp);
+ if (--clistp->c_cbcount >= clistp->c_cbreserved)
+ ++cslushcount;
clistp->c_cf = clistp->c_cl = NULL;
}
@@ -546,19 +605,25 @@ catq(src_clistp, dest_clistp)
s = spltty();
/*
* If the destination clist is empty (has no cblocks atttached),
+ * and there are no possible complications with the resource counters,
* then we simply assign the current clist to the destination.
*/
- if (!dest_clistp->c_cf) {
+ if (!dest_clistp->c_cf
+ && src_clistp->c_cbcount <= src_clistp->c_cbmax
+ && src_clistp->c_cbcount <= dest_clistp->c_cbmax) {
dest_clistp->c_cf = src_clistp->c_cf;
dest_clistp->c_cl = src_clistp->c_cl;
src_clistp->c_cf = src_clistp->c_cl = NULL;
dest_clistp->c_cc = src_clistp->c_cc;
src_clistp->c_cc = 0;
+ dest_clistp->c_cbcount = src_clistp->c_cbcount;
+ src_clistp->c_cbcount = 0;
splx(s);
return;
}
+
splx(s);
/*
@@ -567,6 +632,4 @@ catq(src_clistp, dest_clistp)
*/
while ((chr = getc(src_clistp)) != -1)
putc(chr, dest_clistp);
-
- return;
}
diff --git a/sys/net/if_ppp.c b/sys/net/if_ppp.c
index fac8eca..826bcc6 100644
--- a/sys/net/if_ppp.c
+++ b/sys/net/if_ppp.c
@@ -69,7 +69,7 @@
* Paul Mackerras (paulus@cs.anu.edu.au).
*/
-/* $Id: if_ppp.c,v 1.6 1994/11/01 22:18:34 wollman Exp $ */
+/* $Id: if_ppp.c,v 1.7 1994/11/23 08:29:44 ugen Exp $ */
/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
#include "ppp.h"
@@ -127,6 +127,7 @@
#define CCOUNT(q) ((q)->c_cc)
#define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
+#define PPP_MAXMTU 16384 /* Largest MTU we allow */
struct ppp_softc ppp_softc[NPPP];
@@ -319,6 +320,15 @@ pppopen(dev, tp)
tp->t_sc = (caddr_t) sc;
ttyflush(tp, FREAD | FWRITE);
+ /*
+ * XXX we fudge t_canq to avoid providing pppselect() and FIONREAD.
+ * I hope one char is enough. The following actually gives CBSIZE
+ * chars.
+ */
+ clist_alloc_cblocks(&tp->t_canq, 1, 1);
+ clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
+ sc->sc_if.if_mtu + PPP_HIWAT);
+ clist_alloc_cblocks(&tp->t_rawq, 0, 0);
return (0);
}
@@ -339,6 +349,7 @@ pppclose(tp, flag)
ttywflush(tp);
s = splimp(); /* paranoid; splnet probably ok */
+ clist_free_cblocks(&tp->t_outq);
tp->t_line = 0;
sc = (struct ppp_softc *)tp->t_sc;
if (sc != NULL) {
@@ -1494,7 +1505,14 @@ pppioctl(ifp, cmd, data)
case SIOCSIFMTU:
if (error = suser(p->p_ucred, &p->p_acflag))
return (error);
- sc->sc_if.if_mtu = ifr->ifr_mtu;
+ if (ifr->ifr_mtu > PPP_MAXMTU)
+ error = EINVAL;
+ else {
+ sc->sc_if.if_mtu = ifr->ifr_mtu;
+ clist_alloc_cblocks(&((struct tty *) sc->sc_devp)->t_outq,
+ sc->sc_if.if_mtu + PPP_HIWAT,
+ sc->sc_if.if_mtu + PPP_HIWAT);
+ }
break;
case SIOCGIFMTU:
diff --git a/sys/net/if_sl.c b/sys/net/if_sl.c
index 61b2be2..915bc4b 100644
--- a/sys/net/if_sl.c
+++ b/sys/net/if_sl.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)if_sl.c 8.6 (Berkeley) 2/1/94
- * $Id: if_sl.c,v 1.8 1994/10/05 21:22:45 wollman Exp $
+ * $Id: if_sl.c,v 1.9 1994/10/08 01:40:22 phk Exp $
*/
/*
@@ -127,7 +127,8 @@ Huh? Slip without inet?
* role in interactive performance than the MTU. The MTU can be changed
* at any time to suit the specific environment with ifconfig(8), and
* its maximum value is defined as SLTMAX. SLTMAX must not be so large
- * that it would overflow the stack if BPF is configured.
+ * that it would overflow the stack if BPF is configured (XXX; if_ppp.c
+ * handles this better).
*
* SLIP_HIWAT is the amount of data that will be queued 'downstream'
* of us (i.e., in clists waiting to be picked up by the tty output
@@ -155,13 +156,10 @@ Huh? Slip without inet?
#ifndef SLMTU
#define SLMTU 552 /* default MTU */
#endif
-#define SLTMAX 1500 /* maximum MTU */
+#define SLTMAX 1500 /* maximum MTU */
#define SLIP_HIWAT roundup(50,CBSIZE)
#define CLISTRESERVE 1024 /* Can't let clists get too low */
-/* add this many cblocks to the pool */
-#define CLISTEXTRA ((SLRMAX+SLTMAX) / CBSIZE)
-
/*
* SLIP ABORT ESCAPE MECHANISM:
* (inspired by HAYES modem escape arrangement)
@@ -276,7 +274,21 @@ slopen(dev, tp)
sc->sc_if.if_baudrate = tp->t_ospeed;
ttyflush(tp, FREAD | FWRITE);
- cblock_alloc_cblocks(CLISTEXTRA);
+ /*
+ * We don't use t_canq or t_rawq, so reduce their
+ * cblock resources to 0. Reserve enough cblocks
+ * for t_outq to guarantee that we can fit a full
+ * packet if the SLIP_HIWAT check allows slstart()
+ * to loop. Use the same value for the cblock
+ * limit since the reserved blocks should always
+ * be enough. Reserving cblocks probably makes
+ * the CLISTRESERVE check unnecessary and wasteful.
+ */
+ clist_alloc_cblocks(&tp->t_canq, 0, 0);
+ clist_alloc_cblocks(&tp->t_outq,
+ sc->sc_if.if_mtu + SLIP_HIWAT,
+ sc->sc_if.if_mtu + SLIP_HIWAT);
+ clist_alloc_cblocks(&tp->t_rawq, 0, 0);
return (0);
}
@@ -296,7 +308,13 @@ slclose(tp,flag)
int s;
ttywflush(tp);
+ /*
+ * XXX the placement of the following spl is misleading. tty
+ * interrupts must be blocked across line discipline switches
+ * and throughout closes to avoid races.
+ */
s = splimp(); /* actually, max(spltty, splnet) */
+ clist_free_cblocks(&tp->t_outq);
tp->t_line = 0;
sc = (struct sl_softc *)tp->t_sc;
if (sc != NULL) {
@@ -307,7 +325,6 @@ slclose(tp,flag)
sc->sc_ep = 0;
sc->sc_mp = 0;
sc->sc_buf = 0;
- cblock_free_cblocks(CLISTEXTRA);
}
splx(s);
return 0;
@@ -863,10 +880,14 @@ slioctl(ifp, cmd, data)
/*
* Set the interface MTU.
*/
- if (ifr->ifr_mtu > SLTMAX) {
+ if (ifr->ifr_mtu > SLTMAX)
error = EINVAL;
- } else {
+ else {
ifp->if_mtu = ifr->ifr_mtu;
+ clist_alloc_cblocks(
+ &sl_softc[ifp->if_unit].sc_ttyp->t_outq,
+ ifp->if_mtu + SLIP_HIWAT,
+ ifp->if_mtu + SLIP_HIWAT);
}
break;
diff --git a/sys/sys/tty.h b/sys/sys/tty.h
index 5899625..275c7f9 100644
--- a/sys/sys/tty.h
+++ b/sys/sys/tty.h
@@ -36,11 +36,11 @@
* SUCH DAMAGE.
*
* @(#)tty.h 8.6 (Berkeley) 1/21/94
- * $Id: tty.h,v 1.5 1994/09/13 16:03:35 davidg Exp $
+ * $Id: tty.h,v 1.6 1994/10/02 17:25:02 phk Exp $
*/
#ifndef _SYS_TTY_H_
-#define _SYS_TTY_H_
+#define _SYS_TTY_H_
#include <sys/termios.h>
#include <sys/select.h> /* For struct selinfo. */
@@ -51,6 +51,9 @@
*/
struct clist {
int c_cc; /* Number of characters in the clist. */
+ int c_cbcount; /* Number of cblocks. */
+ int c_cbmax; /* Max # cblocks allowed for this clist. */
+ int c_cbreserved; /* # cblocks reserved for this clist. */
char *c_cf; /* Pointer to the first cblock. */
char *c_cl; /* Pointer to the last cblock. */
};
@@ -179,10 +182,10 @@ extern struct ttychars ttydefaults;
/* Symbolic sleep message strings. */
extern char ttyin[], ttyout[], ttopen[], ttclos[], ttybg[], ttybuf[];
-void cblock_alloc_cblocks __P((int));
-void cblock_free_cblocks __P((int));
int b_to_q __P((char *cp, int cc, struct clist *q));
void catq __P((struct clist *from, struct clist *to));
+void clist_alloc_cblocks __P((struct clist *q, int ccmax, int ccres));
+void clist_free_cblocks __P((struct clist *q));
/* void clist_init __P((void)); */ /* defined in systm.h for main() */
int getc __P((struct clist *q));
void ndflush __P((struct clist *q, int cc));
@@ -220,6 +223,6 @@ int ttysleep __P((struct tty *tp,
void *chan, int pri, char *wmesg, int timeout));
int ttywait __P((struct tty *tp));
int ttywflush __P((struct tty *tp));
-#endif
+#endif /* KERNEL */
-#endif
+#endif /* !_SYS_TTY_H_ */
OpenPOWER on IntegriCloud