lkml.org 
[lkml]   [1999]   [Dec]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: TTY_FLIPBUF_SIZE too low causing dataloss on too fast serial lines?
On Fri, 28 May 1999, Theodore Y. Ts'o wrote:

> Date: Thu, 27 May 1999 00:15:03 +0200
> From: Pavel Machek <pavel@bug.ucw.cz>
...

> Is there some easy way for me to make it work 'just now'? Like calling
> tty_flip_buffer_push from some kind of bh or increasing hz to 1000 or
> ...?
>
> Well, you could set tty->low_latency and then call
> tty_flip_buffer_push(), which will force it out to the line discpline
> right away. Increasaing HZ to 1000 is also a possibility.

Here's a reposting of the fix I suggested in the spring.

-ben


--- kernel/softirq.c.orig Sun Mar 21 10:22:00 1999
+++ kernel/softirq.c Thu May 6 21:30:47 1999
@@ -26,45 +26,50 @@
void (*bh_base[32])(void);

/*
- * This needs to make sure that only one bottom half handler
- * is ever active at a time. We do this without locking by
- * doing an atomic increment on the intr_count, and checking
- * (nonatomically) against 1. Only if it's 1 do we schedule
- * the bottom half.
- *
- * Note that the non-atomicity of the test (as opposed to the
- * actual update) means that the test may fail, and _nobody_
- * runs the handlers if there is a race that makes multiple
- * CPU's get here at the same time. That's ok, we'll run them
- * next time around.
+ * Repeatedly run over the bottom halves until there are no more, but only run
+ * each bottom half at most once. If we don't loop, if one bottom half triggers
+ * another, it might get delayed a long time. If we loop indefinately, then the
+ * system will lock completely under a heavy irq load. -bcrl
*/
-static inline void run_bottom_halves(void)
-{
- unsigned long active;
- void (**bh)(void);
-
- active = get_active_bhs();
- clear_active_bhs(active);
- bh = bh_base;
- do {
- if (active & 1)
- (*bh)();
- bh++;
- active >>= 1;
- } while (active);
-}
-
asmlinkage void do_bottom_half(void)
{
int cpu = smp_processor_id();
+ unsigned long left = ~0UL;
+ unsigned long active;
+ void (**bh)(void);

+again:
if (softirq_trylock(cpu)) {
if (hardirq_trylock(cpu)) {
__sti();
- run_bottom_halves();
+
+ while ((active = left & get_active_bhs())) {
+ left &= ~active;
+ clear_active_bhs(active);
+ bh = bh_base;
+ do {
+ if (active & 1)
+ (*bh)();
+ bh++;
+ active >>= 1;
+ } while (active);
+ }
+
__cli();
hardirq_endlock(cpu);
+ softirq_endlock(cpu);
+
+ /*
+ * Avoid the race by checking if any bottom halves
+ * are active after releasing all locks. This is a
+ * rare race, but should inexpensive to check. -bcrl
+ */
+ rmb();
+ if (get_active_bhs() & left)
+ goto again;
+ return;
}
softirq_endlock(cpu);
}
}
+



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:55    [W:0.207 / U:0.108 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site