patch-2.1.115 linux/drivers/char/tty_io.c
Next file: linux/drivers/char/vt.c
Previous file: linux/drivers/char/stallion.c
Back to the patch index
Back to the overall index
- Lines: 163
- Date:
Thu Aug 6 02:29:45 1998
- Orig file:
v2.1.114/linux/drivers/char/tty_io.c
- Orig date:
Tue Jul 21 00:15:31 1998
diff -u --recursive --new-file v2.1.114/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
@@ -65,6 +65,7 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
+#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/devpts_fs.h>
#include <linux/file.h>
@@ -80,6 +81,7 @@
#include <linux/proc_fs.h>
#endif
#include <linux/init.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -107,6 +109,10 @@
struct tty_driver *tty_drivers = NULL; /* linked list of tty drivers */
struct tty_ldisc ldiscs[NR_LDISCS]; /* line disc dispatch table */
+#ifdef CONFIG_UNIX98_PTYS
+extern struct tty_driver ptm_driver[]; /* Unix98 pty masters; for /dev/ptmx */
+#endif
+
/*
* redirect is the pseudo-tty that console output
* is redirected to if asked by TIOCCONS.
@@ -371,17 +377,24 @@
NULL /* hung_up_tty_fasync */
};
+/*
+ * This can be called through the "tq_scheduler"
+ * task-list. That is process synchronous, but
+ * doesn't hold any locks, so we need to make
+ * sure we have the appropriate locks for what
+ * we're doing..
+ */
void do_tty_hangup(void *data)
{
struct tty_struct *tty = (struct tty_struct *) data;
struct file * filp;
struct task_struct *p;
- unsigned long flags;
if (!tty)
return;
-
- save_flags(flags); cli();
+
+ /* inuse_filps is protected by the single kernel lock */
+ lock_kernel();
check_tty_count(tty, "do_tty_hangup");
for (filp = inuse_filps; filp; filp = filp->f_next) {
@@ -400,13 +413,21 @@
filp->f_op = &hung_up_tty_fops;
}
- if (tty->ldisc.flush_buffer)
- tty->ldisc.flush_buffer(tty);
- if (tty->driver.flush_buffer)
- tty->driver.flush_buffer(tty);
- if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
- tty->ldisc.write_wakeup)
- (tty->ldisc.write_wakeup)(tty);
+ /* FIXME! What are the locking issues here? This may me overdoing things.. */
+ {
+ unsigned long flags;
+
+ save_flags(flags); cli();
+ if (tty->ldisc.flush_buffer)
+ tty->ldisc.flush_buffer(tty);
+ if (tty->driver.flush_buffer)
+ tty->driver.flush_buffer(tty);
+ if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+ restore_flags(flags);
+ }
+
wake_up_interruptible(&tty->write_wait);
wake_up_interruptible(&tty->read_wait);
@@ -449,7 +470,7 @@
tty->ctrl_status = 0;
if (tty->driver.hangup)
(tty->driver.hangup)(tty);
- restore_flags(flags);
+ unlock_kernel();
}
void tty_hangup(struct tty_struct * tty)
@@ -459,7 +480,7 @@
printk("%s hangup...\n", tty_name(tty, buf));
#endif
- queue_task(&tty->tq_hangup, &tq_timer);
+ queue_task(&tty->tq_hangup, &tq_scheduler);
}
void tty_vhangup(struct tty_struct * tty)
@@ -1158,6 +1179,7 @@
* Make sure that the tty's task queue isn't activated.
*/
run_task_queue(&tq_timer);
+ run_task_queue(&tq_scheduler);
/*
* The release_mem function takes care of the details of clearing
@@ -1213,34 +1235,33 @@
device = c->device(c);
noctty = 1;
}
+#ifdef CONFIG_UNIX98_PTYS
if (device == PTMX_DEV) {
/* find a free pty. */
- struct tty_driver *driver = tty_drivers;
- int minor, line;
+ int major, minor, line;
+ struct tty_driver *driver;
- /* find the pty driver */
- for (driver=tty_drivers; driver; driver=driver->next)
- if (driver->major == PTY_MASTER_MAJOR)
- break;
- if (!driver) return -ENODEV;
-
- /* find a minor device that is not in use. */
- for (minor=driver->minor_start;
- minor<driver->minor_start+driver->num;
- minor++) {
- device = MKDEV(driver->major, minor);
- retval = init_dev(device, &tty);
- if (retval==0) break; /* success! */
+ /* find a device that is not in use. */
+ retval = -1;
+ for ( major = 0 ; major < UNIX98_NR_MAJORS ; major++ ) {
+ driver = &ptm_driver[major];
+ for (minor = driver->minor_start ;
+ minor < driver->minor_start + driver->num ;
+ minor++) {
+ device = MKDEV(driver->major, minor);
+ if (!init_dev(device, &tty)) goto ptmx_found; /* ok! */
+ }
}
- if (minor==driver->minor_start+driver->num) /* no success */
- return -EIO; /* no free ptys */
-
+ return -EIO; /* no free ptys */
+ ptmx_found:
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
line = minor - driver->minor_start;
- devpts_pty_new(line, MKDEV(driver->other->major, line+driver->other->minor_start));
+ devpts_pty_new(line + major*NR_PTYS, MKDEV(driver->other->major,
+ line+driver->other->minor_start));
noctty = 1;
goto init_dev_done;
}
+#endif
retval = init_dev(device, &tty);
if (retval)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov