Re: any chance of 2.6.0-test*?

From: Greg KH (greg@kroah.com)
Date: Mon Jan 13 2003 - 01:23:00 EST


On Sun, Jan 12, 2003 at 11:15:52AM -0800, Linus Torvalds wrote:
>
> Anybody willing to test it and see if the above works?

Hm, I just did, and it seems to work for me. I ran a bunch of different
usb-serial drivers through some tests, but these worked for me without
this patch. I don't know what stress tests Alan was running to show up
a problem.

Anyway, here's a patch with your new lock, if you want to apply it.

thanks,

greg k-h

diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c
--- a/drivers/char/tty_io.c Sun Jan 12 22:27:42 2003
+++ b/drivers/char/tty_io.c Sun Jan 12 22:27:42 2003
@@ -159,6 +159,58 @@
 extern void tx3912_rs_init(void);
 extern void hvc_console_init(void);
 
+
+/*
+* This isn't even _trying_ to be fast!
+*/
+struct recursive_spinlock {
+ spinlock_t lock;
+ int lock_count;
+ struct task_struct *lock_owner;
+};
+
+static struct recursive_spinlock tty_lock = {
+ .lock = SPIN_LOCK_UNLOCKED,
+ .lock_count = 0,
+ .lock_owner = NULL
+};
+
+unsigned long tty_spin_lock(void)
+{
+ unsigned long flags;
+ struct task_struct *tsk;
+
+ local_irq_save(flags);
+ preempt_disable();
+ tsk = current;
+ if (spin_trylock(&tty_lock.lock))
+ goto got_lock;
+ if (tsk == tty_lock.lock_owner) {
+ WARN_ON(!tty_lock.lock_count);
+ tty_lock.lock_count++;
+ return flags;
+ }
+ spin_lock(&tty_lock.lock);
+got_lock:
+ WARN_ON(tty_lock.lock_owner);
+ WARN_ON(tty_lock.lock_count);
+ tty_lock.lock_owner = tsk;
+ tty_lock.lock_count = 1;
+ return flags;
+}
+
+void tty_spin_unlock(unsigned long flags)
+{
+ WARN_ON(tty_lock.lock_owner != current);
+ WARN_ON(!tty_lock.lock_count);
+ if (!--tty_lock.lock_count) {
+ tty_lock.lock_owner = NULL;
+ spin_unlock(&tty_lock.lock);
+ }
+ preempt_enable();
+ local_irq_restore(flags);
+}
+
 static struct tty_struct *alloc_tty_struct(void)
 {
         struct tty_struct *tty;
@@ -460,7 +512,7 @@
         {
                 unsigned long flags;
 
- local_irq_save(flags); // FIXME: is this safe?
+ flags = tty_spin_lock();
                 if (tty->ldisc.flush_buffer)
                         tty->ldisc.flush_buffer(tty);
                 if (tty->driver.flush_buffer)
@@ -468,7 +520,7 @@
                 if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
                     tty->ldisc.write_wakeup)
                         (tty->ldisc.write_wakeup)(tty);
- local_irq_restore(flags); // FIXME: is this safe?
+ tty_spin_unlock(flags);
         }
 
         wake_up_interruptible(&tty->write_wait);
@@ -1926,7 +1978,7 @@
                 fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
                 tty->flip.buf_num = 0;
 
- local_irq_save(flags); // FIXME: is this safe?
+ flags = tty_spin_lock();
                 tty->flip.char_buf_ptr = tty->flip.char_buf;
                 tty->flip.flag_buf_ptr = tty->flip.flag_buf;
         } else {
@@ -1934,13 +1986,13 @@
                 fp = tty->flip.flag_buf;
                 tty->flip.buf_num = 1;
 
- local_irq_save(flags); // FIXME: is this safe?
+ flags = tty_spin_lock();
                 tty->flip.char_buf_ptr = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
                 tty->flip.flag_buf_ptr = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
         }
         count = tty->flip.count;
         tty->flip.count = 0;
- local_irq_restore(flags); // FIXME: is this safe?
+ tty_spin_unlock(flags);
         
         tty->ldisc.receive_buf(tty, cp, fp, count);
 }
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Wed Jan 15 2003 - 22:00:44 EST