summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>1994-11-26 19:24:13 +0000
committerbde <bde@FreeBSD.org>1994-11-26 19:24:13 +0000
commit33d82aa474e4140ae777bf35955374cbd36f678b (patch)
tree43b4d6b52d4e04328bc6d2c4e22788a3bae0c2b9 /sys
parentc879ab57fdf04799367f95d66a66ccbbd32c1d08 (diff)
downloadFreeBSD-src-33d82aa474e4140ae777bf35955374cbd36f678b.zip
FreeBSD-src-33d82aa474e4140ae777bf35955374cbd36f678b.tar.gz
Fix cblock starvation bugs by reserving enough cblocks for minimal
operation of each clist. Limit the growth of each clist. Clists can only grow larger than the reserved minimum if there are free cblocks in a shared pool. The size of this pool is now fixed (this could be improved). The reserved and maximum sizes are more carefully allocated for slip and ppp, depending on the mtu. A maximum MTU of 16384 is now enforced for ppp.
Diffstat (limited to 'sys')
-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