lkml.org 
[lkml]   [2003]   [Jan]   [13]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
DateSun, 12 Jan 2003 22:23:00 -0800
FromGreg KH <>
SubjectRe: any chance of 2.6.0-test*?
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/
\
 
 \ /
  Last update: 2005-03-22 12:32    [W:0.450 / U:0.060 seconds]
©2003-2008 Jasper Spaans