Re: 2.0.30 serial.c, ppp.c and pppd-2.2 questions

Bill Hawes (whawes@star.net)
Mon, 21 Jul 1997 21:48:54 -0400


This is a multi-part message in MIME format.
--------------5893C146C8EE01ED60B46D6D
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Theodore Y. Ts'o wrote:
>
> Bill,
> Your analysis is a good one, and it may solve the problem ---
> however, your patch isn't quite sufficient, because if the flip buffer
> is disabled, it can't just return; it needs to requeue the tty flip
> buffer so that it can get processed on the next clock tick. Otherwise,
> you could get into a situation where if there aren't any more tty
> transmit interrupts, and the flip buffer never gets requeued.
>
> Fortunatelly it's safe to requeue a task queue from within the
> task queue handler, so it should be a matter of adding a
>
> queue_task(&tty->flip.tqueue, &tq_timer)

Good, thanks for checking that. I've added queue_task() to the patch,
with a goto to keep the code out of the flow path.

The serial.c code requeues the flip tqueue after each character, but if
we've already missed one tick it's best to get back in line right away.

In studying the bottom-half handlers this afternoon I came across
another potential problem -- it appears that run_task_queue
uncondtionally fires off all of the enqueued tasks. Seems like this
could be a problem if code is using disable_bh/enable_bh for exclusion
-- if another task invoked run_task_queue on that task list, it could
violate the exclusion. Is there something to guard against this?

Regards,
Bill
--------------5893C146C8EE01ED60B46D6D
Content-Type: text/plain; charset=us-ascii; name="flip_30-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="flip_30-patch"

--- linux-2.0.30/drivers/char/n_tty.c.old Mon Sep 2 08:18:26 1996
+++ linux-2.0.30/drivers/char/n_tty.c Mon Jul 21 17:47:39 1997
@@ -40,6 +40,9 @@

#define CONSOLE_DEV MKDEV(TTY_MAJOR,0)

+#define disable_flip(tty) (tty)->flip.disabled++;
+#define enable_flip(tty) (tty)->flip.disabled--;
+
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
@@ -859,9 +862,9 @@
while (1) {
int eol;

- disable_bh(TQUEUE_BH);
+ disable_flip(tty);
if (!tty->read_cnt) {
- enable_bh(TQUEUE_BH);
+ enable_flip(tty);
break;
}
eol = clear_bit(tty->read_tail,
@@ -870,7 +873,7 @@
tty->read_tail = ((tty->read_tail+1) &
(N_TTY_BUF_SIZE-1));
tty->read_cnt--;
- enable_bh(TQUEUE_BH);
+ enable_flip(tty);
if (!eol) {
put_user(c, b++);
if (--nr)
@@ -887,10 +890,10 @@
break;
}
} else {
- disable_bh(TQUEUE_BH);
+ disable_flip(tty);
copy_from_read_buf(tty, &b, &nr);
copy_from_read_buf(tty, &b, &nr);
- enable_bh(TQUEUE_BH);
+ enable_flip(tty);
}

/* If there is enough space in the read buffer now, let the
--- linux-2.0.30/drivers/char/tty_io.c.old Thu Oct 31 07:34:58 1996
+++ linux-2.0.30/drivers/char/tty_io.c Mon Jul 21 21:21:42 1997
@@ -1721,6 +1721,12 @@
char *fp;
int count;

+ /*
+ * Check the disabled count ...
+ */
+ if (tty->flip.disabled)
+ goto requeue;
+
if (tty->flip.buf_num) {
cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
@@ -1747,6 +1753,14 @@
tty->max_flip_cnt = count;
#endif
tty->ldisc.receive_buf(tty, cp, fp, count);
+ return;
+
+ /*
+ * Requeue immediately for the next tick.
+ */
+requeue:
+ queue_task(&tty->flip.tqueue, &tq_timer);
+ return;
}

/*
--- linux-2.0.30/include/linux/tty.h.old Sun Apr 27 16:22:13 1997
+++ linux-2.0.30/include/linux/tty.h Mon Jul 21 17:44:17 1997
@@ -96,6 +96,7 @@
unsigned char *flag_buf_ptr;
int count;
int buf_num;
+ int disabled;
};

/*

--------------5893C146C8EE01ED60B46D6D--